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