Skip to main content

provenant/models/
line_number.rs

1// SPDX-FileCopyrightText: Provenant contributors
2// SPDX-License-Identifier: Apache-2.0
3
4use 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}