tamer: span::Span::endpoints_saturated: New method

This gets rid of the `Option` and is used in the diagnostic system (next
commit).

DEV-10935
main
Mike Gerwitz 2022-04-21 14:15:25 -04:00
parent a22e8e79f7
commit e555955450
1 changed files with 71 additions and 0 deletions

View File

@ -220,6 +220,10 @@ pub struct Span {
/// Context onto which byte offsets are mapped,
/// such as a source file.
///
/// N.B.: This is an unaligned field,
/// and accessing it frequently may have a negative impact on
/// performance.
ctx: Context,
}
@ -370,6 +374,49 @@ impl Span {
},
)
}
/// Create two zero-length spans representing respectively the first and
/// last offsets in the span,
/// saturating the ending offset if it cannot be represented by
/// [`SpanOffsetSize`].
///
/// Aside from the saturation,
/// this is identical to [`Span::endpoints`].
pub fn endpoints_saturated(self) -> (Self, Self) {
let endpoints = self.endpoints();
(
endpoints.0,
endpoints.1.unwrap_or(Self {
offset: SpanOffsetSize::MAX,
..endpoints.0
}),
)
}
/// Adjust span such that its offset is relative to the provided span.
///
/// If the provide `rel_span` does not precede this span,
/// [`None`] will be returned.
///
/// If the two spans do not share the same [`Context`],
/// no comparison can be made and [`None`] will be returned.
pub fn relative_to(self, rel_span: Span) -> Option<Self> {
// Note that this is unaligned.
if self.ctx() != rel_span.ctx() {
return None;
}
if self.offset() < rel_span.offset() {
return None;
}
Some(Self {
ctx: self.ctx,
offset: self.offset.saturating_sub(rel_span.offset),
len: self.len,
})
}
}
impl Into<u64> for Span {
@ -676,4 +723,28 @@ mod test {
assert_eq!(start, Span::new(10, 0, ctx));
assert_eq!(end, Some(Span::new(30, 0, ctx)));
}
#[test]
fn span_endpoints_exceeding_max_offset() {
let ctx = Context::from("end");
let offset = SpanOffsetSize::MAX - 5;
let span = ctx.span(offset, 10);
let (start, end) = span.endpoints();
assert_eq!(start, Span::new(offset, 0, ctx));
assert_eq!(end, None);
}
#[test]
fn span_endpoints_saturated() {
let ctx = Context::from("end");
let offset = SpanOffsetSize::MAX - 5;
let span = ctx.span(offset, 10);
let (start, end) = span.endpoints_saturated();
assert_eq!(start, Span::new(offset, 0, ctx));
assert_eq!(end, Span::new(SpanOffsetSize::MAX, 0, ctx));
}
}