daml_syntax/
coordinate.rs1use std::fmt;
8use std::num::NonZeroUsize;
9use text_size::TextSize;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct InvalidOneBasedCoordinate {
14 value: usize,
15}
16
17impl InvalidOneBasedCoordinate {
18 #[must_use]
20 pub const fn value(self) -> usize {
21 self.value
22 }
23}
24
25impl fmt::Display for InvalidOneBasedCoordinate {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 write!(f, "1-based coordinate value must be non-zero")
28 }
29}
30
31impl std::error::Error for InvalidOneBasedCoordinate {}
32
33macro_rules! define_zero_based_coordinate {
34 ($(#[$meta:meta])* $name:ident) => {
35 $(#[$meta])*
36 #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
37 pub struct $name(usize);
38
39 impl $name {
40 #[must_use]
42 pub const fn new(value: usize) -> Self {
43 Self(value)
44 }
45
46 #[must_use]
48 pub const fn get(self) -> usize {
49 self.0
50 }
51 }
52
53 impl From<$name> for usize {
54 fn from(value: $name) -> Self {
55 value.get()
56 }
57 }
58
59 impl From<usize> for $name {
60 fn from(value: usize) -> Self {
61 Self::new(value)
62 }
63 }
64
65 impl fmt::Debug for $name {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 write!(f, "{}({})", stringify!($name), self.0)
68 }
69 }
70
71 impl fmt::Display for $name {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 self.0.fmt(f)
74 }
75 }
76 };
77}
78
79macro_rules! define_one_based_coordinate {
80 ($(#[$meta:meta])* $name:ident) => {
81 $(#[$meta])*
82 #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
83 pub struct $name(NonZeroUsize);
84
85 impl $name {
86 #[must_use]
88 pub const fn try_new(value: usize) -> Option<Self> {
89 match NonZeroUsize::new(value) {
90 Some(v) => Some(Self(v)),
91 None => None,
92 }
93 }
94
95 #[must_use]
101 pub const fn new(value: usize) -> Self {
102 match NonZeroUsize::new(value) {
103 Some(v) => Self(v),
104 None => panic!("1-based coordinates must be non-zero"),
105 }
106 }
107
108 #[must_use]
110 pub const fn get(self) -> usize {
111 self.0.get()
112 }
113 }
114
115 impl From<$name> for usize {
116 fn from(value: $name) -> Self {
117 value.get()
118 }
119 }
120
121 impl TryFrom<usize> for $name {
122 type Error = InvalidOneBasedCoordinate;
123
124 fn try_from(value: usize) -> Result<Self, Self::Error> {
125 Self::try_new(value).ok_or(InvalidOneBasedCoordinate { value })
126 }
127 }
128
129 impl fmt::Debug for $name {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 write!(f, "{}({})", stringify!($name), self.0)
132 }
133 }
134
135 impl fmt::Display for $name {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 self.0.fmt(f)
138 }
139 }
140 };
141}
142
143define_one_based_coordinate!(
144 LineNumber
148);
149define_one_based_coordinate!(
150 ByteColumn
154);
155define_one_based_coordinate!(
156 CharColumn
160);
161define_zero_based_coordinate!(
162 ByteOffset
167);
168define_zero_based_coordinate!(
169 Utf16Offset
171);
172
173#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
179pub struct Utf16Range {
180 start: Utf16Offset,
181 end: Utf16Offset,
182}
183
184impl Utf16Range {
185 #[must_use]
187 pub const fn new(start: Utf16Offset, end: Utf16Offset) -> Self {
188 Self { start, end }
189 }
190
191 #[must_use]
193 pub const fn start(self) -> Utf16Offset {
194 self.start
195 }
196
197 #[must_use]
199 pub const fn end(self) -> Utf16Offset {
200 self.end
201 }
202}
203
204impl From<TextSize> for ByteOffset {
205 fn from(offset: TextSize) -> Self {
206 Self::new(usize::from(offset))
207 }
208}
209
210impl TryFrom<ByteOffset> for TextSize {
211 type Error = std::num::TryFromIntError;
212
213 fn try_from(offset: ByteOffset) -> Result<Self, Self::Error> {
214 Self::try_from(offset.get())
215 }
216}
217
218#[derive(Debug, Clone, Copy, PartialEq, Eq)]
220pub struct ByteLineCol {
221 pub line: LineNumber,
223 pub column: ByteColumn,
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
230pub struct CharLineCol {
231 pub line: LineNumber,
233 pub column: CharColumn,
235}