-
Notifications
You must be signed in to change notification settings - Fork 74
Clarify docs for Offset
and Stream
#826
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
base: main
Are you sure you want to change the base?
Conversation
previously, the docs in `Offset` and `Stream` made implementing it for a type yourself pretty difficult. I had some trouble, so thought I'd spare myself the time in the future by improving it for everyone :D
/// | ||
/// Types can implement this trait to become custom input types. |
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.
This feels redundant
/// | |
/// Types can implement this trait to become custom input types. |
/// An iterator containing a tuple of: | ||
/// | ||
/// - [`usize`]: the offset from the current location. | ||
/// - [`Self::Token`]: the token at the `usize` location. |
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.
Let's use https://doc.rust-lang.org/std/string/struct.String.html#method.char_indices for inspiration for wording
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 guess https://doc.rust-lang.org/std/str/struct.CharIndices.html would be more closely aligned with intent
/// | ||
/// Note that, since [`Iterator`] is a trait, this type can be anything | ||
/// that implements that trait. Therefore, an efficient implementation will | ||
/// dynamically create this tuple instead of precomputing it. |
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.
This feels oddly specific and more about teaching Rust than explaining this functionality
/// Note that this type must implement [`Offset`], which says how many | ||
/// bytes have been computed between a checkpoint and some initial/starting | ||
/// checkpoint. |
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.
This is redundant with the trait bounds and their own documentation as well as inaccurate as we talk about Offsets, not Bytes.
Pull Request Test Coverage Report for Build 18062781148Details
💛 - Coveralls |
/// A saved location within the [`Stream`]. | ||
/// | ||
/// This type should allow users to reset the stream to a previous state. |
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.
Should we have reset
link to Self::reset
? If so, then we should probably also link to Self::checkpoint()
? This also quickly becomes redundant with those.
Maybe
/// A saved location within the [`Stream`]. | |
/// | |
/// This type should allow users to reset the stream to a previous state. | |
/// A saved location within the [`Stream`]. | |
/// | |
/// See also [`Self::checkpoint`] and [`Self::reset`] |
/// Creates a [`Self::IterOffsets`] from the existing stream state. | ||
/// | ||
/// For efficiency, this should probably be computed on the fly, at least | ||
/// when it's possible. |
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.
This is too implementation focused. Most people will be using an existing stream type. Their goal isn't to create a IterOffsets
but to iterate with offsets. Might be good to take inspiration from https://doc.rust-lang.org/std/string/struct.String.html#method.char_indices for wording
fn iter_offsets(&self) -> Self::IterOffsets; | ||
|
||
/// Returns the offset to the end of the input | ||
/// Returns the number of bytes until the stream completes. |
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.
offset, not bytes
fn eof_offset(&self) -> usize; | ||
|
||
/// Split off the next token from the input | ||
/// Takes the next token from the stream. |
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.
This doesn't express that we are also advancing the stream
/// This method should consume the token, mutating the original input to | ||
/// no longer have it. |
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.
We should word this in terms that work for both user and implementer
/// Finds the offset of the next value matching the given `predicate` | ||
/// function. |
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.
/// Finds the offset of the next value matching the given `predicate` | |
/// function. | |
/// Finds the offset of the next token that matches `predicate` |
/// | ||
/// The offset is relative from the current location. |
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 wonder if there is a better way to teach this concept because everything is relative to the stream's current location
/// The offset is relative to the current position. This means that an | ||
/// input of "0 tokens" will return an offset of `0`. |
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.
P: Fn(Self::Token) -> bool; | ||
/// Get the offset for the number of `tokens` into the stream | ||
|
||
/// Find the offset after consuming a number of `tokens` from the stream. |
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.
"consuming" makes this sound like this advanced the stream's position.
/// **Note:** For inputs with variable width tokens, like `&str`'s `char`, | ||
/// `offset` might not correspond with the number of tokens. To get a valid | ||
/// offset, use: | ||
/// |
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.
Did nothing change here? If so, please revert
/// Takes a slice of `offset` tokens from the input. | ||
/// | ||
/// This method should consume `offset` tokens. |
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 feel like saying "split off" covers both sentences and ensures its all in the summary
/// # Panic | ||
/// | ||
/// This will panic if | ||
/// This method panics if any of the following invariants are violated: |
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.
Please revert. This doesn't add anything but does make it more likely for the user to miss whats being said
fn next_slice(&mut self, offset: usize) -> Self::Slice; | ||
/// Split off a slice of tokens from the input | ||
|
||
/// Takes a slice of `offset` tokens from the input. |
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.
FYI this is the point that I'm taking a break. Please consider my feedback above on the documentation below and we can re-evaluate once its all been updated
Thanks for your feedback! Note that my primary reason for making these changes is to increase accessibility for implementers. :D The stable docs on this trait make it overly confusing to implement for the first time. So, I focused on making it easier to understand. If you'd like me to remove those elements and assume that all readers are very experienced (will take a better look at these suggestions later this week; your notes on sounding more like the stl and being more careful w/ "consuming" vs. "peeking" are veeeery important) |
I am fine with making the docs more approachable. My concerns are:
|
Got it! I'll approach this again later with that mindset. Thanks for the feedback 😄 |
Goal
Improve the
Offset
+Stream
docs.Background
I implemented
Stream
for a type yesterday, but it took quite a lot of time to understand what was going on. The existing docs weren't very clear, so it kinda required me to copy what&[u8]
and&str
were doing.After implementing it successfully, I thought I may as well share what I learned! (and spare myself the time re-learning it in the future)
These changes should clarify what an implementation should do... without being too over the top. If I still sounded a little off, or anything is incorrect, please let me know and I'll fix it up! :D
Changes
winnow::stream::Stream
...winnow::stream::Offset
.Testing
I know it'll run in CI, but I tested my changes like so:
typos
committed
cargo doc