mod located;
pub mod position;
pub use located::Located;
pub use position::Position;
use serde::Deserialize;
use serde::Serialize;
#[derive(Debug)]
pub enum Error {
Position(position::Error),
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::Position(err) => write!(f, "position error: {err}"),
}
}
}
impl std::error::Error for Error {}
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum Location {
Unplaced,
Position(Position),
Span {
start: Position,
end: Position,
},
}
impl Location {
pub fn byte_range(&self) -> Option<std::ops::Range<usize>> {
match self {
Location::Unplaced => None,
Location::Position(position) => Some(position.byte_no()..position.byte_no()),
Location::Span { start, end } => Some(start.byte_no()..end.byte_no()),
}
}
pub fn to_string(&self) -> Option<String> {
match self {
Location::Unplaced => None,
Location::Position(position) => Some(format!("{}", position)),
Location::Span { start, end } => Some(format!("{}-{}", start, end)),
}
}
}
impl TryFrom<pest::Span<'_>> for Location {
type Error = Error;
fn try_from(span: pest::Span<'_>) -> Result<Self, Self::Error> {
let start = Position::try_from(span.start_pos()).map_err(Error::Position)?;
let end = Position::try_from(span.end_pos()).map_err(Error::Position)?;
Ok(Location::Span { start, end })
}
}
impl std::fmt::Display for Location {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Location::Unplaced => write!(f, ""),
Location::Position(position) => write!(f, "{}", position),
Location::Span { start, end } => write!(f, "{}-{}", start, end),
}
}
}
#[cfg(test)]
mod tests {
use std::num::NonZeroUsize;
use super::*;
#[test]
fn display_file() {
assert_eq!(Location::Unplaced.to_string(), None);
}
#[test]
fn display_position() {
let result = Location::Position(Position::new(
NonZeroUsize::try_from(1).unwrap(),
NonZeroUsize::try_from(1).unwrap(),
0,
))
.to_string();
assert_eq!(result, Some(String::from("1:1")));
}
#[test]
fn display_span() {
let result = Location::Span {
start: Position::new(
NonZeroUsize::try_from(1).unwrap(),
NonZeroUsize::try_from(1).unwrap(),
0,
),
end: Position::new(
NonZeroUsize::try_from(5).unwrap(),
NonZeroUsize::try_from(5).unwrap(),
24,
),
}
.to_string();
assert_eq!(result, Some(String::from("1:1-5:5")));
}
}