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