From 73c37aa4ca68ebae9eefe84dfc350ed8ca2fab1e Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 27 Jun 2023 18:26:53 -0400 Subject: [PATCH] clean up valuesubkeyrangeseT --- .../operations/operation_value_changed.rs | 27 +++++++--------- .../operations/operation_watch_value.rs | 31 ++++++++----------- veilid-core/src/veilid_api/debug.rs | 27 +++++++++++++++- veilid-core/src/veilid_api/types/dht/mod.rs | 2 -- .../types/dht/value_subkey_range_set.rs | 22 +++++++++++++ veilid-flutter/lib/routing_context.dart | 6 ++-- veilid-flutter/lib/veilid_ffi.dart | 5 +-- veilid-flutter/lib/veilid_js.dart | 4 +-- 8 files changed, 80 insertions(+), 44 deletions(-) diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs b/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs index d7a815a2..b138d884 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs @@ -4,7 +4,7 @@ use crate::storage_manager::SignedValueData; #[derive(Debug, Clone)] pub struct RPCOperationValueChanged { key: TypedKey, - subkeys: Vec, + subkeys: ValueSubkeyRangeSet, count: u32, value: SignedValueData, } @@ -12,7 +12,7 @@ pub struct RPCOperationValueChanged { impl RPCOperationValueChanged { pub fn new( key: TypedKey, - subkeys: Vec, + subkeys: ValueSubkeyRangeSet, count: u32, value: SignedValueData, ) -> Self { @@ -32,7 +32,7 @@ impl RPCOperationValueChanged { pub fn key(&self) -> &TypedKey { &self.key } - pub fn subkeys(&self) -> &[ValueSubkeyRange] { + pub fn subkeys(&self) -> &ValueSubkeyRangeSet { &self.subkeys } pub fn count(&self) -> u32 { @@ -41,7 +41,7 @@ impl RPCOperationValueChanged { pub fn value(&self) -> &SignedValueData { &self.value } - pub fn destructure(self) -> (TypedKey, Vec, u32, SignedValueData) { + pub fn destructure(self) -> (TypedKey, ValueSubkeyRangeSet, u32, SignedValueData) { (self.key, self.subkeys, self.count, self.value) } @@ -52,25 +52,20 @@ impl RPCOperationValueChanged { let key = decode_typed_key(&k_reader)?; let sk_reader = reader.get_subkeys().map_err(RPCError::protocol)?; - let mut subkeys = Vec::::with_capacity( - sk_reader - .len() - .try_into() - .map_err(RPCError::map_protocol("too many subkey ranges"))?, - ); + let mut subkeys = ValueSubkeyRangeSet::new(); for skr in sk_reader.iter() { let vskr = (skr.get_start(), skr.get_end()); if vskr.0 > vskr.1 { return Err(RPCError::protocol("invalid subkey range")); } if let Some(lvskr) = subkeys.last() { - if lvskr.1 >= vskr.0 { + if lvskr >= vskr.0 { return Err(RPCError::protocol( "subkey range out of order or not merged", )); } } - subkeys.push(vskr); + subkeys.ranges_insert(vskr.0..=vskr.1); } let count = reader.get_count(); let v_reader = reader.get_value().map_err(RPCError::protocol)?; @@ -91,14 +86,14 @@ impl RPCOperationValueChanged { let mut sk_builder = builder.reborrow().init_subkeys( self.subkeys - .len() + .ranges_len() .try_into() .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); - skr_builder.set_start(skr.0); - skr_builder.set_end(skr.1); + skr_builder.set_start(*skr.start()); + skr_builder.set_end(*skr.end()); } builder.set_count(self.count); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs b/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs index 9da63df7..d2aefa79 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs @@ -6,7 +6,7 @@ const MAX_WATCH_VALUE_A_PEERS_LEN: usize = 20; #[derive(Debug, Clone)] pub struct RPCOperationWatchValueQ { key: TypedKey, - subkeys: Vec, + subkeys: ValueSubkeyRangeSet, expiration: u64, count: u32, watcher: PublicKey, @@ -16,7 +16,7 @@ pub struct RPCOperationWatchValueQ { impl RPCOperationWatchValueQ { pub fn new( key: TypedKey, - subkeys: Vec, + subkeys: ValueSubkeyRangeSet, expiration: u64, count: u32, watcher: PublicKey, @@ -41,9 +41,9 @@ impl RPCOperationWatchValueQ { 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.value.bytes); - for sk in &self.subkeys { - sig_data.extend_from_slice(&sk.0.to_le_bytes()); - sig_data.extend_from_slice(&sk.1.to_le_bytes()); + for sk in self.subkeys.ranges() { + sig_data.extend_from_slice(&sk.start().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.count.to_le_bytes()); @@ -66,7 +66,7 @@ impl RPCOperationWatchValueQ { pub fn key(&self) -> &TypedKey { &self.key } - pub fn subkeys(&self) -> &[ValueSubkeyRange] { + pub fn subkeys(&self) -> &ValueSubkeyRangeSet { &self.subkeys } pub fn expiration(&self) -> u64 { @@ -86,7 +86,7 @@ impl RPCOperationWatchValueQ { self, ) -> ( TypedKey, - Vec, + ValueSubkeyRangeSet, u64, u32, PublicKey, @@ -112,25 +112,20 @@ impl RPCOperationWatchValueQ { if sk_reader.len() as usize > MAX_WATCH_VALUE_Q_SUBKEYS_LEN { return Err(RPCError::protocol("WatchValueQ subkeys length too long")); } - let mut subkeys = Vec::::with_capacity( - sk_reader - .len() - .try_into() - .map_err(RPCError::map_protocol("too many subkey ranges"))?, - ); + let mut subkeys = ValueSubkeyRangeSet::new(); for skr in sk_reader.iter() { let vskr = (skr.get_start(), skr.get_end()); if vskr.0 > vskr.1 { return Err(RPCError::protocol("invalid subkey range")); } if let Some(lvskr) = subkeys.last() { - if lvskr.1 >= vskr.0 { + if lvskr >= vskr.0 { return Err(RPCError::protocol( "subkey range out of order or not merged", )); } } - subkeys.push(vskr); + subkeys.ranges_insert(vskr.0..=vskr.1); } let expiration = reader.get_expiration(); @@ -165,10 +160,10 @@ impl RPCOperationWatchValueQ { .try_into() .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); - skr_builder.set_start(skr.0); - skr_builder.set_end(skr.1); + skr_builder.set_start(*skr.start()); + skr_builder.set_end(*skr.end()); } builder.set_expiration(self.expiration); builder.set_count(self.count); diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 5b86a98c..8de6ca34 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -31,6 +31,14 @@ fn get_string(text: &str) -> Option { Some(text.to_owned()) } +fn get_subkeys(text: &str) -> Option { + if let Some(n) = get_number(text) { + Some(ValueSubkeyRangeSet::single(n.try_into().ok()?)) + } else { + ValueSubkeyRangeSet::from_str(text).ok() + } +} + fn get_route_id( rss: RouteSpecStore, allow_allocated: bool, @@ -902,7 +910,7 @@ impl VeilidAPI { } async fn debug_record_purge(&self, args: Vec) -> VeilidAPIResult { - // + // [bytes] let storage_manager = self.storage_manager()?; let scope = get_debug_argument_at(&args, 1, "debug_record_purge", "scope", get_string)?; @@ -914,6 +922,17 @@ impl VeilidAPI { }; return Ok(out); } + async fn debug_record_get(&self, args: Vec) -> VeilidAPIResult { + 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 { let args: Vec = args.split_whitespace().map(|s| s.to_owned()).collect(); @@ -924,6 +943,8 @@ impl VeilidAPI { self.debug_record_list(args).await } else if command == "purge" { self.debug_record_purge(args).await + } else if command == "get" { + self.debug_record_get(args).await } else { Ok(">>> Unknown command\n".to_owned()) } @@ -954,6 +975,7 @@ impl VeilidAPI { test record list purge [bytes] + get is: * direct: [+][] @@ -966,6 +988,9 @@ impl VeilidAPI { is: udp|tcp|ws|wss is: ipv4|ipv6 is: public|local + is: + * a number: 2 + * a comma-separated inclusive range list: 1..=3,5..=8 "# .to_owned()) } diff --git a/veilid-core/src/veilid_api/types/dht/mod.rs b/veilid-core/src/veilid_api/types/dht/mod.rs index 3a830b47..8b757907 100644 --- a/veilid-core/src/veilid_api/types/dht/mod.rs +++ b/veilid-core/src/veilid_api/types/dht/mod.rs @@ -12,7 +12,5 @@ pub use value_subkey_range_set::*; /// Value subkey pub type ValueSubkey = u32; -/// Value subkey range -pub type ValueSubkeyRange = (u32, u32); /// Value sequence number pub type ValueSeqNum = u32; diff --git a/veilid-core/src/veilid_api/types/dht/value_subkey_range_set.rs b/veilid-core/src/veilid_api/types/dht/value_subkey_range_set.rs index 68298f37..241223c1 100644 --- a/veilid-core/src/veilid_api/types/dht/value_subkey_range_set.rs +++ b/veilid-core/src/veilid_api/types/dht/value_subkey_range_set.rs @@ -41,6 +41,28 @@ impl ValueSubkeyRangeSet { } } +impl FromStr for ValueSubkeyRangeSet { + type Err = VeilidAPIError; + + fn from_str(value: &str) -> Result { + let mut data = RangeSetBlaze::::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 { type Target = RangeSetBlaze; diff --git a/veilid-flutter/lib/routing_context.dart b/veilid-flutter/lib/routing_context.dart index 39956503..ec547f56 100644 --- a/veilid-flutter/lib/routing_context.dart +++ b/veilid-flutter/lib/routing_context.dart @@ -266,7 +266,7 @@ abstract class VeilidRoutingContext { Future deleteDHTRecord(TypedKey key); Future getDHTValue(TypedKey key, int subkey, bool forceRefresh); Future setDHTValue(TypedKey key, int subkey, Uint8List data); - Future watchDHTValues( - TypedKey key, ValueSubkeyRange subkeys, Timestamp expiration, int count); - Future cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys); + Future watchDHTValues(TypedKey key, List subkeys, + Timestamp expiration, int count); + Future cancelDHTWatch(TypedKey key, List subkeys); } diff --git a/veilid-flutter/lib/veilid_ffi.dart b/veilid-flutter/lib/veilid_ffi.dart index f39773e8..1bf46e84 100644 --- a/veilid-flutter/lib/veilid_ffi.dart +++ b/veilid-flutter/lib/veilid_ffi.dart @@ -710,7 +710,7 @@ class VeilidRoutingContextFFI implements VeilidRoutingContext { } @override - Future watchDHTValues(TypedKey key, ValueSubkeyRange subkeys, + Future watchDHTValues(TypedKey key, List subkeys, Timestamp expiration, int count) async { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8(); @@ -726,7 +726,8 @@ class VeilidRoutingContextFFI implements VeilidRoutingContext { } @override - Future cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys) async { + Future cancelDHTWatch( + TypedKey key, List subkeys) async { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8(); diff --git a/veilid-flutter/lib/veilid_js.dart b/veilid-flutter/lib/veilid_js.dart index f1c5f84b..08a88140 100644 --- a/veilid-flutter/lib/veilid_js.dart +++ b/veilid-flutter/lib/veilid_js.dart @@ -129,7 +129,7 @@ class VeilidRoutingContextJS implements VeilidRoutingContext { } @override - Future watchDHTValues(TypedKey key, ValueSubkeyRange subkeys, + Future watchDHTValues(TypedKey key, List subkeys, Timestamp expiration, int count) async { final ts = await _wrapApiPromise(js_util.callMethod( wasm, "routing_context_watch_dht_values", [ @@ -143,7 +143,7 @@ class VeilidRoutingContextJS implements VeilidRoutingContext { } @override - Future cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys) { + Future cancelDHTWatch(TypedKey key, List subkeys) { return _wrapApiPromise(js_util.callMethod( wasm, "routing_context_cancel_dht_watch",