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 checked_add(self, n: usize) -> Option<Self> {
32 self.0.get().checked_add(n).and_then(Self::new)
33 }
34
35 pub fn checked_sub(self, n: usize) -> Option<Self> {
36 self.0.get().checked_sub(n).and_then(Self::new)
37 }
38
39 pub fn next(self) -> Self {
40 self.checked_add(1).expect("valid line number")
41 }
42
43 pub fn prev(self) -> Option<Self> {
44 self.checked_sub(1)
45 }
46
47 pub fn saturating_add(self, n: usize) -> Self {
48 Self(NonZeroUsize::new(self.0.get().saturating_add(n)).expect("LineNumber overflow"))
49 }
50
51 pub fn saturating_sub(self, n: usize) -> usize {
52 self.0.get().saturating_sub(n)
53 }
54
55 pub fn abs_diff(self, other: Self) -> usize {
56 self.0.get().abs_diff(other.0.get())
57 }
58}
59
60impl Add<usize> for LineNumber {
61 type Output = Self;
62 fn add(self, rhs: usize) -> Self::Output {
63 Self(NonZeroUsize::new(self.0.get() + rhs).expect("LineNumber overflow"))
64 }
65}
66
67impl AddAssign<usize> for LineNumber {
68 fn add_assign(&mut self, rhs: usize) {
69 *self = *self + rhs;
70 }
71}
72
73impl Sub<usize> for LineNumber {
74 type Output = usize;
75 fn sub(self, rhs: usize) -> Self::Output {
76 self.0.get() - rhs
77 }
78}
79
80impl Sub for LineNumber {
81 type Output = usize;
82 fn sub(self, rhs: Self) -> Self::Output {
83 self.0.get() - rhs.0.get()
84 }
85}
86
87impl std::fmt::Display for LineNumber {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 self.0.fmt(f)
90 }
91}