use std::fmt::Debug;
#[derive(Debug, Clone, PartialEq, Eq)]
#[allow(dead_code)]
pub struct DetailedField<V, D> {
value: V,
detail: Option<D>,
}
impl<V, D> DetailedField<V, D> {
#[inline]
#[must_use]
pub const fn from_value(value: V) -> Self {
Self {
value,
detail: None,
}
}
#[inline]
#[must_use]
pub const fn with_detail(value: V, detail: D) -> Self {
Self {
value,
detail: Some(detail),
}
}
#[inline]
#[must_use]
pub const fn value(&self) -> &V {
&self.value
}
#[inline]
pub const fn value_mut(&mut self) -> &mut V {
&mut self.value
}
#[inline]
#[must_use]
pub const fn detail(&self) -> Option<&D> {
self.detail.as_ref()
}
#[inline]
pub const fn detail_mut(&mut self) -> Option<&mut D> {
self.detail.as_mut()
}
#[inline]
pub fn set_detail(&mut self, detail: D) {
self.detail = Some(detail);
}
#[inline]
pub const fn take_detail(&mut self) -> Option<D> {
self.detail.take()
}
#[inline]
#[must_use]
pub fn into_parts(self) -> (V, Option<D>) {
(self.value, self.detail)
}
}
impl<V: Default, D> Default for DetailedField<V, D> {
fn default() -> Self {
Self {
value: V::default(),
detail: None,
}
}
}
impl<V, D> From<V> for DetailedField<V, D> {
fn from(value: V) -> Self {
Self::from_value(value)
}
}
impl<V, D> From<(V, D)> for DetailedField<V, D> {
fn from((value, detail): (V, D)) -> Self {
Self::with_detail(value, detail)
}
}
pub trait LimitedCollectionExt<T> {
fn try_push_limited(&mut self, item: T, limit: usize) -> bool;
fn is_at_limit(&self, limit: usize) -> bool;
fn remaining_capacity(&self, limit: usize) -> usize;
}
impl<T> LimitedCollectionExt<T> for Vec<T> {
#[inline]
fn try_push_limited(&mut self, item: T, limit: usize) -> bool {
if self.len() < limit {
self.push(item);
true
} else {
false
}
}
#[inline]
fn is_at_limit(&self, limit: usize) -> bool {
self.len() >= limit
}
#[inline]
#[allow(dead_code)]
fn remaining_capacity(&self, limit: usize) -> usize {
limit.saturating_sub(self.len())
}
}
pub trait FromAttributes: Sized {
fn from_attributes<'a, I>(attrs: I, max_attr_length: usize) -> Option<Self>
where
I: Iterator<Item = quick_xml::events::attributes::Attribute<'a>>;
}
pub trait ParseFrom<Source>: Sized {
fn parse_from(source: Source) -> Option<Self>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_detailed_field_from_value() {
let field: DetailedField<String, i32> = DetailedField::from_value("test".to_string());
assert_eq!(field.value(), "test");
assert!(field.detail().is_none());
}
#[test]
fn test_detailed_field_with_detail() {
let field = DetailedField::with_detail("test".to_string(), 42);
assert_eq!(field.value(), "test");
assert_eq!(field.detail(), Some(&42));
}
#[test]
fn test_detailed_field_from_tuple() {
let field: DetailedField<String, i32> = ("test".to_string(), 42).into();
assert_eq!(field.value(), "test");
assert_eq!(field.detail(), Some(&42));
}
#[test]
fn test_detailed_field_into_parts() {
let field = DetailedField::with_detail("test".to_string(), 42);
let (value, detail) = field.into_parts();
assert_eq!(value, "test");
assert_eq!(detail, Some(42));
}
#[test]
fn test_limited_collection_try_push() {
let mut vec: Vec<i32> = Vec::new();
assert!(vec.try_push_limited(1, 3));
assert!(vec.try_push_limited(2, 3));
assert!(vec.try_push_limited(3, 3));
assert!(!vec.try_push_limited(4, 3));
assert_eq!(vec.len(), 3);
}
#[test]
fn test_limited_collection_is_at_limit() {
let mut vec: Vec<i32> = Vec::new();
assert!(!vec.is_at_limit(2));
vec.push(1);
assert!(!vec.is_at_limit(2));
vec.push(2);
assert!(vec.is_at_limit(2));
}
#[test]
fn test_limited_collection_remaining_capacity() {
let mut vec: Vec<i32> = Vec::new();
assert_eq!(vec.remaining_capacity(5), 5);
vec.push(1);
vec.push(2);
assert_eq!(vec.remaining_capacity(5), 3);
}
#[test]
fn test_detailed_field_default() {
let field: DetailedField<String, i32> = DetailedField::default();
assert_eq!(field.value(), "");
assert!(field.detail().is_none());
}
#[test]
fn test_detailed_field_mutability() {
let mut field = DetailedField::from_value("original".to_string());
*field.value_mut() = "modified".to_string();
assert_eq!(field.value(), "modified");
field.set_detail(100);
assert_eq!(field.detail(), Some(&100));
let taken = field.take_detail();
assert_eq!(taken, Some(100));
assert!(field.detail().is_none());
}
}