+6
ufos/src/lib.rs
+6
ufos/src/lib.rs
···
303
303
#[derive(Debug, Serialize, JsonSchema)]
304
304
pub struct NsidPrefix(String);
305
305
impl NsidPrefix {
306
+
/// Input must not include a trailing dot.
306
307
pub fn new(pre: &str) -> EncodingResult<Self> {
307
308
// it's a valid prefix if appending `.name` makes it a valid NSID
308
309
Nsid::new(format!("{pre}.name")).map_err(EncodingError::BadAtriumStringType)?;
···
319
320
);
320
321
self.0 == other.domain_authority()
321
322
}
323
+
/// The prefix as initialized (no trailing dot)
322
324
pub fn as_str(&self) -> &str {
323
325
self.0.as_str()
326
+
}
327
+
/// The prefix with a trailing `.` appended to avoid matching a longer segment
328
+
pub fn terminated(&self) -> String {
329
+
format!("{}.", self.0)
324
330
}
325
331
}
326
332
+6
-18
ufos/src/storage_fjall.rs
+6
-18
ufos/src/storage_fjall.rs
···
665
665
cursor: Option<Vec<u8>>,
666
666
buckets: Vec<CursorBucket>,
667
667
) -> StorageResult<(JustCount, Vec<PrefixChild>, Option<Vec<u8>>)> {
668
-
// TODO: fix up this mess
669
-
// the lower/start bound is tricky because `Exclusive()` _without_ a null terminator _will_ include the null-
670
-
// terminated exact match. so we actually need the null terminator for an exclusive lower bound!
671
-
//
672
-
// but for upper/end bound, we *cannot* have a null terminator after the prefix, else we'll only get everything up
673
-
// until prefix+null (aka nothing).
674
-
// anywayyyyyyyy
675
-
let prefix_sub_with_null = prefix.as_str().to_string().to_db_bytes()?;
676
-
let prefix_sub = String::sub_prefix(prefix.as_str())?;
668
+
// let prefix_sub_with_null = prefix.as_str().to_string().to_db_bytes()?;
669
+
let prefix_sub = String::sub_prefix(&prefix.terminated())?; // with trailing dot to ensure full segment match
677
670
let cursor_child = cursor
678
671
.as_deref()
679
672
.map(|encoded_bytes| {
680
673
let decoded: String = db_complete(encoded_bytes)?;
674
+
// TODO: write some tests for cursors, there's probably bugs here
681
675
let as_sub_prefix_with_null = decoded.to_db_bytes()?;
682
676
Ok::<_, EncodingError>(as_sub_prefix_with_null)
683
677
})
···
689
683
let start = cursor_child
690
684
.as_ref()
691
685
.map(|child| HourlyRollupKey::after_nsid_prefix(*t, child))
692
-
.unwrap_or_else(|| {
693
-
HourlyRollupKey::after_nsid_prefix(*t, &prefix_sub_with_null)
694
-
})?;
686
+
.unwrap_or_else(|| HourlyRollupKey::after_nsid_prefix(*t, &prefix_sub))?;
695
687
let end = HourlyRollupKey::nsid_prefix_end(*t, &prefix_sub)?;
696
688
get_lexi_iter::<HourlyRollupKey>(&snapshot, start, end)?
697
689
}
···
699
691
let start = cursor_child
700
692
.as_ref()
701
693
.map(|child| WeeklyRollupKey::after_nsid_prefix(*t, child))
702
-
.unwrap_or_else(|| {
703
-
WeeklyRollupKey::after_nsid_prefix(*t, &prefix_sub_with_null)
704
-
})?;
694
+
.unwrap_or_else(|| WeeklyRollupKey::after_nsid_prefix(*t, &prefix_sub))?;
705
695
let end = WeeklyRollupKey::nsid_prefix_end(*t, &prefix_sub)?;
706
696
get_lexi_iter::<WeeklyRollupKey>(&snapshot, start, end)?
707
697
}
···
709
699
let start = cursor_child
710
700
.as_ref()
711
701
.map(|child| AllTimeRollupKey::after_nsid_prefix(child))
712
-
.unwrap_or_else(|| {
713
-
AllTimeRollupKey::after_nsid_prefix(&prefix_sub_with_null)
714
-
})?;
702
+
.unwrap_or_else(|| AllTimeRollupKey::after_nsid_prefix(&prefix_sub))?;
715
703
let end = AllTimeRollupKey::nsid_prefix_end(&prefix_sub)?;
716
704
get_lexi_iter::<AllTimeRollupKey>(&snapshot, start, end)?
717
705
}