easypdf_core/
page_number.rs1use crate::{PageIndex, PdfError, Result};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct PageNumber(usize);
8
9impl PageNumber {
10 pub const fn new(value: usize) -> Result<Self> {
16 if value == 0 {
17 return Err(PdfError::InvalidPage(0));
18 }
19 Ok(Self(value))
20 }
21
22 #[must_use]
24 pub const fn from_index(index: PageIndex) -> Self {
25 Self(index.value() + 1)
26 }
27
28 #[must_use]
30 pub const fn value(self) -> usize {
31 self.0
32 }
33
34 #[must_use]
36 pub const fn index(self) -> PageIndex {
37 PageIndex::new(self.0 - 1)
38 }
39}
40
41#[cfg(test)]
42#[allow(clippy::uninlined_format_args, clippy::float_cmp)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn new_valid_value() {
48 let pn = PageNumber::new(1).unwrap();
49 assert_eq!(pn.value(), 1);
50 }
51
52 #[test]
53 fn new_large_value() {
54 let pn = PageNumber::new(1000).unwrap();
55 assert_eq!(pn.value(), 1000);
56 }
57
58 #[test]
59 fn new_zero_returns_error() {
60 let result = PageNumber::new(0);
61 assert!(result.is_err());
62 let err = result.unwrap_err();
63 assert!(matches!(err, PdfError::InvalidPage(0)));
64 }
65
66 #[test]
67 fn from_index_converts_correctly() {
68 let idx = PageIndex::new(0);
69 let pn = PageNumber::from_index(idx);
70 assert_eq!(pn.value(), 1);
71
72 let idx = PageIndex::new(4);
73 let pn = PageNumber::from_index(idx);
74 assert_eq!(pn.value(), 5);
75 }
76
77 #[test]
78 fn value_returns_inner() {
79 let pn = PageNumber::new(42).unwrap();
80 assert_eq!(pn.value(), 42);
81 }
82
83 #[test]
84 fn index_converts_to_zero_based() {
85 let pn = PageNumber::new(1).unwrap();
86 assert_eq!(pn.index().value(), 0);
87
88 let pn = PageNumber::new(5).unwrap();
89 assert_eq!(pn.index().value(), 4);
90 }
91
92 #[test]
93 fn roundtrip_page_number_to_index_and_back() {
94 let pn = PageNumber::new(10).unwrap();
95 let idx = pn.index();
96 let pn2 = PageNumber::from_index(idx);
97 assert_eq!(pn, pn2);
98 }
99
100 #[test]
101 fn clone_and_copy() {
102 let pn = PageNumber::new(3).unwrap();
103 let cloned = pn;
104 assert_eq!(pn, cloned);
105 }
106
107 #[test]
108 fn debug_format() {
109 let pn = PageNumber::new(7).unwrap();
110 assert_eq!(format!("{:?}", pn), "PageNumber(7)");
111 }
112
113 #[test]
114 fn ordering() {
115 let a = PageNumber::new(1).unwrap();
116 let b = PageNumber::new(5).unwrap();
117 assert!(a < b);
118 assert!(b > a);
119 }
120
121 #[test]
122 fn equality() {
123 let a = PageNumber::new(3).unwrap();
124 let b = PageNumber::new(3).unwrap();
125 let c = PageNumber::new(4).unwrap();
126 assert_eq!(a, b);
127 assert_ne!(a, c);
128 }
129
130 #[test]
131 fn hash_same_values() {
132 use std::collections::HashSet;
133 let mut set = HashSet::new();
134 set.insert(PageNumber::new(1).unwrap());
135 set.insert(PageNumber::new(1).unwrap());
136 set.insert(PageNumber::new(2).unwrap());
137 assert_eq!(set.len(), 2);
138 }
139}