1use std::fmt::Display;
2use std::sync::Arc;
3
4#[derive(Clone, Default, Debug)]
6#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
7#[cfg_attr(
8 any(test, feature = "serde"),
9 derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
10)]
11pub struct SourcePosition {
12 pub index: usize,
14 pub line: usize,
16 pub column: usize,
18}
19
20impl Display for SourcePosition {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 f.write_fmt(format_args!("{},{}", self.line, self.column))
23 }
24}
25
26impl SourcePosition {
27 #[must_use]
34 pub const fn offset(&self, offset: &SourcePositionOffset) -> Self {
35 Self {
36 index: self.index + offset.index,
37 line: self.line + offset.line,
38 column: if offset.line == 0 {
39 self.column + offset.column
40 } else {
41 offset.column + 1
42 },
43 }
44 }
45}
46
47#[cfg(feature = "diagnostics")]
48impl From<&SourcePosition> for miette::SourceOffset {
49 #[allow(clippy::cast_sign_loss)]
50 fn from(position: &SourcePosition) -> Self {
51 position.index.into()
52 }
53}
54
55#[derive(Clone, Default, Debug)]
57#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
58#[cfg_attr(
59 any(test, feature = "serde"),
60 derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
61)]
62pub struct SourcePositionOffset {
63 pub index: usize,
65 pub line: usize,
67 pub column: usize,
69}
70
71#[derive(Clone, Default, Debug)]
73#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
74#[cfg_attr(
75 any(test, feature = "serde"),
76 derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
77)]
78pub struct SourceSpan {
79 pub start: Arc<SourcePosition>,
81 pub end: Arc<SourcePosition>,
83}
84
85impl SourceSpan {
86 pub fn length(&self) -> usize {
88 self.end.index - self.start.index
89 }
90 pub(crate) fn within(start: &Self, end: &Self) -> Self {
91 Self {
92 start: start.start.clone(),
93 end: end.end.clone(),
94 }
95 }
96}