use crate::*; use core::fmt; use core::iter::FusedIterator; macro_rules! slice { ( $( $(#[$attrs:meta])* $variant:ident($ty:ty), )* ) => { /// A slice containing primitive values. /// /// The `Slice` enum is used to pass multiple primitive-values to the /// [visitor][`Visit`]. This is used as an optimization when visiting /// [`Listable`] types to avoid a dynamic dispatch call to [`Visit`] for /// each element in the collection. /// /// `Slice` instances are usually not created explicitly. Instead, they /// are created when calling [`Valuable::visit_slice()`]. #[non_exhaustive] pub enum Slice<'a> { $( $(#[$attrs])* $variant(&'a [$ty]), )* } /// [`Slice`] iterator /// /// Instances are created by the [`iter()`][Slice::iter] method on /// [`Slice`]. See its documentation for more. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let slice = Slice::U32(&[1, 1, 2, 3, 5]); /// /// for value in slice.iter() { /// println!("{:?}", value); /// } /// ``` #[derive(Debug)] pub struct Iter<'a>(IterKind<'a>); #[derive(Debug)] enum IterKind<'a> { $( $(#[$attrs])* $variant(core::slice::Iter<'a, $ty>), )* } impl<'a> Slice<'a> { /// Returns the number of elements in the slice /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let slice = Slice::U32(&[1, 1, 2, 3, 5]); /// assert_eq!(5, slice.len()); /// ``` pub fn len(&self) -> usize { #[allow(unused_doc_comments)] match self { $( $(#[$attrs])* Slice::$variant(s) => s.len(), )* } } /// Returns `true` if the slice is not empty. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let slice = Slice::U32(&[1, 1, 2, 3, 5]); /// assert!(!slice.is_empty()); /// ``` /// ``` /// # use valuable::Slice; /// let slice = Slice::U32(&[]); /// assert!(slice.is_empty()); /// ``` pub fn is_empty(&self) -> bool { self.len() == 0 } /// Returns an iterator over the slice. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let slice = Slice::U32(&[1, 1, 2, 3, 5]); /// /// for value in slice.iter() { /// println!("{:?}", value); /// } /// ``` pub fn iter(&self) -> Iter<'a> { self.into_iter() } } impl<'a> IntoIterator for Slice<'a> { type Item = Value<'a>; type IntoIter = Iter<'a>; fn into_iter(self) -> Self::IntoIter { (&self).into_iter() } } impl<'a> IntoIterator for &'_ Slice<'a> { type Item = Value<'a>; type IntoIter = Iter<'a>; fn into_iter(self) -> Self::IntoIter { #[allow(unused_doc_comments)] Iter(match self { $( $(#[$attrs])* Slice::$variant(s) => IterKind::$variant(s.iter()), )* }) } } impl fmt::Debug for Slice<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { use Slice::*; let mut d = fmt.debug_list(); #[allow(unused_doc_comments)] match *self { $( $(#[$attrs])* $variant(v) => d.entries(v), )* }; d.finish() } } impl<'a> Iterator for Iter<'a> { type Item = Value<'a>; fn size_hint(&self) -> (usize, Option) { use IterKind::*; #[allow(unused_doc_comments)] match &self.0 { $( $(#[$attrs])* $variant(v) => v.size_hint(), )* } } fn next(&mut self) -> Option> { use IterKind::*; #[allow(unused_doc_comments)] match &mut self.0 { $( $(#[$attrs])* $variant(v) => v.next().map(Valuable::as_value), )* } } } impl DoubleEndedIterator for Iter<'_> { fn next_back(&mut self) -> Option { use IterKind::*; #[allow(unused_doc_comments)] match &mut self.0 { $( $(#[$attrs])* $variant(v) => v.next_back().map(Valuable::as_value), )* } } } impl ExactSizeIterator for Iter<'_> { fn len(&self) -> usize { use IterKind::*; #[allow(unused_doc_comments)] match &self.0 { $( $(#[$attrs])* $variant(v) => v.len(), )* } } } impl FusedIterator for Iter<'_> {} } } slice! { /// A slice containing `bool` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::Bool(&[true, true, false]); /// ``` Bool(bool), /// A slice containing `char` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::Char(&['a', 'b', 'c']); /// ``` Char(char), /// A slice containing `f32` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::F32(&[3.1415, 2.71828]); /// ``` F32(f32), /// A slice containing `f64` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::F64(&[3.1415, 2.71828]); /// ``` F64(f64), /// A slice containing `i8` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::I8(&[1, 1, 2, 3, 5]); /// ``` I8(i8), /// A slice containing `i16` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::I16(&[1, 1, 2, 3, 5]); /// ``` I16(i16), /// A slice containing `I32` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::I32(&[1, 1, 2, 3, 5]); /// ``` I32(i32), /// A slice containing `I64` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::I64(&[1, 1, 2, 3, 5]); /// ``` I64(i64), /// A slice containing `I128` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::I128(&[1, 1, 2, 3, 5]); /// ``` I128(i128), /// A slice containing `isize` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::Isize(&[1, 1, 2, 3, 5]); /// ``` Isize(isize), /// A slice containing `str` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::Str(&["foo", "bar", "baz"]); /// ``` Str(&'a str), /// A slice containing `String` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::String(&["foo".to_string(), "bar".to_string()]); /// ``` #[cfg(feature = "alloc")] String(alloc::string::String), /// A slice containing `u8` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::U8(&[1, 1, 2, 3, 5]); /// ``` U8(u8), /// A slice containing `u16` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::U16(&[1, 1, 2, 3, 5]); /// ``` U16(u16), /// A slice containing `u32` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::U32(&[1, 1, 2, 3, 5]); /// ``` U32(u32), /// A slice containing `u64` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::U64(&[1, 1, 2, 3, 5]); /// ``` U64(u64), /// A slice containing `u128` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::U128(&[1, 1, 2, 3, 5]); /// ``` U128(u128), /// A slice containing `usize` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::Usize(&[1, 1, 2, 3, 5]); /// ``` Usize(usize), /// A slice containing `()` values. /// /// # Examples /// /// ``` /// use valuable::Slice; /// /// let v = Slice::Unit(&[(), (), ()]); /// ``` Unit(()), }