feedparser_rs/types/
generics.rs1use std::fmt::Debug;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
34#[allow(dead_code)]
35pub struct DetailedField<V, D> {
36 value: V,
37 detail: Option<D>,
38}
39
40impl<V, D> DetailedField<V, D> {
41 #[inline]
43 #[must_use]
44 pub const fn from_value(value: V) -> Self {
45 Self {
46 value,
47 detail: None,
48 }
49 }
50
51 #[inline]
53 #[must_use]
54 pub const fn with_detail(value: V, detail: D) -> Self {
55 Self {
56 value,
57 detail: Some(detail),
58 }
59 }
60
61 #[inline]
63 #[must_use]
64 pub const fn value(&self) -> &V {
65 &self.value
66 }
67
68 #[inline]
70 pub const fn value_mut(&mut self) -> &mut V {
71 &mut self.value
72 }
73
74 #[inline]
76 #[must_use]
77 pub const fn detail(&self) -> Option<&D> {
78 self.detail.as_ref()
79 }
80
81 #[inline]
83 pub const fn detail_mut(&mut self) -> Option<&mut D> {
84 self.detail.as_mut()
85 }
86
87 #[inline]
89 pub fn set_detail(&mut self, detail: D) {
90 self.detail = Some(detail);
91 }
92
93 #[inline]
95 pub const fn take_detail(&mut self) -> Option<D> {
96 self.detail.take()
97 }
98
99 #[inline]
101 #[must_use]
102 pub fn into_parts(self) -> (V, Option<D>) {
103 (self.value, self.detail)
104 }
105}
106
107impl<V: Default, D> Default for DetailedField<V, D> {
108 fn default() -> Self {
109 Self {
110 value: V::default(),
111 detail: None,
112 }
113 }
114}
115
116impl<V, D> From<V> for DetailedField<V, D> {
117 fn from(value: V) -> Self {
118 Self::from_value(value)
119 }
120}
121
122impl<V, D> From<(V, D)> for DetailedField<V, D> {
123 fn from((value, detail): (V, D)) -> Self {
124 Self::with_detail(value, detail)
125 }
126}
127
128pub trait LimitedCollectionExt<T> {
145 fn try_push_limited(&mut self, item: T, limit: usize) -> bool;
149
150 fn is_at_limit(&self, limit: usize) -> bool;
152
153 fn remaining_capacity(&self, limit: usize) -> usize;
155}
156
157impl<T> LimitedCollectionExt<T> for Vec<T> {
158 #[inline]
159 fn try_push_limited(&mut self, item: T, limit: usize) -> bool {
160 if self.len() < limit {
161 self.push(item);
162 true
163 } else {
164 false
165 }
166 }
167
168 #[inline]
169 fn is_at_limit(&self, limit: usize) -> bool {
170 self.len() >= limit
171 }
172
173 #[inline]
174 #[allow(dead_code)]
175 fn remaining_capacity(&self, limit: usize) -> usize {
176 limit.saturating_sub(self.len())
177 }
178}
179
180pub trait FromAttributes: Sized {
185 fn from_attributes<'a, I>(attrs: I, max_attr_length: usize) -> Option<Self>
197 where
198 I: Iterator<Item = quick_xml::events::attributes::Attribute<'a>>;
199}
200
201pub trait ParseFrom<Source>: Sized {
220 fn parse_from(source: Source) -> Option<Self>;
231}
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236
237 #[test]
238 fn test_detailed_field_from_value() {
239 let field: DetailedField<String, i32> = DetailedField::from_value("test".to_string());
240 assert_eq!(field.value(), "test");
241 assert!(field.detail().is_none());
242 }
243
244 #[test]
245 fn test_detailed_field_with_detail() {
246 let field = DetailedField::with_detail("test".to_string(), 42);
247 assert_eq!(field.value(), "test");
248 assert_eq!(field.detail(), Some(&42));
249 }
250
251 #[test]
252 fn test_detailed_field_from_tuple() {
253 let field: DetailedField<String, i32> = ("test".to_string(), 42).into();
254 assert_eq!(field.value(), "test");
255 assert_eq!(field.detail(), Some(&42));
256 }
257
258 #[test]
259 fn test_detailed_field_into_parts() {
260 let field = DetailedField::with_detail("test".to_string(), 42);
261 let (value, detail) = field.into_parts();
262 assert_eq!(value, "test");
263 assert_eq!(detail, Some(42));
264 }
265
266 #[test]
267 fn test_limited_collection_try_push() {
268 let mut vec: Vec<i32> = Vec::new();
269 assert!(vec.try_push_limited(1, 3));
270 assert!(vec.try_push_limited(2, 3));
271 assert!(vec.try_push_limited(3, 3));
272 assert!(!vec.try_push_limited(4, 3));
273 assert_eq!(vec.len(), 3);
274 }
275
276 #[test]
277 fn test_limited_collection_is_at_limit() {
278 let mut vec: Vec<i32> = Vec::new();
279 assert!(!vec.is_at_limit(2));
280 vec.push(1);
281 assert!(!vec.is_at_limit(2));
282 vec.push(2);
283 assert!(vec.is_at_limit(2));
284 }
285
286 #[test]
287 fn test_limited_collection_remaining_capacity() {
288 let mut vec: Vec<i32> = Vec::new();
289 assert_eq!(vec.remaining_capacity(5), 5);
290 vec.push(1);
291 vec.push(2);
292 assert_eq!(vec.remaining_capacity(5), 3);
293 }
294
295 #[test]
296 fn test_detailed_field_default() {
297 let field: DetailedField<String, i32> = DetailedField::default();
298 assert_eq!(field.value(), "");
299 assert!(field.detail().is_none());
300 }
301
302 #[test]
303 fn test_detailed_field_mutability() {
304 let mut field = DetailedField::from_value("original".to_string());
305 *field.value_mut() = "modified".to_string();
306 assert_eq!(field.value(), "modified");
307
308 field.set_detail(100);
309 assert_eq!(field.detail(), Some(&100));
310
311 let taken = field.take_detail();
312 assert_eq!(taken, Some(100));
313 assert!(field.detail().is_none());
314 }
315}