provenant/models/
line_number.rs1use std::num::NonZeroUsize;
2use std::ops::{Add, AddAssign, Sub};
3
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
7#[serde(transparent)]
8pub struct LineNumber(NonZeroUsize);
9
10impl LineNumber {
11 pub const ONE: Self = match NonZeroUsize::new(1) {
12 Some(n) => Self(n),
13 None => unreachable!(),
14 };
15
16 pub fn new(n: usize) -> Option<Self> {
17 NonZeroUsize::new(n).map(Self)
18 }
19
20 pub fn from_0_indexed(i: usize) -> Self {
21 Self(NonZeroUsize::new(i + 1).expect("0-indexed line overflow"))
22 }
23
24 pub fn get(self) -> usize {
25 self.0.get()
26 }
27
28 pub fn saturating_add(self, n: usize) -> Self {
29 Self(NonZeroUsize::new(self.0.get().saturating_add(n)).expect("LineNumber overflow"))
30 }
31
32 pub fn saturating_sub(self, n: usize) -> usize {
33 self.0.get().saturating_sub(n)
34 }
35
36 pub fn abs_diff(self, other: Self) -> usize {
37 self.0.get().abs_diff(other.0.get())
38 }
39}
40
41impl Add<usize> for LineNumber {
42 type Output = Self;
43 fn add(self, rhs: usize) -> Self::Output {
44 Self(NonZeroUsize::new(self.0.get() + rhs).expect("LineNumber overflow"))
45 }
46}
47
48impl AddAssign<usize> for LineNumber {
49 fn add_assign(&mut self, rhs: usize) {
50 *self = *self + rhs;
51 }
52}
53
54impl Sub<usize> for LineNumber {
55 type Output = usize;
56 fn sub(self, rhs: usize) -> Self::Output {
57 self.0.get() - rhs
58 }
59}
60
61impl Sub for LineNumber {
62 type Output = usize;
63 fn sub(self, rhs: Self) -> Self::Output {
64 self.0.get() - rhs.0.get()
65 }
66}
67
68impl std::fmt::Display for LineNumber {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 self.0.fmt(f)
71 }
72}