diff options
Diffstat (limited to 'audio/src/parse/pos.rs')
| -rw-r--r-- | audio/src/parse/pos.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/audio/src/parse/pos.rs b/audio/src/parse/pos.rs new file mode 100644 index 0000000..f56a96b --- /dev/null +++ b/audio/src/parse/pos.rs @@ -0,0 +1,83 @@ +use std::fmt; + +#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] +pub struct Pos { + pub idx: u32, + pub line: u32, + pub col: u32, +} + +impl std::cmp::PartialOrd for Pos { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + Some(self.cmp(other)) + } +} + +impl std::cmp::Ord for Pos { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.idx.cmp(&other.idx) + } +} + +impl Pos { + pub const fn new() -> Self { + Self { + idx: 0, + line: 1, + col: 1, + } + } + + #[must_use] + pub fn advance(self, c: char) -> Self { + let idx = self.idx + u32::try_from(c.len_utf8()).unwrap_or_default(); + if c == '\n' { + Self { + idx, + line: self.line + 1, + col: 1, + } + } else { + Self { + idx, + line: self.line, + col: self.col + 1, + } + } + } +} + +impl fmt::Display for Pos { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}:{}", self.line, self.col) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Span { + pub start: Pos, + pub end: Pos, +} + +impl Span { + pub const fn new(start: Pos, end: Pos) -> Self { + if end.idx < start.idx { + Self { + start: end, + end: start, + } + } else { + Self { start, end } + } + } + + pub fn of<'a>(&self, s: &'a str) -> &'a str { + &s[(self.start.idx as usize)..(self.end.idx as usize)] + } +} + +impl fmt::Display for Span { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}-{}", self.start, self.end) + } +} |