Skip to content

Commit

Permalink
remove need for mutating spans of a Parsable
Browse files Browse the repository at this point in the history
  • Loading branch information
sam0x17 committed Mar 30, 2024
1 parent d5f834a commit 8f5e30d
Show file tree
Hide file tree
Showing 8 changed files with 11 additions and 65 deletions.
8 changes: 1 addition & 7 deletions src/parsable/everything.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ impl Parsable for Everything {
let s = value.span();
let text = s.source_text();
if stream.remaining() == text {
let mut value = value;
value.set_span(stream.consume(text.len())?);
return Ok(value);
return Ok(Everything(stream.consume(text.len())?));
}
let prefix = common_prefix(text, stream.remaining());
stream.consume(prefix.len())?;
Expand All @@ -38,10 +36,6 @@ impl Parsable for Everything {
}
Err(Error::new(missing_span, "expected end of input"))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.0 = span.into();
}
}

#[test]
Expand Down
4 changes: 0 additions & 4 deletions src/parsable/exact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ impl Parsable for Exact {
let missing = &text[prefix.len()..];
Err(Error::expected(missing_span, missing))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.0 = span.into();
}
}

#[test]
Expand Down
4 changes: 0 additions & 4 deletions src/parsable/nothing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ impl Parsable for Nothing {
fn unparse(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(())
}

fn set_span(&mut self, span: impl Into<Span>) {
self.0 = span.into();
}
}

#[test]
Expand Down
24 changes: 0 additions & 24 deletions src/parsable/numbers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ impl Parsable for U64 {
let span = Span::new(stream.source().clone(), start_position..stream.position);
Ok(U64(parsed, span))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.1 = span.into();
}
}

make_parsable!(U64);
Expand Down Expand Up @@ -113,10 +109,6 @@ impl Parsable for U128 {
let span = Span::new(stream.source().clone(), start_position..stream.position);
Ok(U128(parsed, span))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.1 = span.into();
}
}

make_parsable!(U128);
Expand Down Expand Up @@ -172,10 +164,6 @@ impl Parsable for I64 {
let span = Span::new(stream.source().clone(), start_position..stream.position);
Ok(I64(parsed * sign, span))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.1 = span.into();
}
}

make_parsable!(I64);
Expand Down Expand Up @@ -238,10 +226,6 @@ impl Parsable for I128 {
let span = Span::new(stream.source().clone(), start_position..stream.position);
Ok(I128(parsed * sign, span))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.1 = span.into();
}
}

make_parsable!(I128);
Expand Down Expand Up @@ -313,10 +297,6 @@ impl Parsable for Decimal {
span,
))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.1 = span.into();
}
}

/// A bounded version of [`I64`].
Expand Down Expand Up @@ -355,10 +335,6 @@ impl<const MIN: i64, const MAX: i64> Parsable for BoundedI64<MIN, MAX> {
}
Ok(BoundedI64(i))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.0 .1 = span.into();
}
}

#[test]
Expand Down
8 changes: 4 additions & 4 deletions src/parsable/optional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ impl<T: Parsable> Parsable for Optional<T> {
Ok(Optional::None)
}

fn set_span(&mut self, span: impl Into<Span>) {
match self {
Optional::Some(val) => val.set_span(span),
Optional::None => (),
fn parse_value(value: Self, stream: &mut ParseStream) -> ParseResult<Self> {
match value {
Optional::Some(val) => stream.parse_value(val).map(Optional::Some),
Optional::None => Ok(Optional::None),
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions src/parsable/whitespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ impl Parsable for Whitespace {
start_position..stream.position,
)))
}

fn set_span(&mut self, span: impl Into<Span>) {
self.0 = span.into();
}
}

#[test]
Expand Down
4 changes: 1 addition & 3 deletions src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,9 +358,7 @@ pub trait Parsable:
let s = value.span();
let text = s.source_text();
if stream.remaining().starts_with(text) {
let mut value = value;
*value.span_mut() = stream.consume(text.len())?;
return Ok(value);
return stream.parse();
}
let prefix = common_prefix(text, stream.remaining());
let expected = &text[prefix.len()..];
Expand Down
20 changes: 5 additions & 15 deletions src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ impl Span {
byte_range: start..end,
})
}

/// Returns whether this [`Span`] is blank, i.e. has a zero-length range.
pub fn is_blank(&self) -> bool {
self.byte_range.start == self.byte_range.end
}
}

/// Represents a line and column within a [`Source`].
Expand All @@ -192,27 +197,12 @@ pub trait Spanned {
/// i.e. by joining all of the [`Span`]s together, rather than storing a permanent primary
/// [`Span`] on the type directly.
fn span(&self) -> Span;

/// Provides mutable access to the underlying [`Span`] of self.
///
/// Use with caution. With great power comes great responsibility. In particular, changing
/// the [`Span`] of a type that has already been parsed or for types that are part of a larger
/// structure can lead to unexpected behavior.
///
/// One guarantee implementers must provide is that the [`Span`] returned by this method is
/// always the same as the one returned by [`span`], even if the type is mutated in between
/// calls to the two methods.
fn span_mut(&mut self) -> &mut Span;
}

impl Spanned for Span {
fn span(&self) -> Span {
self.clone()
}

fn span_mut(&mut self) -> &mut Span {
self
}
}

/// A trait for types that have multiple [`Span`]s.
Expand Down

0 comments on commit 8f5e30d

Please sign in to comment.