1use crate::*;
2
3#[derive(PartialEq, Eq, Clone, Copy, Hash)]
20pub struct PaddedNumber<const A: u8 = 1, const B: u8 = { u8::MAX }> {
21 pub(crate) leading_zeros: u8,
22 pub(crate) number: u64,
23}
24
25impl<const A: u8, const B: u8> PaddedNumber<A, B> {
26 #[doc(hidden)]
27 pub const unsafe fn new_unchecked(leading_zeros: u8, number: u64) -> Self {
28 Self { leading_zeros, number }
29 }
30
31 pub const fn try_new(str: &str) -> Result<Self, ParsePaddedNumberError> {
33 let (leading_zeros, remaining_number) = konst::try_!(padded_number_internal::parse(A, B, str));
34
35 Ok(Self { leading_zeros, number: remaining_number })
36 }
37
38 pub const fn len(&self) -> u8 {
46 self.leading_zeros + utils::number_len(self.number)
47 }
48
49 pub const fn is_empty(&self) -> bool {
56 self.leading_zeros == 0 && self.number == 0
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use crate::tests::mock_from_str;
64
65 #[test]
66 fn new_with_leading_zeros() {
67 let number = mock_from_str::<1, 3>("001");
68 assert_eq!(2, number.leading_zeros);
69 }
70
71 #[test]
72 fn new_with_leading_zeros_only() {
73 let number = mock_from_str::<1, 3>("000");
74 let expected = PaddedNumber { leading_zeros: 3, number: 0 };
75 assert_eq!(expected, number)
76 }
77
78 #[test]
79 fn new_with_empty_str() {
80 let number = mock_from_str::<0, 0>("");
81 assert!(number.is_empty());
82 }
83
84 #[test]
85 fn too_long_error() {
86 let invalid_number = "123";
87
88 let actual_err = invalid_number.parse::<PaddedNumber<1, 2>>().unwrap_err();
89
90 assert_eq!(ParsePaddedNumberError::TooLong(2, 3), actual_err);
91 }
92
93 #[test]
94 fn too_short_error() {
95 let invalid_number = "";
96
97 let actual_err = invalid_number.parse::<PaddedNumber<1, 2>>().unwrap_err();
98
99 assert_eq!(ParsePaddedNumberError::TooShort(1, 0), actual_err);
100 }
101
102 #[test]
103 fn non_ascii_digits_error() {
104 let invalid_number = "123abc";
105
106 let actual_err = invalid_number.parse::<PaddedNumber<0, 10>>().unwrap_err();
107
108 assert!(matches!(actual_err, ParsePaddedNumberError::InvalidNumber(_)));
109 }
110
111 #[test]
112 fn is_empty() {
113 let number = PaddedNumber::<0, 0> { leading_zeros: 0, number: 0 };
114 assert!(number.is_empty())
115 }
116
117 #[test]
118 fn length() {
119 assert_len(0, "");
120 assert_len(1, "0");
121 assert_len(3, "000");
122 assert_len(3, "467");
123 assert_len(5, "00467");
124
125 fn assert_len(expected_length: u8, number_str: &str) {
126 let number = mock_from_str::<0, 10>(number_str);
127 assert_eq!(expected_length, number.len());
128 }
129 }
130}