Skip to content

Commit

Permalink
Tweak Cursor ordering documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
CAD97 committed Jul 25, 2022
1 parent 580038a commit 487c114
Showing 1 changed file with 15 additions and 11 deletions.
26 changes: 15 additions & 11 deletions src/buffer.rs
Expand Up @@ -132,7 +132,7 @@ impl TokenBuffer {
/// Creates a cursor referencing the first token in the buffer and able to
/// traverse until the end of the buffer.
pub fn begin(&self) -> Cursor {
unsafe { Cursor::create(self.ptr, self.ptr.add(self.len - 1)) }
unsafe { Cursor::create(self.ptr, self.ptr.add(self.len - 1), 0) }
}
}

Expand All @@ -145,8 +145,9 @@ impl TokenBuffer {
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
/// Two cursors can only be compared if they have the same scope in the same
/// input stream, and are ordered based on location in the stream. The two
/// cursors are equal if they have the same location in the input stream.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct Cursor<'a> {
Expand All @@ -155,6 +156,9 @@ pub struct Cursor<'a> {
// This is the only `Entry::End(..)` object which this cursor is allowed to
// point at. All other `End` objects are skipped over in `Cursor::create`.
scope: *const Entry,
// How many entries the cursor has traversed since the beginning of the
// buffer. Used to compare two cursors.
index: usize,
// Cursor is covariant in 'a. This field ensures that our pointers are still
// valid.
marker: PhantomData<&'a Entry>,
Expand All @@ -177,14 +181,15 @@ impl<'a> Cursor<'a> {
Cursor {
ptr: &EMPTY_ENTRY.0,
scope: &EMPTY_ENTRY.0,
index: 0,
marker: PhantomData,
}
}

/// This create method intelligently exits non-explicitly-entered
/// `None`-delimited scopes when the cursor reaches the end of them,
/// allowing for them to be treated transparently.
unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
unsafe fn create(mut ptr: *const Entry, scope: *const Entry, index: usize) -> Self {
// NOTE: If we're looking at a `End(..)`, we want to advance the cursor
// past it, unless `ptr == scope`, which means that we're at the edge of
// our cursor's scope. We should only have `ptr != scope` at the exit
Expand All @@ -199,6 +204,7 @@ impl<'a> Cursor<'a> {
Cursor {
ptr,
scope,
index,
marker: PhantomData,
}
}
Expand All @@ -212,7 +218,7 @@ impl<'a> Cursor<'a> {
/// is undefined behavior if the cursor is currently looking at an
/// `Entry::End`.
unsafe fn bump(self) -> Cursor<'a> {
Cursor::create(self.ptr.offset(1), self.scope)
Cursor::create(self.ptr.offset(1), self.scope, self.index + 1)
}

/// While the cursor is looking at a `None`-delimited group, move it to look
Expand All @@ -227,7 +233,7 @@ impl<'a> Cursor<'a> {
// situations where we should immediately exit the span after
// entering it are handled correctly.
unsafe {
*self = Cursor::create(buf.ptr, self.scope);
*self = Cursor::create(buf.ptr, self.scope, self.index);
}
} else {
break;
Expand Down Expand Up @@ -389,18 +395,16 @@ impl<'a> Eq for Cursor<'a> {}

impl<'a> PartialEq for Cursor<'a> {
fn eq(&self, other: &Self) -> bool {
let Cursor { ptr, scope, marker } = self;
let _ = marker;
let Cursor { ptr, scope, .. } = self;
*ptr == other.ptr && *scope == other.scope
}
}

impl<'a> PartialOrd for Cursor<'a> {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
let Cursor { ptr, scope, marker } = self;
let _ = marker;
let Cursor { index, scope, .. } = self;
if *scope == other.scope {
Some(ptr.cmp(&other.ptr))
Some(index.cmp(&other.index))
} else {
None
}
Expand Down

0 comments on commit 487c114

Please sign in to comment.