1#![no_std]
11
12extern crate alloc;
13use alloc::collections::BTreeSet;
14use alloc::{format, string::String};
15
16pub fn upper_bound_from_prefix(prefix: &str) -> Option<String> {
34 for i in (0..prefix.len()).rev() {
35 if let Some(last_char_str) = prefix.get(i..) {
36 let rest_of_prefix = {
37 debug_assert!(prefix.is_char_boundary(i));
38 &prefix[0..i]
39 };
40
41 let last_char = last_char_str
42 .chars()
43 .next()
44 .expect("last_char_str will contain at least one char");
45 let Some(last_char_incr) = (last_char..=char::MAX).nth(1) else {
46 continue;
49 };
50
51 let new_string = format!("{rest_of_prefix}{last_char_incr}");
52
53 return Some(new_string);
54 }
55 }
56
57 None
58}
59
60pub fn prefixed_set(mut set: BTreeSet<String>, prefix: &str) -> BTreeSet<String> {
62 let mut set = set.split_off(prefix);
63
64 if let Some(not_in_prefix) = upper_bound_from_prefix(prefix) {
65 set.split_off(¬_in_prefix);
66 }
67
68 set
69}
70
71#[cfg(test)]
72mod tests {
73
74 use alloc::string::ToString;
75
76 use super::*;
77
78 #[test]
79 fn it_works() {
80 let set = {
81 let mut set = BTreeSet::new();
82 set.insert("Hi".to_string());
83 set.insert("Hey".to_string());
84 set.insert("Hello".to_string());
85 set.insert("heyyy".to_string());
86 set.insert("".to_string());
87 set.insert("H".to_string());
88 set
89 };
90 let set = prefixed_set(set, "H");
91 assert_eq!(set.len(), 4);
92 assert!(!set.contains("heyyy"));
93 }
94
95 #[test]
96 fn maxicode() {
97 let set = {
98 let mut set = BTreeSet::new();
99 set.insert("Hi".to_string());
100 set.insert("Hey".to_string());
101 set.insert("Hello".to_string());
102 set.insert("heyyy".to_string());
103 set.insert("H\u{10FFFF}eyyy".to_string());
104 set.insert("H\u{10FFFF}".to_string());
105 set.insert("I".to_string());
106 set.insert("".to_string());
107 set.insert("H".to_string());
108 set
109 };
110 let set = prefixed_set(set, "H\u{10FFFF}");
111 assert_eq!(set.len(), 2);
112 assert!(!set.contains("I"));
113 }
114}