clean up valuesubkeyrangeseT

This commit is contained in:
John Smith 2023-06-27 18:26:53 -04:00
parent 291e3ef2fe
commit 73c37aa4ca
8 changed files with 80 additions and 44 deletions

View File

@ -4,7 +4,7 @@ use crate::storage_manager::SignedValueData;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RPCOperationValueChanged { pub struct RPCOperationValueChanged {
key: TypedKey, key: TypedKey,
subkeys: Vec<ValueSubkeyRange>, subkeys: ValueSubkeyRangeSet,
count: u32, count: u32,
value: SignedValueData, value: SignedValueData,
} }
@ -12,7 +12,7 @@ pub struct RPCOperationValueChanged {
impl RPCOperationValueChanged { impl RPCOperationValueChanged {
pub fn new( pub fn new(
key: TypedKey, key: TypedKey,
subkeys: Vec<ValueSubkeyRange>, subkeys: ValueSubkeyRangeSet,
count: u32, count: u32,
value: SignedValueData, value: SignedValueData,
) -> Self { ) -> Self {
@ -32,7 +32,7 @@ impl RPCOperationValueChanged {
pub fn key(&self) -> &TypedKey { pub fn key(&self) -> &TypedKey {
&self.key &self.key
} }
pub fn subkeys(&self) -> &[ValueSubkeyRange] { pub fn subkeys(&self) -> &ValueSubkeyRangeSet {
&self.subkeys &self.subkeys
} }
pub fn count(&self) -> u32 { pub fn count(&self) -> u32 {
@ -41,7 +41,7 @@ impl RPCOperationValueChanged {
pub fn value(&self) -> &SignedValueData { pub fn value(&self) -> &SignedValueData {
&self.value &self.value
} }
pub fn destructure(self) -> (TypedKey, Vec<ValueSubkeyRange>, u32, SignedValueData) { pub fn destructure(self) -> (TypedKey, ValueSubkeyRangeSet, u32, SignedValueData) {
(self.key, self.subkeys, self.count, self.value) (self.key, self.subkeys, self.count, self.value)
} }
@ -52,25 +52,20 @@ impl RPCOperationValueChanged {
let key = decode_typed_key(&k_reader)?; let key = decode_typed_key(&k_reader)?;
let sk_reader = reader.get_subkeys().map_err(RPCError::protocol)?; let sk_reader = reader.get_subkeys().map_err(RPCError::protocol)?;
let mut subkeys = Vec::<ValueSubkeyRange>::with_capacity( let mut subkeys = ValueSubkeyRangeSet::new();
sk_reader
.len()
.try_into()
.map_err(RPCError::map_protocol("too many subkey ranges"))?,
);
for skr in sk_reader.iter() { for skr in sk_reader.iter() {
let vskr = (skr.get_start(), skr.get_end()); let vskr = (skr.get_start(), skr.get_end());
if vskr.0 > vskr.1 { if vskr.0 > vskr.1 {
return Err(RPCError::protocol("invalid subkey range")); return Err(RPCError::protocol("invalid subkey range"));
} }
if let Some(lvskr) = subkeys.last() { if let Some(lvskr) = subkeys.last() {
if lvskr.1 >= vskr.0 { if lvskr >= vskr.0 {
return Err(RPCError::protocol( return Err(RPCError::protocol(
"subkey range out of order or not merged", "subkey range out of order or not merged",
)); ));
} }
} }
subkeys.push(vskr); subkeys.ranges_insert(vskr.0..=vskr.1);
} }
let count = reader.get_count(); let count = reader.get_count();
let v_reader = reader.get_value().map_err(RPCError::protocol)?; let v_reader = reader.get_value().map_err(RPCError::protocol)?;
@ -91,14 +86,14 @@ impl RPCOperationValueChanged {
let mut sk_builder = builder.reborrow().init_subkeys( let mut sk_builder = builder.reborrow().init_subkeys(
self.subkeys self.subkeys
.len() .ranges_len()
.try_into() .try_into()
.map_err(RPCError::map_internal("invalid subkey range list length"))?, .map_err(RPCError::map_internal("invalid subkey range list length"))?,
); );
for (i, skr) in self.subkeys.iter().enumerate() { for (i, skr) in self.subkeys.ranges().enumerate() {
let mut skr_builder = sk_builder.reborrow().get(i as u32); let mut skr_builder = sk_builder.reborrow().get(i as u32);
skr_builder.set_start(skr.0); skr_builder.set_start(*skr.start());
skr_builder.set_end(skr.1); skr_builder.set_end(*skr.end());
} }
builder.set_count(self.count); builder.set_count(self.count);

View File

@ -6,7 +6,7 @@ const MAX_WATCH_VALUE_A_PEERS_LEN: usize = 20;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RPCOperationWatchValueQ { pub struct RPCOperationWatchValueQ {
key: TypedKey, key: TypedKey,
subkeys: Vec<ValueSubkeyRange>, subkeys: ValueSubkeyRangeSet,
expiration: u64, expiration: u64,
count: u32, count: u32,
watcher: PublicKey, watcher: PublicKey,
@ -16,7 +16,7 @@ pub struct RPCOperationWatchValueQ {
impl RPCOperationWatchValueQ { impl RPCOperationWatchValueQ {
pub fn new( pub fn new(
key: TypedKey, key: TypedKey,
subkeys: Vec<ValueSubkeyRange>, subkeys: ValueSubkeyRangeSet,
expiration: u64, expiration: u64,
count: u32, count: u32,
watcher: PublicKey, watcher: PublicKey,
@ -41,9 +41,9 @@ impl RPCOperationWatchValueQ {
Vec::with_capacity(PUBLIC_KEY_LENGTH + 4 + (self.subkeys.len() * 8) + 8 + 4); Vec::with_capacity(PUBLIC_KEY_LENGTH + 4 + (self.subkeys.len() * 8) + 8 + 4);
sig_data.extend_from_slice(&self.key.kind.0); sig_data.extend_from_slice(&self.key.kind.0);
sig_data.extend_from_slice(&self.key.value.bytes); sig_data.extend_from_slice(&self.key.value.bytes);
for sk in &self.subkeys { for sk in self.subkeys.ranges() {
sig_data.extend_from_slice(&sk.0.to_le_bytes()); sig_data.extend_from_slice(&sk.start().to_le_bytes());
sig_data.extend_from_slice(&sk.1.to_le_bytes()); sig_data.extend_from_slice(&sk.end().to_le_bytes());
} }
sig_data.extend_from_slice(&self.expiration.to_le_bytes()); sig_data.extend_from_slice(&self.expiration.to_le_bytes());
sig_data.extend_from_slice(&self.count.to_le_bytes()); sig_data.extend_from_slice(&self.count.to_le_bytes());
@ -66,7 +66,7 @@ impl RPCOperationWatchValueQ {
pub fn key(&self) -> &TypedKey { pub fn key(&self) -> &TypedKey {
&self.key &self.key
} }
pub fn subkeys(&self) -> &[ValueSubkeyRange] { pub fn subkeys(&self) -> &ValueSubkeyRangeSet {
&self.subkeys &self.subkeys
} }
pub fn expiration(&self) -> u64 { pub fn expiration(&self) -> u64 {
@ -86,7 +86,7 @@ impl RPCOperationWatchValueQ {
self, self,
) -> ( ) -> (
TypedKey, TypedKey,
Vec<ValueSubkeyRange>, ValueSubkeyRangeSet,
u64, u64,
u32, u32,
PublicKey, PublicKey,
@ -112,25 +112,20 @@ impl RPCOperationWatchValueQ {
if sk_reader.len() as usize > MAX_WATCH_VALUE_Q_SUBKEYS_LEN { if sk_reader.len() as usize > MAX_WATCH_VALUE_Q_SUBKEYS_LEN {
return Err(RPCError::protocol("WatchValueQ subkeys length too long")); return Err(RPCError::protocol("WatchValueQ subkeys length too long"));
} }
let mut subkeys = Vec::<ValueSubkeyRange>::with_capacity( let mut subkeys = ValueSubkeyRangeSet::new();
sk_reader
.len()
.try_into()
.map_err(RPCError::map_protocol("too many subkey ranges"))?,
);
for skr in sk_reader.iter() { for skr in sk_reader.iter() {
let vskr = (skr.get_start(), skr.get_end()); let vskr = (skr.get_start(), skr.get_end());
if vskr.0 > vskr.1 { if vskr.0 > vskr.1 {
return Err(RPCError::protocol("invalid subkey range")); return Err(RPCError::protocol("invalid subkey range"));
} }
if let Some(lvskr) = subkeys.last() { if let Some(lvskr) = subkeys.last() {
if lvskr.1 >= vskr.0 { if lvskr >= vskr.0 {
return Err(RPCError::protocol( return Err(RPCError::protocol(
"subkey range out of order or not merged", "subkey range out of order or not merged",
)); ));
} }
} }
subkeys.push(vskr); subkeys.ranges_insert(vskr.0..=vskr.1);
} }
let expiration = reader.get_expiration(); let expiration = reader.get_expiration();
@ -165,10 +160,10 @@ impl RPCOperationWatchValueQ {
.try_into() .try_into()
.map_err(RPCError::map_internal("invalid subkey range list length"))?, .map_err(RPCError::map_internal("invalid subkey range list length"))?,
); );
for (i, skr) in self.subkeys.iter().enumerate() { for (i, skr) in self.subkeys.ranges().enumerate() {
let mut skr_builder = sk_builder.reborrow().get(i as u32); let mut skr_builder = sk_builder.reborrow().get(i as u32);
skr_builder.set_start(skr.0); skr_builder.set_start(*skr.start());
skr_builder.set_end(skr.1); skr_builder.set_end(*skr.end());
} }
builder.set_expiration(self.expiration); builder.set_expiration(self.expiration);
builder.set_count(self.count); builder.set_count(self.count);

View File

@ -31,6 +31,14 @@ fn get_string(text: &str) -> Option<String> {
Some(text.to_owned()) Some(text.to_owned())
} }
fn get_subkeys(text: &str) -> Option<ValueSubkeyRangeSet> {
if let Some(n) = get_number(text) {
Some(ValueSubkeyRangeSet::single(n.try_into().ok()?))
} else {
ValueSubkeyRangeSet::from_str(text).ok()
}
}
fn get_route_id( fn get_route_id(
rss: RouteSpecStore, rss: RouteSpecStore,
allow_allocated: bool, allow_allocated: bool,
@ -902,7 +910,7 @@ impl VeilidAPI {
} }
async fn debug_record_purge(&self, args: Vec<String>) -> VeilidAPIResult<String> { async fn debug_record_purge(&self, args: Vec<String>) -> VeilidAPIResult<String> {
// <local|remote> // <local|remote> [bytes]
let storage_manager = self.storage_manager()?; let storage_manager = self.storage_manager()?;
let scope = get_debug_argument_at(&args, 1, "debug_record_purge", "scope", get_string)?; let scope = get_debug_argument_at(&args, 1, "debug_record_purge", "scope", get_string)?;
@ -914,6 +922,17 @@ impl VeilidAPI {
}; };
return Ok(out); return Ok(out);
} }
async fn debug_record_get(&self, args: Vec<String>) -> VeilidAPIResult<String> {
let storage_manager = self.storage_manager()?;
let key = get_debug_argument_at(&args, 1, "debug_record_get", "key", get_typed_key)?;
let subkeys =
get_debug_argument_at(&args, 2, "debug_record_subkeys", "subkeys", get_string)?;
// let rc = self.routing_context();
return Ok("TODO");
}
async fn debug_record(&self, args: String) -> VeilidAPIResult<String> { async fn debug_record(&self, args: String) -> VeilidAPIResult<String> {
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect(); let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
@ -924,6 +943,8 @@ impl VeilidAPI {
self.debug_record_list(args).await self.debug_record_list(args).await
} else if command == "purge" { } else if command == "purge" {
self.debug_record_purge(args).await self.debug_record_purge(args).await
} else if command == "get" {
self.debug_record_get(args).await
} else { } else {
Ok(">>> Unknown command\n".to_owned()) Ok(">>> Unknown command\n".to_owned())
} }
@ -954,6 +975,7 @@ impl VeilidAPI {
test <route> test <route>
record list <local|remote> record list <local|remote>
purge <local|remote> [bytes] purge <local|remote> [bytes]
get <key> <subkeys>
<destination> is: <destination> is:
* direct: <node>[+<safety>][<modifiers>] * direct: <node>[+<safety>][<modifiers>]
@ -966,6 +988,9 @@ impl VeilidAPI {
<protocoltype> is: udp|tcp|ws|wss <protocoltype> is: udp|tcp|ws|wss
<addresstype> is: ipv4|ipv6 <addresstype> is: ipv4|ipv6
<routingdomain> is: public|local <routingdomain> is: public|local
<subkeys> is:
* a number: 2
* a comma-separated inclusive range list: 1..=3,5..=8
"# "#
.to_owned()) .to_owned())
} }

View File

@ -12,7 +12,5 @@ pub use value_subkey_range_set::*;
/// Value subkey /// Value subkey
pub type ValueSubkey = u32; pub type ValueSubkey = u32;
/// Value subkey range
pub type ValueSubkeyRange = (u32, u32);
/// Value sequence number /// Value sequence number
pub type ValueSeqNum = u32; pub type ValueSeqNum = u32;

View File

@ -41,6 +41,28 @@ impl ValueSubkeyRangeSet {
} }
} }
impl FromStr for ValueSubkeyRangeSet {
type Err = VeilidAPIError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
let mut data = RangeSetBlaze::<ValueSubkey>::new();
for r in value.split(",") {
let r = r.trim();
let Some((ss, es)) = r.split_once("..=") else {
return Err(VeilidAPIError::parse_error("can not parse ValueSubkeyRangeSet", r));
};
let sn = ValueSubkey::from_str(ss)
.map_err(|e| VeilidAPIError::parse_error("could not parse ValueSubkey", e))?;
let en = ValueSubkey::from_str(es)
.map_err(|e| VeilidAPIError::parse_error("could not parse ValueSubkey", e))?;
data.ranges_insert(sn..=en);
}
Ok(ValueSubkeyRangeSet { data })
}
}
impl Deref for ValueSubkeyRangeSet { impl Deref for ValueSubkeyRangeSet {
type Target = RangeSetBlaze<ValueSubkey>; type Target = RangeSetBlaze<ValueSubkey>;

View File

@ -266,7 +266,7 @@ abstract class VeilidRoutingContext {
Future<void> deleteDHTRecord(TypedKey key); Future<void> deleteDHTRecord(TypedKey key);
Future<ValueData?> getDHTValue(TypedKey key, int subkey, bool forceRefresh); Future<ValueData?> getDHTValue(TypedKey key, int subkey, bool forceRefresh);
Future<ValueData?> setDHTValue(TypedKey key, int subkey, Uint8List data); Future<ValueData?> setDHTValue(TypedKey key, int subkey, Uint8List data);
Future<Timestamp> watchDHTValues( Future<Timestamp> watchDHTValues(TypedKey key, List<ValueSubkeyRange> subkeys,
TypedKey key, ValueSubkeyRange subkeys, Timestamp expiration, int count); Timestamp expiration, int count);
Future<bool> cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys); Future<bool> cancelDHTWatch(TypedKey key, List<ValueSubkeyRange> subkeys);
} }

View File

@ -710,7 +710,7 @@ class VeilidRoutingContextFFI implements VeilidRoutingContext {
} }
@override @override
Future<Timestamp> watchDHTValues(TypedKey key, ValueSubkeyRange subkeys, Future<Timestamp> watchDHTValues(TypedKey key, List<ValueSubkeyRange> subkeys,
Timestamp expiration, int count) async { Timestamp expiration, int count) async {
final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeKey = jsonEncode(key).toNativeUtf8();
final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8(); final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8();
@ -726,7 +726,8 @@ class VeilidRoutingContextFFI implements VeilidRoutingContext {
} }
@override @override
Future<bool> cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys) async { Future<bool> cancelDHTWatch(
TypedKey key, List<ValueSubkeyRange> subkeys) async {
final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeKey = jsonEncode(key).toNativeUtf8();
final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8(); final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8();

View File

@ -129,7 +129,7 @@ class VeilidRoutingContextJS implements VeilidRoutingContext {
} }
@override @override
Future<Timestamp> watchDHTValues(TypedKey key, ValueSubkeyRange subkeys, Future<Timestamp> watchDHTValues(TypedKey key, List<ValueSubkeyRange> subkeys,
Timestamp expiration, int count) async { Timestamp expiration, int count) async {
final ts = await _wrapApiPromise(js_util.callMethod( final ts = await _wrapApiPromise(js_util.callMethod(
wasm, "routing_context_watch_dht_values", [ wasm, "routing_context_watch_dht_values", [
@ -143,7 +143,7 @@ class VeilidRoutingContextJS implements VeilidRoutingContext {
} }
@override @override
Future<bool> cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys) { Future<bool> cancelDHTWatch(TypedKey key, List<ValueSubkeyRange> subkeys) {
return _wrapApiPromise(js_util.callMethod( return _wrapApiPromise(js_util.callMethod(
wasm, wasm,
"routing_context_cancel_dht_watch", "routing_context_cancel_dht_watch",