rumdl_lib/types/
line_length.rs1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use std::fmt;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct LineLength(Option<usize>);
13
14impl LineLength {
15 pub fn new(value: usize) -> Self {
17 if value == 0 { Self(None) } else { Self(Some(value)) }
18 }
19
20 pub fn get(self) -> usize {
22 self.0.unwrap_or(0)
23 }
24
25 pub fn is_unlimited(self) -> bool {
27 self.0.is_none()
28 }
29
30 pub fn effective_limit(self) -> usize {
33 self.0.unwrap_or(usize::MAX)
34 }
35
36 pub const fn from_const(value: usize) -> Self {
41 if value == 0 { Self(None) } else { Self(Some(value)) }
42 }
43}
44
45impl<'de> Deserialize<'de> for LineLength {
48 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
49 where
50 D: Deserializer<'de>,
51 {
52 let value = usize::deserialize(deserializer)?;
53 Ok(LineLength::new(value))
54 }
55}
56
57impl Serialize for LineLength {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: Serializer,
61 {
62 self.get().serialize(serializer)
63 }
64}
65
66impl From<LineLength> for usize {
67 fn from(val: LineLength) -> Self {
68 val.get()
69 }
70}
71
72impl fmt::Display for LineLength {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 if self.is_unlimited() {
75 write!(f, "unlimited")
76 } else {
77 write!(f, "{}", self.get())
78 }
79 }
80}
81
82impl Default for LineLength {
83 fn default() -> Self {
84 Self::from_const(80) }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_valid_values() {
94 let unlimited = LineLength::new(0);
96 assert_eq!(unlimited.get(), 0);
97 assert!(unlimited.is_unlimited());
98 assert_eq!(unlimited.effective_limit(), usize::MAX);
99 assert_eq!(usize::from(unlimited), 0);
100
101 for value in [1, 2, 80, 100, 120, 1000] {
103 let limited = LineLength::new(value);
104 assert_eq!(limited.get(), value);
105 assert!(!limited.is_unlimited());
106 assert_eq!(limited.effective_limit(), value);
107 assert_eq!(usize::from(limited), value);
108 }
109 }
110
111 #[test]
112 fn test_from_const() {
113 const UNLIMITED: LineLength = LineLength::from_const(0);
114 assert_eq!(UNLIMITED.get(), 0);
115 assert!(UNLIMITED.is_unlimited());
116
117 const LIMITED: LineLength = LineLength::from_const(80);
118 assert_eq!(LIMITED.get(), 80);
119 assert!(!LIMITED.is_unlimited());
120 }
121
122 #[test]
123 fn test_display() {
124 let unlimited = LineLength::new(0);
125 assert_eq!(format!("{unlimited}"), "unlimited");
126
127 let limited = LineLength::new(80);
128 assert_eq!(format!("{limited}"), "80");
129 }
130
131 #[test]
132 fn test_roundtrip() {
133 #[derive(serde::Serialize, serde::Deserialize)]
134 struct TestConfig {
135 value: LineLength,
136 }
137
138 let config = TestConfig {
140 value: LineLength::new(0),
141 };
142 let serialized = toml::to_string(&config).unwrap();
143 assert_eq!(serialized.trim(), "value = 0");
144 let deserialized: TestConfig = toml::from_str(&serialized).unwrap();
145 assert_eq!(deserialized.value.get(), 0);
146 assert!(deserialized.value.is_unlimited());
147
148 let config = TestConfig {
150 value: LineLength::new(100),
151 };
152 let serialized = toml::to_string(&config).unwrap();
153 assert_eq!(serialized.trim(), "value = 100");
154 let deserialized: TestConfig = toml::from_str(&serialized).unwrap();
155 assert_eq!(deserialized.value.get(), 100);
156 assert!(!deserialized.value.is_unlimited());
157 }
158
159 #[test]
160 fn test_deserialization() {
161 #[derive(Debug, serde::Deserialize)]
162 struct TestConfig {
163 value: LineLength,
164 }
165
166 let toml_str = "value = 0";
168 let config: TestConfig = toml::from_str(toml_str).unwrap();
169 assert_eq!(config.value.get(), 0);
170 assert!(config.value.is_unlimited());
171
172 let toml_str = "value = 120";
174 let config: TestConfig = toml::from_str(toml_str).unwrap();
175 assert_eq!(config.value.get(), 120);
176 assert!(!config.value.is_unlimited());
177 }
178}