-
Notifications
You must be signed in to change notification settings - Fork 174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ZeroTrie probe function for stepwise iteration. #4725
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -222,6 +222,97 @@ impl<'a> ZeroTrieSimpleAsciiCursor<'a> { | |
reader::take_value(&mut self.trie.store) | ||
} | ||
|
||
/// Probes the next byte in the cursor, stepping the cursor and returning the byte. | ||
/// | ||
/// This function is similar to [`Self::step()`], but it takes an index instead of a char. | ||
/// This enables stepwise iteration over the contents of the trie. | ||
/// | ||
/// If there are multiple possibilities for the next byte, the `index` argument allows | ||
/// visiting them in order. Since this function steps the cursor, the cursor must be | ||
/// cloned (a cheap operation) in order to visit multiple children. | ||
/// | ||
/// # Examples | ||
/// | ||
/// Continually query index 0 to extract the first item from a trie: | ||
/// | ||
/// ``` | ||
/// use zerotrie::ZeroTrieSimpleAscii; | ||
/// | ||
/// let data: &[(String, usize)] = &[ | ||
/// ("ab".to_string(), 111), | ||
/// ("abc".to_string(), 22), | ||
/// ("abde".to_string(), 333), | ||
/// ("afg".to_string(), 44), | ||
/// ]; | ||
/// | ||
/// let trie: ZeroTrieSimpleAscii<Vec<u8>> = | ||
/// data.iter().map(|(s, v)| (s.as_str(), *v)).collect(); | ||
/// | ||
/// let mut cursor = trie.cursor(); | ||
/// let mut key = String::new(); | ||
/// let value = loop { | ||
/// if let Some(value) = cursor.take_value() { | ||
/// break value; | ||
/// } | ||
/// let ch = cursor.probe(0).unwrap(); | ||
/// key.push(char::from(ch)); | ||
/// }; | ||
/// | ||
/// assert_eq!(key, "ab"); | ||
/// assert_eq!(value, 111); | ||
/// ``` | ||
/// | ||
/// Stepwise iterate over all entries in the trie: | ||
/// | ||
/// ``` | ||
/// # use zerotrie::ZeroTrieSimpleAscii; | ||
/// # let data: &[(String, usize)] = &[ | ||
/// # ("ab".to_string(), 111), | ||
/// # ("abc".to_string(), 22), | ||
/// # ("abde".to_string(), 333), | ||
/// # ("afg".to_string(), 44) | ||
/// # ]; | ||
/// # let trie: ZeroTrieSimpleAscii<Vec<u8>> = data | ||
/// # .iter() | ||
/// # .map(|(s, v)| (s.as_str(), *v)) | ||
/// # .collect(); | ||
/// // (trie built as in previous example) | ||
/// | ||
/// // Initialize the iteration at the first child of the trie. | ||
/// let mut stack = Vec::from([(trie.cursor(), 0)]); | ||
/// let mut key = Vec::new(); | ||
/// let mut results = Vec::new(); | ||
/// loop { | ||
/// let Some((ref mut cursor, ref mut index)) = stack.last_mut() else { | ||
/// // Nothing left in the trie. | ||
/// break; | ||
/// }; | ||
/// // Check to see if there is a value at the current node. | ||
/// if let Some(value) = cursor.take_value() { | ||
/// results.push((String::from_utf8(key.clone()).unwrap(), value)); | ||
/// } | ||
/// // Now check for children of the current node. | ||
/// let mut sub_cursor = cursor.clone(); | ||
/// if let Some(ch) = sub_cursor.probe(*index) { | ||
/// // Found a child. Add the child to the stack, and also | ||
/// // increment the index, so that next time we visit the | ||
/// // current node, we check the next child. | ||
/// *index += 1; | ||
/// stack.push((sub_cursor, 0)); | ||
/// key.push(ch); | ||
/// } else { | ||
/// // No more children. Pop this node from the stack. | ||
/// stack.pop(); | ||
/// key.pop(); | ||
/// } | ||
/// } | ||
/// | ||
/// assert_eq!(&results, data); | ||
/// ``` | ||
pub fn probe(&mut self, index: usize) -> Option<u8> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thought: We could also return the number of children in order to avoid re-checking the same node an extra time. |
||
reader::probe_parameterized::<ZeroTrieSimpleAscii<[u8]>>(&mut self.trie.store, index) | ||
} | ||
|
||
/// Checks whether the cursor points to an empty trie. | ||
/// | ||
/// Use this to determine when to stop iterating. | ||
|
@@ -270,23 +361,30 @@ impl<'a> ZeroAsciiIgnoreCaseTrieCursor<'a> { | |
/// assert_eq!(&*key_str, "aBc".as_bytes()); | ||
/// ``` | ||
/// | ||
/// For more examples, see [`ZeroAsciiIgnoreCaseTrieCursor::step`]. | ||
/// For more examples, see [`ZeroTrieSimpleAsciiCursor::step`]. | ||
#[inline] | ||
pub fn step(&mut self, byte: u8) -> Option<u8> { | ||
reader::step_parameterized::<ZeroAsciiIgnoreCaseTrie<[u8]>>(&mut self.trie.store, byte) | ||
} | ||
|
||
/// Takes the value at the current position. | ||
/// | ||
/// For more details, see [`ZeroAsciiIgnoreCaseTrieCursor::take_value`]. | ||
/// For more details, see [`ZeroTrieSimpleAsciiCursor::take_value`]. | ||
#[inline] | ||
pub fn take_value(&mut self) -> Option<usize> { | ||
reader::take_value(&mut self.trie.store) | ||
} | ||
|
||
/// Probes the next byte in the cursor. | ||
/// | ||
/// For more details, see [`ZeroTrieSimpleAsciiCursor::probe`]. | ||
pub fn probe(&mut self, index: usize) -> Option<u8> { | ||
reader::probe_parameterized::<ZeroAsciiIgnoreCaseTrie<[u8]>>(&mut self.trie.store, index) | ||
} | ||
|
||
/// Checks whether the cursor points to an empty trie. | ||
/// | ||
/// For more details, see [`ZeroAsciiIgnoreCaseTrieCursor::is_empty`]. | ||
/// For more details, see [`ZeroTrieSimpleAsciiCursor::is_empty`]. | ||
#[inline] | ||
pub fn is_empty(&self) -> bool { | ||
self.trie.is_empty() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I understand what this means
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you suggest wording that explains it better? This was my attempt at explaining it clearly+succinctly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't suggest wording because I don't understand what this means :)
I'm looking at step and still not understanding how these relate. I suspect wording it less dependently on step will help, and you can mention the correlation after that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reworded the first paragraph of the doc string. Does that help explain the second paragraph?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is only one child node,
step
andprobe
have the same behavior. If there are multiple children,probe
can walk them by their index, whereasstep
binary searches to find the desired child.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah this works