use crate::{Valuable, Value, Visit}; use core::fmt; /// A tuple-like [`Valuable`] sub-type. /// /// Implemented by [`Valuable`] types that have a tuple-like shape. Fields are /// always unnamed. Values that implement `Tuplable` must return /// [`Value::Tuplable`] from their [`Valuable::as_value`] implementation. /// /// It is uncommon for users to implement this type as the crate provides /// implementations of `Tuplable` for Rust tuples. /// /// # Inspecting /// /// Inspecting fields contained by a `Tuplable` instance is done by visiting the /// tuple. When visiting a `Tuple`, the `visit_unnamed_fields()` method is /// called. When the tuple is statically defined, `visit_unnamed_fields()` is /// called once with the values of all the fields. A dynamic tuple /// implementation may call `visit_unnamed_fields()` multiple times. pub trait Tuplable: Valuable { /// Returns the tuple's definition. /// /// See [`TupleDef`] documentation for more details. /// /// # Examples /// /// ``` /// use valuable::{Tuplable, TupleDef}; /// /// let tuple = (123, "hello"); /// /// if let TupleDef::Static { fields, .. } = tuple.definition() { /// assert_eq!(2, fields); /// } /// ``` fn definition(&self) -> TupleDef; } /// The number of fields and other tuple-level information. /// /// Returned by [`Tuplable::definition()`], `TupleDef` provides the caller with /// information about the tuple's definition. /// /// This includes the number of fields contained by the tuple. #[derive(Debug)] #[non_exhaustive] pub enum TupleDef { /// The tuple is statically-defined, all fields are known ahead of time. /// /// Static tuple implementations are provided by the crate. /// /// # Examples /// /// A statically defined tuple. /// /// ``` /// use valuable::{Tuplable, TupleDef}; /// /// let tuple = (123, "hello"); /// /// match tuple.definition() { /// TupleDef::Static { fields, .. } => { /// assert_eq!(2, fields); /// } /// _ => unreachable!(), /// }; /// ``` #[non_exhaustive] Static { /// The number of fields contained by the tuple. fields: usize, }, /// The tuple is dynamically-defined, not all fields are known ahead of /// time. /// /// # Examples /// /// ``` /// use valuable::{Tuplable, TupleDef, Valuable, Value, Visit}; /// /// struct MyTuple; /// /// impl Valuable for MyTuple { /// fn as_value(&self) -> Value<'_> { /// Value::Tuplable(self) /// } /// /// fn visit(&self, visit: &mut dyn Visit) { /// visit.visit_unnamed_fields(&[Value::I32(123)]); /// visit.visit_unnamed_fields(&[Value::String("hello world")]); /// } /// } /// /// impl Tuplable for MyTuple { /// fn definition(&self) -> TupleDef { /// TupleDef::new_dynamic((1, Some(3))) /// } /// } /// ``` #[non_exhaustive] Dynamic { /// Returns the bounds on the number of tuple fields. /// /// Specifically, the first element is the lower bound, and the second /// element is the upper bound. fields: (usize, Option), }, } macro_rules! deref { ( $( $(#[$attrs:meta])* $ty:ty, )* ) => { $( $(#[$attrs])* impl Tuplable for $ty { fn definition(&self) -> TupleDef { T::definition(&**self) } } )* }; } deref! { &T, &mut T, #[cfg(feature = "alloc")] alloc::boxed::Box, #[cfg(feature = "alloc")] alloc::rc::Rc, #[cfg(not(valuable_no_atomic_cas))] #[cfg(feature = "alloc")] alloc::sync::Arc, } impl Tuplable for () { fn definition(&self) -> TupleDef { TupleDef::Static { fields: 0 } } } macro_rules! tuple_impls { ( $( $len:expr => ( $($n:tt $name:ident)+ ) )+ ) => { $( impl<$($name),+> Valuable for ($($name,)+) where $($name: Valuable,)+ { fn as_value(&self) -> Value<'_> { Value::Tuplable(self) } fn visit(&self, visit: &mut dyn Visit) { visit.visit_unnamed_fields(&[ $( self.$n.as_value(), )+ ]); } } impl<$($name),+> Tuplable for ($($name,)+) where $($name: Valuable,)+ { fn definition(&self) -> TupleDef { TupleDef::Static { fields: $len } } } )+ } } tuple_impls! { 1 => (0 T0) 2 => (0 T0 1 T1) 3 => (0 T0 1 T1 2 T2) 4 => (0 T0 1 T1 2 T2 3 T3) 5 => (0 T0 1 T1 2 T2 3 T3 4 T4) 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5) 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6) 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7) 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8) 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9) 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10) 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11) 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12) 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13) 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14) 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15) } impl fmt::Debug for dyn Tuplable + '_ { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { if self.definition().is_unit() { ().fmt(fmt) } else { struct DebugTuple<'a, 'b> { fmt: fmt::DebugTuple<'a, 'b>, } impl Visit for DebugTuple<'_, '_> { fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { for value in values { self.fmt.field(value); } } fn visit_value(&mut self, _: Value<'_>) { unimplemented!() } } let mut debug = DebugTuple { fmt: fmt.debug_tuple(""), }; self.visit(&mut debug); debug.fmt.finish() } } } impl TupleDef { /// Create a new [`TupleDef::Static`] instance /// /// This should be used when the tuple's fields are fixed and known ahead of time. /// /// # Examples /// /// ``` /// use valuable::TupleDef; /// /// let def = TupleDef::new_static(2); /// ``` pub const fn new_static(fields: usize) -> TupleDef { TupleDef::Static { fields } } /// Create a new [`TupleDef::Dynamic`] instance. /// /// This is used when the tuple's fields may vary at runtime. /// /// # Examples /// /// ``` /// use valuable::TupleDef; /// /// let def = TupleDef::new_dynamic((2, Some(10))); /// ``` pub const fn new_dynamic(fields: (usize, Option)) -> TupleDef { TupleDef::Dynamic { fields } } /// Returns `true` if `self` represents the [unit][primitive@unit] tuple. /// /// # Examples /// /// With the unit tuple /// /// ``` /// use valuable::Tuplable; /// /// let tuple: &dyn Tuplable = &(); /// assert!(tuple.definition().is_unit()); /// ``` /// /// When not the unit tuple. /// /// ``` /// use valuable::Tuplable; /// /// let tuple: &dyn Tuplable = &(123,456); /// assert!(!tuple.definition().is_unit()); /// ``` pub fn is_unit(&self) -> bool { match *self { TupleDef::Static { fields } => fields == 0, TupleDef::Dynamic { fields } => fields == (0, Some(0)), } } /// Returns `true` if the tuple is [statically defined](TupleDef::Static). /// /// # Examples /// /// With a static tuple /// /// ``` /// use valuable::TupleDef; /// /// let def = TupleDef::new_static(2); /// assert!(def.is_static()); /// ``` /// /// With a dynamic tuple /// /// ``` /// use valuable::TupleDef; /// /// let def = TupleDef::new_dynamic((2, None)); /// assert!(!def.is_static()); /// ``` pub fn is_static(&self) -> bool { matches!(self, TupleDef::Static { .. }) } /// Returns `true` if the tuple is [dynamically defined](TupleDef::Dynamic). /// /// # Examples /// /// With a static tuple /// /// ``` /// use valuable::TupleDef; /// /// let def = TupleDef::new_static(2); /// assert!(!def.is_dynamic()); /// ``` /// /// With a dynamic tuple /// /// ``` /// use valuable::TupleDef; /// /// let def = TupleDef::new_dynamic((2, None)); /// assert!(def.is_dynamic()); /// ``` pub fn is_dynamic(&self) -> bool { matches!(self, TupleDef::Dynamic { .. }) } }