summaryrefslogtreecommitdiff
path: root/audio/src/parse/pos.rs
diff options
context:
space:
mode:
Diffstat (limited to 'audio/src/parse/pos.rs')
-rw-r--r--audio/src/parse/pos.rs83
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)
+ }
+}