diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/valuable/src | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/valuable/src')
-rw-r--r-- | vendor/valuable/src/enumerable.rs | 682 | ||||
-rw-r--r-- | vendor/valuable/src/field.rs | 166 | ||||
-rw-r--r-- | vendor/valuable/src/lib.rs | 146 | ||||
-rw-r--r-- | vendor/valuable/src/listable.rs | 257 | ||||
-rw-r--r-- | vendor/valuable/src/mappable.rs | 191 | ||||
-rw-r--r-- | vendor/valuable/src/named_values.rs | 222 | ||||
-rw-r--r-- | vendor/valuable/src/slice.rs | 428 | ||||
-rw-r--r-- | vendor/valuable/src/structable.rs | 496 | ||||
-rw-r--r-- | vendor/valuable/src/tuplable.rs | 339 | ||||
-rw-r--r-- | vendor/valuable/src/valuable.rs | 339 | ||||
-rw-r--r-- | vendor/valuable/src/value.rs | 877 | ||||
-rw-r--r-- | vendor/valuable/src/visit.rs | 459 |
12 files changed, 4602 insertions, 0 deletions
diff --git a/vendor/valuable/src/enumerable.rs b/vendor/valuable/src/enumerable.rs new file mode 100644 index 000000000..3161f19f0 --- /dev/null +++ b/vendor/valuable/src/enumerable.rs @@ -0,0 +1,682 @@ +use crate::field::*; +use crate::*; + +#[cfg(feature = "alloc")] +use alloc::format; +use core::fmt; + +/// An enum-like [`Valuable`] sub-type. +/// +/// Implemented by [`Valuable`] types that have an enum-like shape. Fields may +/// be named or unnamed (tuple). Values that implement `Enumerable` must return +/// [`Value::Enumerable`] from their [`Valuable::as_value`] implementation. +/// +/// # Inspecting +/// +/// The [`variant()`] method returns the `Enumerable` instance's variant. The +/// `Enumerable` may also have unnamed fields (tuple) or named fields. +/// Inspecting the field values is done by visiting the enum. When visiting an +/// `Enumerable`, either the [`visit_named_fields()`] or the +/// [`visit_unnamed_fields()`] methods of [`Visit`] are called. Each method may +/// be called multiple times per `Enumerable`, but the two methods are never +/// mixed. +/// +/// [`variant()`]: Enumerable::variant +/// [`visit_named_fields()`]: Visit::visit_named_fields +/// [`visit_unnamed_fields()`]: Visit::visit_unnamed_fields +/// +/// ``` +/// use valuable::{Valuable, Value, Visit}; +/// +/// #[derive(Valuable)] +/// enum MyEnum { +/// Foo, +/// Bar(u32), +/// } +/// +/// struct PrintVariant; +/// +/// impl Visit for PrintVariant { +/// fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { +/// for value in values { +/// println!(" - {:?}", value); +/// } +/// } +/// +/// fn visit_value(&mut self, value: Value<'_>) { +/// match value { +/// Value::Enumerable(v) => { +/// println!("{}", v.variant().name()); +/// v.visit(self) +/// } +/// _ => {} +/// } +/// } +/// } +/// +/// let my_enum = MyEnum::Bar(123); +/// +/// valuable::visit(&my_enum, &mut PrintVariant); +/// ``` +/// +/// If the enum is **statically** defined, then all variants, and variant fields +/// are known ahead of time and may be accessed via the [`EnumDef`] instance +/// returned by [`definition()`]. +/// +/// [`definition()`]: Enumerable::definition +/// +/// # Implementing +/// +/// Implementing `Enumerable` is usually done by adding `#[derive(Valuable)]` to +/// a Rust `enum` definition. +/// +/// ``` +/// use valuable::{Valuable, Enumerable, EnumDef}; +/// +/// #[derive(Valuable)] +/// enum MyEnum { +/// Foo, +/// Bar(u32), +/// } +/// +/// let my_enum = MyEnum::Bar(123); +/// +/// let variants = match my_enum.definition() { +/// EnumDef::Static { name, variants, .. } => { +/// assert_eq!("MyEnum", name); +/// variants +/// } +/// _ => unreachable!(), +/// }; +/// +/// assert_eq!(2, variants.len()); +/// assert_eq!("Foo", variants[0].name()); +/// assert!(variants[0].fields().is_unnamed()); +/// ``` +pub trait Enumerable: Valuable { + /// Returns the enum's definition. + /// + /// See [`EnumDef`] documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use valuable::{Enumerable, Valuable}; + /// + /// #[derive(Valuable)] + /// enum MyEnum { + /// Foo, + /// Bar(u32), + /// } + /// + /// let my_enum = MyEnum::Bar(123); + /// + /// assert_eq!("MyEnum", my_enum.definition().name()); + /// ``` + fn definition(&self) -> EnumDef<'_>; + + /// Returns the `enum`'s current variant. + /// + /// # Examples + /// + /// ``` + /// use valuable::{Enumerable, Valuable}; + /// + /// #[derive(Valuable)] + /// enum MyEnum { + /// Foo, + /// Bar(u32), + /// } + /// + /// let my_enum = MyEnum::Foo; + /// assert_eq!("Foo", my_enum.variant().name()); + /// ``` + fn variant(&self) -> Variant<'_>; +} + +/// An enum's variants, variant fields, and other enum-level information. +/// +/// Returned by [`Enumerable::definition()`], `EnumDef` provides the caller with +/// information about the enum's definition. +#[non_exhaustive] +#[derive(Debug)] +pub enum EnumDef<'a> { + /// The enum is statically-defined, all variants and variant-level fields + /// are known ahead of time. + /// + /// Most `Enumerable` definitions for Rust enum types will be + /// `EnumDef::Static`. + /// + /// # Examples + /// + /// A statically defined enum + /// + /// ``` + /// use valuable::{Valuable, Enumerable, EnumDef}; + /// + /// #[derive(Valuable)] + /// enum MyEnum { + /// Foo, + /// Bar(u32), + /// } + /// + /// let my_enum = MyEnum::Bar(123); + /// + /// let variants = match my_enum.definition() { + /// EnumDef::Static { name, variants, .. } => { + /// assert_eq!("MyEnum", name); + /// variants + /// } + /// _ => unreachable!(), + /// }; + /// + /// assert_eq!(2, variants.len()); + /// assert_eq!("Foo", variants[0].name()); + /// assert_eq!("Bar", variants[1].name()); + /// ``` + #[non_exhaustive] + Static { + /// The enum's name + name: &'static str, + + /// The enum's variants + variants: &'static [VariantDef<'static>], + }, + + /// The enum is dynamically-defined, not all variants and fields are known + /// ahead of time. + /// + /// # Examples + /// + /// The enum variant is tracked as a string + /// + /// ``` + /// use valuable::{Enumerable, EnumDef, Fields, VariantDef, Valuable, Value, Variant, Visit}; + /// + /// /// A dynamic enum + /// struct DynEnum { + /// // The enum name + /// name: String, + /// + /// // The current variant + /// variant: String, + /// } + /// + /// impl Valuable for DynEnum { + /// fn as_value(&self) -> Value<'_> { + /// Value::Enumerable(self) + /// } + /// + /// fn visit(&self, _visit: &mut dyn Visit) { + /// // No variant fields, so there is nothing to call here. + /// } + /// } + /// + /// impl Enumerable for DynEnum { + /// fn definition(&self) -> EnumDef<'_> { + /// EnumDef::new_dynamic(&self.name, &[]) + /// } + /// + /// fn variant(&self) -> Variant<'_> { + /// Variant::Dynamic(VariantDef::new(&self.variant, Fields::Unnamed(0))) + /// } + /// } + /// ``` + #[non_exhaustive] + Dynamic { + /// The enum's name + name: &'a str, + + /// The enum's variants + variants: &'a [VariantDef<'a>], + }, +} + +/// An enum variant definition. +/// +/// Included with [`EnumDef`] returned by [`Enumerable::definition()`], +/// `VariantDef` provides the caller with information about a specific variant. +#[derive(Debug)] +pub struct VariantDef<'a> { + /// Variant name + name: &'a str, + + /// Variant fields + fields: Fields<'a>, +} + +/// An enum variant +/// +/// Returned by [`Enumerable::variant()`], `Variant` represents a single enum +/// variant. +#[derive(Debug)] +pub enum Variant<'a> { + /// The variant is statically defined by the associated enum. + Static(&'static VariantDef<'static>), + + /// The variant is dynamically defined and not included as part of + /// [`Enumerable::definition()`]. + Dynamic(VariantDef<'a>), +} + +impl<'a> EnumDef<'a> { + /// Create a new [`EnumDef::Static`] instance. + /// + /// This should be used when an enum's variants are fixed and known ahead of + /// time. + /// + /// # Examples + /// + /// ``` + /// use valuable::{EnumDef, Fields, VariantDef}; + /// + /// static VARIANTS: &[VariantDef<'static>] = &[ + /// VariantDef::new("Bar", Fields::Unnamed(1)), + /// ]; + /// + /// let def = EnumDef::new_static( "Foo", VARIANTS); + /// ``` + pub const fn new_static( + name: &'static str, + variants: &'static [VariantDef<'static>], + ) -> EnumDef<'a> { + EnumDef::Static { name, variants } + } + + /// Create a new [`EnumDef::Dynamic`] instance. + /// + /// This is used when the enum's variants may vary at runtime. + /// + /// # Examples + /// + /// ``` + /// use valuable::{EnumDef, Fields, VariantDef}; + /// + /// let def = EnumDef::new_dynamic( + /// "Foo", + /// &[VariantDef::new("Bar", Fields::Unnamed(1))] + /// ); + /// ``` + pub const fn new_dynamic(name: &'a str, variants: &'a [VariantDef<'a>]) -> EnumDef<'a> { + EnumDef::Dynamic { name, variants } + } + + /// Returns the enum's name + /// + /// # Examples + /// + /// ``` + /// use valuable::{Enumerable, Valuable}; + /// + /// #[derive(Valuable)] + /// enum Foo { + /// Bar, + /// Baz, + /// } + /// + /// let def = Foo::Bar.definition(); + /// assert_eq!("Foo", def.name()); + /// ``` + pub fn name(&self) -> &str { + match self { + EnumDef::Static { name, .. } => name, + EnumDef::Dynamic { name, .. } => name, + } + } + + /// Returns the enum's variants + /// + /// # Examples + /// + /// ``` + /// use valuable::{Enumerable, Valuable}; + /// + /// #[derive(Valuable)] + /// enum Foo { + /// Bar, + /// Baz, + /// } + /// + /// let def = Foo::Bar.definition(); + /// let variants = def.variants(); + /// + /// assert_eq!(2, variants.len()); + /// assert_eq!("Bar", variants[0].name()); + /// ``` + pub fn variants(&self) -> &[VariantDef<'_>] { + match self { + EnumDef::Static { variants, .. } => variants, + EnumDef::Dynamic { variants, .. } => variants, + } + } + + /// Returns `true` if the enum is [statically defined](EnumDef::Static). + /// + /// # Examples + /// + /// With a static enum + /// + /// ``` + /// use valuable::{Enumerable, Valuable}; + /// + /// #[derive(Valuable)] + /// enum Foo { + /// Bar, + /// Baz, + /// } + /// + /// let def = Foo::Bar.definition(); + /// assert!(def.is_static()); + /// ``` + /// + /// With a dynamic enum + /// + /// ``` + /// use valuable::{EnumDef, Fields, VariantDef}; + /// + /// let def = EnumDef::new_dynamic("Foo", &[]); + /// assert!(!def.is_static()); + /// ``` + pub fn is_static(&self) -> bool { + matches!(self, EnumDef::Static { .. }) + } + + /// Returns `true` if the enum is [dynamically defined](EnumDef::Dynamic). + /// + /// # Examples + /// + /// With a static enum + /// + /// ``` + /// use valuable::{Enumerable, Valuable}; + /// + /// #[derive(Valuable)] + /// enum Foo { + /// Bar, + /// Baz, + /// } + /// + /// let def = Foo::Bar.definition(); + /// assert!(!def.is_dynamic()); + /// ``` + /// + /// With a dynamic enum + /// + /// ``` + /// use valuable::{EnumDef, Fields, VariantDef}; + /// + /// let def = EnumDef::new_dynamic("Foo", &[]); + /// assert!(def.is_dynamic()); + /// ``` + pub fn is_dynamic(&self) -> bool { + matches!(self, EnumDef::Dynamic { .. }) + } +} + +impl<'a> VariantDef<'a> { + /// Creates a new `VariantDef` instance. + /// + /// # Examples + /// + /// ``` + /// use valuable::{Fields, VariantDef}; + /// + /// let def = VariantDef::new("Foo", Fields::Unnamed(2)); + /// ``` + pub const fn new(name: &'a str, fields: Fields<'a>) -> VariantDef<'a> { + VariantDef { name, fields } + } + + /// Returns the variant's name + /// + /// # Examples + /// + /// ``` + /// use valuable::{Fields, VariantDef}; + /// + /// let def = VariantDef::new("Foo", Fields::Unnamed(2)); + /// assert_eq!("Foo", def.name()); + /// ``` + pub fn name(&self) -> &str { + self.name + } + + /// Returns the variant's fields + /// + /// # Examples + /// + /// ``` + /// use valuable::{Fields, VariantDef}; + /// + /// let def = VariantDef::new("Foo", Fields::Unnamed(3)); + /// assert!(matches!(def.fields(), Fields::Unnamed(_))); + /// ``` + pub fn fields(&self) -> &Fields<'_> { + &self.fields + } +} + +impl Variant<'_> { + /// Returns the variant's name + /// + /// # Examples + /// + /// ``` + /// use valuable::{Fields, Variant, VariantDef}; + /// + /// static VARIANT: &VariantDef<'static> = &VariantDef::new( + /// "Foo", Fields::Unnamed(2)); + /// + /// let variant = Variant::Static(VARIANT); + /// assert_eq!("Foo", variant.name()); + /// ``` + pub fn name(&self) -> &str { + match self { + Variant::Static(v) => v.name(), + Variant::Dynamic(v) => v.name(), + } + } + + /// Returns the variant's fields + pub fn fields(&self) -> &Fields<'_> { + match self { + Variant::Static(v) => v.fields(), + Variant::Dynamic(v) => v.fields(), + } + } + + /// Returns `true` if the variant has associated named fields. + /// + /// # Examples + /// + /// With named fields + /// + /// ``` + /// use valuable::{Fields, NamedField, Variant, VariantDef}; + /// + /// static VARIANT: &VariantDef<'static> = &VariantDef::new( + /// "Foo", Fields::Named(&[NamedField::new("hello")])); + /// + /// let variant = Variant::Static(VARIANT); + /// assert!(variant.is_named_fields()); + /// ``` + /// + /// With unnamed fields + /// + /// ``` + /// use valuable::{Fields, Variant, VariantDef}; + /// + /// static VARIANT: &VariantDef<'static> = &VariantDef::new( + /// "Foo", Fields::Unnamed(1)); + /// + /// let variant = Variant::Static(VARIANT); + /// assert!(!variant.is_named_fields()); + /// ``` + pub fn is_named_fields(&self) -> bool { + self.fields().is_named() + } + + /// Returns `true` if the variant has associated unnamed fields. + /// + /// # Examples + /// + /// With named fields + /// + /// ``` + /// use valuable::{Fields, NamedField, Variant, VariantDef}; + /// + /// static VARIANT: &VariantDef<'static> = &VariantDef::new( + /// "Foo", Fields::Named(&[NamedField::new("hello")])); + /// + /// let variant = Variant::Static(VARIANT); + /// assert!(!variant.is_unnamed_fields()); + /// ``` + /// + /// With unnamed fields + /// + /// ``` + /// use valuable::{Fields, Variant, VariantDef}; + /// + /// static VARIANT: &VariantDef<'static> = &VariantDef::new( + /// "Foo", Fields::Unnamed(1)); + /// + /// let variant = Variant::Static(VARIANT); + /// assert!(variant.is_unnamed_fields()); + /// ``` + pub fn is_unnamed_fields(&self) -> bool { + !self.is_named_fields() + } +} + +impl fmt::Debug for dyn Enumerable + '_ { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let variant = self.variant(); + #[cfg(feature = "alloc")] + let name = format!("{}::{}", self.definition().name(), variant.name()); + #[cfg(not(feature = "alloc"))] + let name = variant.name(); + + if variant.is_named_fields() { + struct DebugEnum<'a, 'b> { + fmt: fmt::DebugStruct<'a, 'b>, + } + + let mut debug = DebugEnum { + fmt: fmt.debug_struct(&name), + }; + + impl Visit for DebugEnum<'_, '_> { + fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { + for (field, value) in named_values { + self.fmt.field(field.name(), value); + } + } + + fn visit_value(&mut self, _: Value<'_>) { + unreachable!(); + } + } + + self.visit(&mut debug); + + debug.fmt.finish() + } else { + struct DebugEnum<'a, 'b> { + fmt: fmt::DebugTuple<'a, 'b>, + } + + let mut debug = DebugEnum { + fmt: fmt.debug_tuple(&name), + }; + + impl Visit for DebugEnum<'_, '_> { + fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { + for value in values { + self.fmt.field(value); + } + } + + fn visit_value(&mut self, _: Value<'_>) { + unreachable!(); + } + } + + self.visit(&mut debug); + + debug.fmt.finish() + } + } +} + +macro_rules! deref { + ( + $( + $(#[$attrs:meta])* + $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<T: ?Sized + Enumerable> Enumerable for $ty { + fn definition(&self) -> EnumDef<'_> { + T::definition(&**self) + } + + fn variant(&self) -> Variant<'_> { + T::variant(&**self) + } + } + )* + }; +} + +deref! { + &T, + &mut T, + #[cfg(feature = "alloc")] + alloc::boxed::Box<T>, + #[cfg(feature = "alloc")] + alloc::rc::Rc<T>, + #[cfg(not(valuable_no_atomic_cas))] + #[cfg(feature = "alloc")] + alloc::sync::Arc<T>, +} + +static RESULT_VARIANTS: &[VariantDef<'static>] = &[ + VariantDef::new("Ok", Fields::Unnamed(1)), + VariantDef::new("Err", Fields::Unnamed(1)), +]; + +impl<T, E> Enumerable for Result<T, E> +where + T: Valuable, + E: Valuable, +{ + fn definition(&self) -> EnumDef<'_> { + EnumDef::new_static("Result", RESULT_VARIANTS) + } + + fn variant(&self) -> Variant<'_> { + match self { + Ok(_) => Variant::Static(&RESULT_VARIANTS[0]), + Err(_) => Variant::Static(&RESULT_VARIANTS[1]), + } + } +} + +impl<T, E> Valuable for Result<T, E> +where + T: Valuable, + E: Valuable, +{ + fn as_value(&self) -> Value<'_> { + Value::Enumerable(self) + } + + fn visit(&self, visitor: &mut dyn Visit) { + match self { + Ok(val) => visitor.visit_unnamed_fields(&[val.as_value()]), + Err(val) => visitor.visit_unnamed_fields(&[val.as_value()]), + } + } +} diff --git a/vendor/valuable/src/field.rs b/vendor/valuable/src/field.rs new file mode 100644 index 000000000..faa00f420 --- /dev/null +++ b/vendor/valuable/src/field.rs @@ -0,0 +1,166 @@ +/// Data stored within a `Structable` or an `Enumerable`. +#[derive(Debug)] +pub enum Fields<'a> { + /// Named fields + Named(&'a [NamedField<'a>]), + + /// Unnamed (positional) fields or unit + /// + /// The `usize` value represents the number of fields. + Unnamed(usize), +} + +/// A named field +#[derive(Debug, Clone, Copy)] +pub struct NamedField<'a>(&'a str); + +impl Fields<'_> { + /// Returns `true` if the fields are named. + /// + /// # Examples + /// + /// Named fields + /// + /// ``` + /// use valuable::Fields; + /// + /// let fields = Fields::Named(&[]); + /// assert!(fields.is_named()); + /// ``` + /// + /// Unnamed fields + /// + /// ``` + /// use valuable::Fields; + /// + /// let fields = Fields::Unnamed(2); + /// assert!(!fields.is_named()); + /// ``` + pub const fn is_named(&self) -> bool { + matches!(self, Fields::Named(..)) + } + + /// Returns `true` if the fields are unnamed. + /// + /// # Examples + /// + /// Named fields + /// + /// ``` + /// use valuable::Fields; + /// + /// let fields = Fields::Named(&[]); + /// assert!(!fields.is_unnamed()); + /// ``` + /// + /// Unnamed fields + /// + /// ``` + /// use valuable::Fields; + /// + /// let fields = Fields::Unnamed(3); + /// assert!(fields.is_unnamed()); + /// ``` + pub const fn is_unnamed(&self) -> bool { + matches!(self, Fields::Unnamed(_)) + } + + /// Returns the number of fields. + /// + /// # Examples + /// + /// Named fields + /// + /// ``` + /// use valuable::{Fields, NamedField}; + /// + /// let fields = &[ + /// NamedField::new("alice"), + /// NamedField::new("bob"), + /// ]; + /// let fields = Fields::Named(fields); + /// + /// assert_eq!(fields.len(), 2); + /// ``` + /// + /// Unnamed fields + /// + /// ``` + /// use valuable::Fields; + /// + /// let fields = Fields::Unnamed(2); + /// assert_eq!(fields.len(), 2); + /// ``` + pub const fn len(&self) -> usize { + match self { + Self::Named(names) => names.len(), + Self::Unnamed(len) => *len, + } + } + + /// Returns `true` if this set of fields defines no fields. + /// + /// # Examples + /// + /// Named fields + /// + /// ``` + /// use valuable::{Fields, NamedField}; + /// + /// let fields = &[ + /// NamedField::new("alice"), + /// NamedField::new("bob"), + /// ]; + /// let non_empty = Fields::Named(fields); + /// + /// let empty = Fields::Named(&[]); + /// + /// assert!(!non_empty.is_empty()); + /// assert!(empty.is_empty()); + /// ``` + /// + /// Unnamed fields + /// + /// ``` + /// use valuable::Fields; + /// + /// let non_empty = Fields::Unnamed(2); + /// let empty = Fields::Unnamed(0); + /// + /// assert!(!non_empty.is_empty()); + /// assert!(empty.is_empty()); + /// ``` + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +impl<'a> NamedField<'a> { + /// Create a new `NamedField` instance with the given name. + /// + /// # Examples + /// + /// ``` + /// use valuable::NamedField; + /// + /// let field = NamedField::new("hello"); + /// assert_eq!("hello", field.name()); + /// ``` + pub const fn new(name: &'a str) -> NamedField<'a> { + NamedField(name) + } + + /// Returns the field name + /// + /// # Examples + /// + /// ``` + /// use valuable::NamedField; + /// + /// let field = NamedField::new("hello"); + /// assert_eq!("hello", field.name()); + /// ``` + pub const fn name(&self) -> &str { + self.0 + } +} diff --git a/vendor/valuable/src/lib.rs b/vendor/valuable/src/lib.rs new file mode 100644 index 000000000..5ba6341a0 --- /dev/null +++ b/vendor/valuable/src/lib.rs @@ -0,0 +1,146 @@ +#![warn( + missing_debug_implementations, + missing_docs, + rust_2018_idioms, + unreachable_pub +)] +//! Valuable provides object-safe value inspection. Use cases include passing +//! structured data to trait objects and object-safe serialization. +//! +//! # Getting started +//! +//! First, derive [`Valuable`][macro@crate::Valuable] on your types. +//! +//! ``` +//! use valuable::Valuable; +//! +//! #[derive(Valuable)] +//! struct HelloWorld { +//! message: Message, +//! } +//! +//! #[derive(Valuable)] +//! enum Message { +//! HelloWorld, +//! Custom(String), +//! } +//! ``` +//! +//! Then, implement a [visitor][Visit] to inspect the data. +//! +//! ``` +//! use valuable::{NamedValues, Value, Valuable, Visit}; +//! +//! struct Print; +//! +//! impl Visit for Print { +//! fn visit_value(&mut self, value: Value<'_>) { +//! match value { +//! Value::Structable(v) => { +//! println!("struct {}", v.definition().name()); +//! v.visit(self); +//! } +//! Value::Enumerable(v) => { +//! println!("enum {}::{}", v.definition().name(), v.variant().name()); +//! v.visit(self); +//! } +//! Value::Listable(v) => { +//! println!("list"); +//! v.visit(self); +//! } +//! Value::Mappable(v) => { +//! println!("map"); +//! v.visit(self); +//! } +//! _ => { +//! println!("value {:?}", value); +//! } +//! } +//! } +//! +//! fn visit_named_fields(&mut self, named_fields: &NamedValues<'_>) { +//! for (field, value) in named_fields.iter() { +//! println!("named field {}", field.name()); +//! value.visit(self); +//! } +//! } +//! +//! fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { +//! for value in values { +//! value.visit(self); +//! } +//! } +//! +//! fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) { +//! println!("key / value"); +//! key.visit(self); +//! value.visit(self); +//! } +//! } +//! ``` +//! +//! Then, use the visitor to visit the value. +//! +//! ``` +//! # use valuable::*; +//! # #[derive(Valuable)] +//! # struct HelloWorld { message: Message } +//! # #[derive(Valuable)] +//! # enum Message { HelloWorld } +//! # struct Print; +//! # impl Visit for Print { +//! # fn visit_value(&mut self, _: Value<'_>) {} +//! # } +//! let hello_world = HelloWorld { message: Message::HelloWorld }; +//! hello_world.visit(&mut Print); +//! ``` + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg, doc_cfg_hide))] +#![cfg_attr( + docsrs, + doc(cfg_hide( + not(valuable_no_atomic_cas), + not(valuable_no_atomic), + not(valuable_no_atomic_64) + )) +)] + +#[cfg(feature = "alloc")] +extern crate alloc; + +mod enumerable; +pub use enumerable::{EnumDef, Enumerable, Variant, VariantDef}; + +mod field; +pub use field::{Fields, NamedField}; + +mod listable; +pub use listable::Listable; + +mod mappable; +pub use mappable::Mappable; + +mod named_values; +pub use named_values::NamedValues; + +mod slice; +pub use slice::Slice; + +mod structable; +pub use structable::{StructDef, Structable}; + +mod tuplable; +pub use tuplable::{Tuplable, TupleDef}; + +mod valuable; +pub use crate::valuable::Valuable; + +mod value; +pub use value::Value; + +mod visit; +pub use visit::{visit, Visit}; + +#[cfg(feature = "derive")] +pub use valuable_derive::Valuable; diff --git a/vendor/valuable/src/listable.rs b/vendor/valuable/src/listable.rs new file mode 100644 index 000000000..b79317f9c --- /dev/null +++ b/vendor/valuable/src/listable.rs @@ -0,0 +1,257 @@ +use crate::*; + +use core::fmt; + +/// A list-like [`Valuable`] sub-type. +/// +/// Implemented by [`Valuable`] types that have a list-like shape. This includes +/// [`Vec`] and other Rust [collection] types. `Listable` types may or may not +/// store items in contiguous memory. Any type that implements [`IntoIterator`] +/// may implement `Listable`. Values that implement `Listable` must return +/// [`Value::Listable`] from their [`Valuable::as_value`] implementation. +/// +/// [collection]: https://doc.rust-lang.org/stable/std/collections/index.html +/// +/// # Inspecting +/// +/// Inspecting `Listable` items is done by visiting the collection. When +/// visiting a `Listable`, contained values are either passed one-by-one by +/// repeatedly calling [`visit_value()`] or all at once by calling +/// [`visit_primitive_slice()`]. The [`visit_primitive_slice()`] method has +/// lower overhead but can only be used when the `Listable` type contains +/// primitive values. +/// +/// See [`Visit`] documentation for more details. +/// +/// # Implementing +/// +/// If the type stores values in slices internally, then those slices are passed +/// to [`Valuable::visit_slice`], which handles calling +/// [`visit_primitive_slice()`] if possible. +/// +/// [`visit_value()`]: Visit::visit_value +/// [`visit_primitive_slice()`]: Visit::visit_primitive_slice +/// +/// ``` +/// use valuable::{Listable, Valuable, Value, Visit}; +/// +/// struct MyCollection<T> { +/// chunks: Vec<Vec<T>>, +/// } +/// +/// impl<T: Valuable> Valuable for MyCollection<T> { +/// fn as_value(&self) -> Value<'_> { +/// Value::Listable(self) +/// } +/// +/// fn visit(&self, visit: &mut dyn Visit) { +/// for chunk in &self.chunks { +/// // Handles visiting the slice +/// Valuable::visit_slice(chunk, visit); +/// } +/// } +/// } +/// +/// impl<T: Valuable> Listable for MyCollection<T> { +/// fn size_hint(&self) -> (usize, Option<usize>) { +/// let len = self.chunks.iter().map(|chunk| chunk.len()).sum(); +/// (len, Some(len)) +/// } +/// } +/// ``` +pub trait Listable: Valuable { + /// Returns the bounds on the remaining length of the `Listable`. + /// + /// Specifically, `size_hint()` returns a tuple where the first element + /// is the lower bound, and the second element is the upper bound. + /// + /// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`. + /// A [`None`] here means that either there is no known upper bound, or the + /// upper bound is larger than [`usize`]. + /// + /// # Implementation notes + /// + /// It is not enforced that a `Listable` implementation yields the declared + /// number of elements. A buggy iterator may yield less than the lower bound + /// or more than the upper bound of elements. + /// + /// `size_hint()` is primarily intended to be used for optimizations such as + /// reserving space for the elements of the `Listable`, but must not be + /// trusted to e.g., omit bounds checks in unsafe code. An incorrect + /// implementation of `size_hint()` should not lead to memory safety + /// violations. + /// + /// That said, the implementation should provide a correct estimation, + /// because otherwise it would be a violation of the trait's protocol. + /// + /// [`usize`]: type@usize + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use valuable::Listable; + /// + /// let a = vec![1, 2, 3]; + /// + /// assert_eq!((3, Some(3)), a.size_hint()); + /// ``` + fn size_hint(&self) -> (usize, Option<usize>); +} + +macro_rules! deref { + ( + $( + $(#[$attrs:meta])* + $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<T: ?Sized + Listable> Listable for $ty { + fn size_hint(&self) -> (usize, Option<usize>) { + T::size_hint(&**self) + } + } + )* + }; +} + +deref! { + &T, + &mut T, + #[cfg(feature = "alloc")] + alloc::boxed::Box<T>, + #[cfg(feature = "alloc")] + alloc::rc::Rc<T>, + #[cfg(not(valuable_no_atomic_cas))] + #[cfg(feature = "alloc")] + alloc::sync::Arc<T>, +} + +macro_rules! slice { + ( + $( + $(#[$attrs:meta])* + ($($generics:tt)*) $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<$($generics)*> Valuable for $ty { + fn as_value(&self) -> Value<'_> { + Value::Listable(self as &dyn Listable) + } + + fn visit(&self, visit: &mut dyn Visit) { + T::visit_slice(self, visit); + } + } + + $(#[$attrs])* + impl<$($generics)*> Listable for $ty { + fn size_hint(&self) -> (usize, Option<usize>) { + (self.len(), Some(self.len())) + } + } + )* + }; +} + +slice! { + (T: Valuable) &'_ [T], + #[cfg(feature = "alloc")] + (T: Valuable) alloc::boxed::Box<[T]>, + #[cfg(feature = "alloc")] + (T: Valuable) alloc::rc::Rc<[T]>, + #[cfg(not(valuable_no_atomic_cas))] + #[cfg(feature = "alloc")] + (T: Valuable) alloc::sync::Arc<[T]>, + (T: Valuable, const N: usize) [T; N], + #[cfg(feature = "alloc")] + (T: Valuable) alloc::vec::Vec<T>, +} + +macro_rules! collection { + ( + $( + $(#[$attrs:meta])* + ($($generics:tt)*) $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<$($generics)*> Valuable for $ty { + fn as_value(&self) -> Value<'_> { + Value::Listable(self as &dyn Listable) + } + + fn visit(&self, visit: &mut dyn Visit) { + for value in self.iter() { + visit.visit_value(value.as_value()); + } + } + } + + $(#[$attrs])* + impl<$($generics)*> Listable for $ty { + fn size_hint(&self) -> (usize, Option<usize>) { + (self.len(), Some(self.len())) + } + } + )* + }; +} + +collection! { + #[cfg(feature = "alloc")] + (T: Valuable) alloc::collections::LinkedList<T>, + #[cfg(feature = "alloc")] + (T: Valuable + Ord) alloc::collections::BinaryHeap<T>, + #[cfg(feature = "alloc")] + (T: Valuable + Ord) alloc::collections::BTreeSet<T>, + #[cfg(feature = "std")] + (T: Valuable + Eq + std::hash::Hash, H: std::hash::BuildHasher) std::collections::HashSet<T, H>, +} + +#[cfg(feature = "alloc")] +impl<T: Valuable> Valuable for alloc::collections::VecDeque<T> { + fn as_value(&self) -> Value<'_> { + Value::Listable(self as &dyn Listable) + } + + fn visit(&self, visit: &mut dyn Visit) { + let (first, second) = self.as_slices(); + T::visit_slice(first, visit); + T::visit_slice(second, visit); + } +} + +#[cfg(feature = "alloc")] +impl<T: Valuable> Listable for alloc::collections::VecDeque<T> { + fn size_hint(&self) -> (usize, Option<usize>) { + (self.len(), Some(self.len())) + } +} + +impl fmt::Debug for dyn Listable + '_ { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + struct DebugListable<'a, 'b> { + fmt: fmt::DebugList<'a, 'b>, + } + + impl Visit for DebugListable<'_, '_> { + fn visit_value(&mut self, value: Value<'_>) { + self.fmt.entry(&value); + } + } + + let mut debug = DebugListable { + fmt: fmt.debug_list(), + }; + + self.visit(&mut debug); + debug.fmt.finish() + } +} diff --git a/vendor/valuable/src/mappable.rs b/vendor/valuable/src/mappable.rs new file mode 100644 index 000000000..c7c30bf0b --- /dev/null +++ b/vendor/valuable/src/mappable.rs @@ -0,0 +1,191 @@ +use crate::*; + +use core::fmt; + +/// A map-like [`Valuable`] sub-type. +/// +/// Implemented by [`Valuable`] types that have a map-like shape. This includes +/// [`HashMap`] and other Rust [collection] types. Values that implement +/// `Mappable` must return [`Value::Mappable`] from their [`Value::as_value`] +/// implementation. +/// +/// [collection]: https://doc.rust-lang.org/stable/std/collections/index.html +/// +/// # Inspecting +/// +/// Inspecting `Mappable` entries is done by visiting the value. When visiting a +/// `Mappable`, contained entries are passed one-by-one to the visitor by +/// repeatedly calling [`visit_entry()`]. +/// +/// See [`Visit`] documentation for more details. +/// +/// [`visit_entry()`]: Visit::visit_entry +/// [`HashMap`]: std::collections::HashMap +/// +/// # Implementing +/// +/// Implementing `Mappable` for a custom map type. The map is represented using +/// a `Vec` of key/value pairs. +/// +/// ``` +/// use valuable::{Mappable, Valuable, Value, Visit}; +/// +/// struct MyMap<K, V> { +/// entries: Vec<(K, V)>, +/// } +/// +/// impl<K: Valuable, V: Valuable> Valuable for MyMap<K, V> { +/// fn as_value(&self) -> Value<'_> { +/// Value::Mappable(self) +/// } +/// +/// fn visit(&self, visit: &mut dyn Visit) { +/// for (k, v) in &self.entries { +/// visit.visit_entry(k.as_value(), v.as_value()); +/// } +/// } +/// } +/// +/// impl<K: Valuable, V: Valuable> Mappable for MyMap<K, V> { +/// fn size_hint(&self) -> (usize, Option<usize>) { +/// let len = self.entries.len(); +/// (len, Some(len)) +/// } +/// } +/// ``` +pub trait Mappable: Valuable { + /// Returns the bounds on the remaining length of the `Mappable`. + /// + /// Specifically, `size_hint()` returns a tuple where the first element is + /// the lower bound, and the second element is the upper bound. + /// + /// The second half of the tuple that is returned is an + /// [`Option`]`<`[`usize`]`>`. A [`None`] here means that either there is no + /// known upper bound, or the upper bound is larger than [`usize`]. + /// + /// # Implementation notes + /// + /// It is not enforced that a `Mappable` implementation yields the declared + /// number of elements. A buggy implementation may yield less than the lower + /// bound or more than the upper bound of elements. + /// + /// `size_hint()` is primarily intended to be used for optimizations such as + /// reserving space for the elements of the `Mappable`, but must not be + /// trusted to e.g., omit bounds checks in unsafe code. An incorrect + /// implementation of `size_hint()` should not lead to memory safety + /// violations. + /// + /// That said, the implementation should provide a correct estimation, + /// because otherwise it would be a violation of the trait's protocol. + /// + /// [`usize`]: type@usize + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use valuable::Mappable; + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("one", 1); + /// map.insert("two", 2); + /// map.insert("three", 3); + /// + /// assert_eq!((3, Some(3)), map.size_hint()); + /// ``` + fn size_hint(&self) -> (usize, Option<usize>); +} + +macro_rules! deref { + ( + $( + $(#[$attrs:meta])* + $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<T: ?Sized + Mappable> Mappable for $ty { + fn size_hint(&self) -> (usize, Option<usize>) { + T::size_hint(&**self) + } + } + )* + }; +} + +deref! { + &T, + &mut T, + #[cfg(feature = "alloc")] + alloc::boxed::Box<T>, + #[cfg(feature = "alloc")] + alloc::rc::Rc<T>, + #[cfg(not(valuable_no_atomic_cas))] + #[cfg(feature = "alloc")] + alloc::sync::Arc<T>, +} + +#[cfg(feature = "std")] +impl<K: Valuable, V: Valuable> Valuable for std::collections::HashMap<K, V> { + fn as_value(&self) -> Value<'_> { + Value::Mappable(self) + } + + fn visit(&self, visit: &mut dyn Visit) { + for (key, value) in self.iter() { + visit.visit_entry(key.as_value(), value.as_value()); + } + } +} + +#[cfg(feature = "std")] +impl<K: Valuable, V: Valuable> Mappable for std::collections::HashMap<K, V> { + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter().size_hint() + } +} + +#[cfg(feature = "alloc")] +impl<K: Valuable, V: Valuable> Valuable for alloc::collections::BTreeMap<K, V> { + fn as_value(&self) -> Value<'_> { + Value::Mappable(self) + } + + fn visit(&self, visit: &mut dyn Visit) { + for (key, value) in self.iter() { + visit.visit_entry(key.as_value(), value.as_value()); + } + } +} + +#[cfg(feature = "alloc")] +impl<K: Valuable, V: Valuable> Mappable for alloc::collections::BTreeMap<K, V> { + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter().size_hint() + } +} + +impl fmt::Debug for dyn Mappable + '_ { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + struct DebugMappable<'a, 'b> { + fmt: fmt::DebugMap<'a, 'b>, + } + + impl Visit for DebugMappable<'_, '_> { + fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) { + self.fmt.entry(&key, &value); + } + + fn visit_value(&mut self, _: Value<'_>) {} + } + + let mut debug = DebugMappable { + fmt: fmt.debug_map(), + }; + self.visit(&mut debug); + debug.fmt.finish() + } +} diff --git a/vendor/valuable/src/named_values.rs b/vendor/valuable/src/named_values.rs new file mode 100644 index 000000000..4f436522a --- /dev/null +++ b/vendor/valuable/src/named_values.rs @@ -0,0 +1,222 @@ +use core::iter::{self, FusedIterator}; + +use crate::field::*; +use crate::*; + +/// Set of values from a `Structable` or `Enumerable` with named fields. +#[derive(Debug)] +pub struct NamedValues<'a> { + fields: &'a [NamedField<'a>], + values: &'a [Value<'a>], +} + +impl<'a> NamedValues<'a> { + /// Create a new `NamedValues` instance. + /// + /// Both `fields` and `values` must be the same length. + /// + /// # Panics + /// + /// The method panics if `fields` and `values` are different lengths. + /// + /// # Examples + /// + /// ``` + /// use valuable::{NamedField, NamedValues, Value}; + /// + /// let fields = [ + /// NamedField::new("foo"), + /// NamedField::new("bar") + /// ]; + /// let values = [ + /// Value::U32(123), + /// Value::U32(456), + /// ]; + /// + /// let named_values = NamedValues::new(&fields, &values); + /// + /// assert_eq!( + /// named_values.get(&fields[0]).unwrap().as_u32(), + /// Some(123)); + /// ``` + pub fn new(fields: &'a [NamedField<'a>], values: &'a [Value<'a>]) -> NamedValues<'a> { + assert!( + fields.len() == values.len(), + "`fields` and `values` must be the same length" + ); + NamedValues { fields, values } + } + + /// Get a value using a `NamedField` reference. + /// + /// # Examples + /// + /// ``` + /// use valuable::{NamedField, NamedValues, Value}; + /// + /// let fields = [ + /// NamedField::new("foo"), + /// NamedField::new("bar") + /// ]; + /// let values = [ + /// Value::U32(123), + /// Value::U32(456), + /// ]; + /// + /// let named_values = NamedValues::new(&fields, &values); + /// + /// assert_eq!( + /// named_values.get(&fields[0]).unwrap().as_u32(), + /// Some(123)); + /// ``` + pub fn get(&self, field: &NamedField<'_>) -> Option<&Value<'_>> { + use core::mem; + + let idx = (field as *const _ as usize - &self.fields[0] as *const _ as usize) + / mem::size_of::<NamedField<'_>>(); + self.values.get(idx) + } + + /// Get a value using string. + /// + /// # Examples + /// + /// ``` + /// use valuable::{NamedField, NamedValues, Value}; + /// + /// let fields = [ + /// NamedField::new("foo"), + /// NamedField::new("bar") + /// ]; + /// let values = [ + /// Value::U32(123), + /// Value::U32(456), + /// ]; + /// + /// let named_values = NamedValues::new(&fields, &values); + /// + /// assert_eq!( + /// named_values.get_by_name("foo").unwrap().as_u32(), + /// Some(123)); + /// ``` + pub fn get_by_name(&self, name: impl AsRef<str>) -> Option<&Value<'_>> { + let name = name.as_ref(); + + for (index, field) in self.fields.iter().enumerate() { + if field.name() == name { + return Some(&self.values[index]); + } + } + + None + } + + /// Iterate all name-value pairs. + /// + /// # Examples + /// + /// ``` + /// use valuable::{NamedField, NamedValues, Value}; + /// + /// let fields = [ + /// NamedField::new("foo"), + /// NamedField::new("bar") + /// ]; + /// let values = [ + /// Value::U32(123), + /// Value::U32(456), + /// ]; + /// + /// let named_values = NamedValues::new(&fields, &values); + /// + /// for (field, value) in named_values.iter() { + /// println!("{:?}: {:?}", field, value); + /// } + /// ``` + pub fn iter<'b>(&'b self) -> Iter<'a, 'b> { + Iter { + iter: self.fields.iter().enumerate(), + values: self.values, + } + } + + /// Returns the length of fields. + pub fn len(&self) -> usize { + self.fields.len() + } + + /// Returns `true` if fields have a length of 0. + pub fn is_empty(&self) -> bool { + self.fields.is_empty() + } +} + +impl<'a, 'b> IntoIterator for &'b NamedValues<'a> { + type Item = (&'b NamedField<'a>, &'b Value<'a>); + type IntoIter = Iter<'a, 'b>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +/// An iterator of name-value pairs contained by [`NamedValues`]. +/// +/// Instances are created by the [`iter()`][NamedValues::iter] method on +/// [`NamedValues`]. See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use valuable::{NamedField, NamedValues, Value}; +/// +/// let fields = [ +/// NamedField::new("foo"), +/// NamedField::new("bar") +/// ]; +/// let values = [ +/// Value::U32(123), +/// Value::U32(456), +/// ]; +/// +/// let named_values = NamedValues::new(&fields, &values); +/// +/// for (field, value) in named_values.iter() { +/// println!("{:?}: {:?}", field, value); +/// } +/// ``` +#[derive(Debug)] +pub struct Iter<'a, 'b> { + iter: iter::Enumerate<core::slice::Iter<'b, NamedField<'a>>>, + values: &'a [Value<'a>], +} + +impl<'a, 'b> Iterator for Iter<'a, 'b> { + type Item = (&'b NamedField<'a>, &'b Value<'a>); + + fn next(&mut self) -> Option<Self::Item> { + self.iter + .next() + .map(move |(i, field)| (field, &self.values[i])) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} + +impl DoubleEndedIterator for Iter<'_, '_> { + fn next_back(&mut self) -> Option<Self::Item> { + self.iter + .next_back() + .map(move |(i, field)| (field, &self.values[i])) + } +} + +impl ExactSizeIterator for Iter<'_, '_> { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl FusedIterator for Iter<'_, '_> {} diff --git a/vendor/valuable/src/slice.rs b/vendor/valuable/src/slice.rs new file mode 100644 index 000000000..a6ada6e67 --- /dev/null +++ b/vendor/valuable/src/slice.rs @@ -0,0 +1,428 @@ +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<usize>) { + use IterKind::*; + + #[allow(unused_doc_comments)] + match &self.0 { + $( + $(#[$attrs])* + $variant(v) => v.size_hint(), + )* + } + } + + fn next(&mut self) -> Option<Value<'a>> { + 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<Self::Item> { + 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(()), +} diff --git a/vendor/valuable/src/structable.rs b/vendor/valuable/src/structable.rs new file mode 100644 index 000000000..611a7e58b --- /dev/null +++ b/vendor/valuable/src/structable.rs @@ -0,0 +1,496 @@ +use crate::field::*; +use crate::*; + +use core::fmt; + +/// A struct-like [`Valuable`] sub-type. +/// +/// Implemented by [`Valuable`] types that have a struct-like shape. Fields may +/// be named or unnamed (tuple). Values that implement `Structable` must return +/// [`Value::Structable`] from their [`Valuable::as_value`] implementation. +/// +/// # Inspecting +/// +/// Inspecting fields contained by a `Structable` instance is done by visiting +/// the struct. When visiting a `Structable`, either the `visit_named_fields()` +/// or the `visit_unnamed_fields()` methods of `Visit` are called. Each method +/// may be called multiple times per `Structable`, but the two methods are never +/// mixed. +/// +/// ``` +/// use valuable::{NamedValues, Valuable, Value, Visit}; +/// +/// #[derive(Valuable)] +/// struct MyStruct { +/// foo: u32, +/// bar: u32, +/// } +/// +/// struct PrintFields; +/// +/// impl Visit for PrintFields { +/// fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { +/// for (field, value) in named_values.iter() { +/// println!("{}: {:?}", field.name(), value); +/// } +/// } +/// +/// fn visit_value(&mut self, value: Value<'_>) { +/// match value { +/// Value::Structable(v) => v.visit(self), +/// _ => {} // do nothing for other types +/// } +/// } +/// } +/// +/// let my_struct = MyStruct { +/// foo: 123, +/// bar: 456, +/// }; +/// +/// valuable::visit(&my_struct, &mut PrintFields); +/// ``` +/// +/// If the struct is **statically** defined, then all fields are known ahead of +/// time and may be accessed via the [`StructDef`] instance returned by +/// [`definition()`]. [`NamedField`] instances returned by [`definition()`] +/// maybe used to efficiently extract specific field values. +/// +/// # Implementing +/// +/// Implementing `Structable` is usually done by adding `#[derive(Valuable)]` to +/// a Rust `struct` definition. +/// +/// ``` +/// use valuable::{Fields, Valuable, Structable, StructDef}; +/// +/// #[derive(Valuable)] +/// struct MyStruct { +/// foo: &'static str, +/// } +/// +/// let my_struct = MyStruct { foo: "Hello" }; +/// let fields = match my_struct.definition() { +/// StructDef::Static { name, fields, .. } => { +/// assert_eq!("MyStruct", name); +/// fields +/// } +/// _ => unreachable!(), +/// }; +/// +/// match fields { +/// Fields::Named(named_fields) => { +/// assert_eq!(1, named_fields.len()); +/// assert_eq!("foo", named_fields[0].name()); +/// } +/// _ => unreachable!(), +/// } +/// ``` +/// +/// [`definition()`]: Structable::definition() +pub trait Structable: Valuable { + /// Returns the struct's definition. + /// + /// See [`StructDef`] documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use valuable::{Structable, Valuable}; + /// + /// #[derive(Valuable)] + /// struct MyStruct { + /// foo: u32, + /// } + /// + /// let my_struct = MyStruct { + /// foo: 123, + /// }; + /// + /// assert_eq!("MyStruct", my_struct.definition().name()); + fn definition(&self) -> StructDef<'_>; +} + +/// A struct's name, fields, and other struct-level information. +/// +/// Returned by [`Structable::definition()`], `StructDef` provides the caller +/// with information about the struct's definition. +/// +/// [`Structable::definition()`]: Structable::definition +#[derive(Debug)] +#[non_exhaustive] +pub enum StructDef<'a> { + /// The struct is statically-defined, all fields are known ahead of time. + /// + /// Most `Structable` definitions for Rust struct types will be + /// `StructDef::Static`. + /// + /// # Examples + /// + /// A statically defined struct + /// + /// ``` + /// use valuable::{Fields, Valuable, Structable, StructDef}; + /// + /// #[derive(Valuable)] + /// struct MyStruct { + /// foo: &'static str, + /// } + /// + /// let my_struct = MyStruct { foo: "Hello" }; + /// let fields = match my_struct.definition() { + /// StructDef::Static { name, fields, ..} => { + /// assert_eq!("MyStruct", name); + /// fields + /// } + /// _ => unreachable!(), + /// }; + /// + /// match fields { + /// Fields::Named(named_fields) => { + /// assert_eq!(1, named_fields.len()); + /// assert_eq!("foo", named_fields[0].name()); + /// } + /// _ => unreachable!(), + /// } + /// ``` + #[non_exhaustive] + Static { + /// The struct's name. + name: &'static str, + + /// The struct's fields. + fields: Fields<'static>, + }, + + /// The struct is dynamically-defined, not all fields are known ahead of + /// time. + /// + /// A dynamically-defined struct **could** be represented using + /// [`Mappable`], though, using `Structable` offers benefits in a couple of + /// cases. For example, when serializing a `Value`, some formats will + /// serialize maps and structs differently. In this case, differentiating + /// the two is required. There also are times when **some** struct fields + /// are known statically, but not all of them (see second example). + /// + /// # Examples + /// + /// The struct stores field values in a `HashMap`. + /// + /// ``` + /// use valuable::{Fields, NamedField, NamedValues, Structable, StructDef, Value, Valuable, Visit}; + /// use std::collections::HashMap; + /// + /// /// A dynamic struct + /// struct Dyn { + /// // The struct name + /// name: String, + /// + /// // Named values. + /// values: HashMap<String, Box<dyn Valuable>>, + /// } + /// + /// impl Valuable for Dyn { + /// fn as_value(&self) -> Value<'_> { + /// Value::Structable(self) + /// } + /// + /// fn visit(&self, visit: &mut dyn Visit) { + /// // This could be optimized to batch some. + /// for (field, value) in self.values.iter() { + /// visit.visit_named_fields(&NamedValues::new( + /// &[NamedField::new(field)], + /// &[value.as_value()], + /// )); + /// } + /// } + /// } + /// + /// impl Structable for Dyn { + /// fn definition(&self) -> StructDef<'_> { + /// StructDef::new_dynamic(&self.name, Fields::Named(&[])) + /// } + /// } + /// ``` + /// + /// Some fields are known statically. + /// + /// ``` + /// use valuable::{Fields, NamedField, NamedValues, Structable, StructDef, Value, Valuable, Visit}; + /// use std::collections::HashMap; + /// + /// struct HalfStatic { + /// foo: u32, + /// bar: u32, + /// extra_values: HashMap<String, Box<dyn Valuable>>, + /// } + /// + /// impl Valuable for HalfStatic { + /// fn as_value(&self) -> Value<'_> { + /// Value::Structable(self) + /// } + /// + /// fn visit(&self, visit: &mut dyn Visit) { + /// // First, visit static fields + /// visit.visit_named_fields(&NamedValues::new( + /// FIELDS, + /// &[self.foo.as_value(), self.bar.as_value()], + /// )); + /// + /// // This could be optimized to batch some. + /// for (field, value) in self.extra_values.iter() { + /// visit.visit_named_fields(&NamedValues::new( + /// &[NamedField::new(field)], + /// &[value.as_value()], + /// )); + /// } + /// } + /// } + /// + /// static FIELDS: &[NamedField<'static>] = &[ + /// NamedField::new("foo"), + /// NamedField::new("bar"), + /// ]; + /// + /// impl Structable for HalfStatic { + /// fn definition(&self) -> StructDef<'_> { + /// // Include known fields. + /// StructDef::new_dynamic( + /// "HalfStatic", + /// Fields::Named(FIELDS)) + /// } + /// } + /// ``` + #[non_exhaustive] + Dynamic { + /// The struct's name + name: &'a str, + + /// The struct's fields. + fields: Fields<'a>, + }, +} + +impl fmt::Debug for dyn Structable + '_ { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let def = self.definition(); + + if def.fields().is_named() { + struct DebugStruct<'a, 'b> { + fmt: fmt::DebugStruct<'a, 'b>, + } + + let mut debug = DebugStruct { + fmt: fmt.debug_struct(def.name()), + }; + + impl Visit for DebugStruct<'_, '_> { + fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { + for (field, value) in named_values { + self.fmt.field(field.name(), value); + } + } + + fn visit_value(&mut self, _: Value<'_>) { + unreachable!() + } + } + + self.visit(&mut debug); + + debug.fmt.finish() + } else { + struct DebugStruct<'a, 'b> { + fmt: fmt::DebugTuple<'a, 'b>, + } + + let mut debug = DebugStruct { + fmt: fmt.debug_tuple(def.name()), + }; + + impl Visit for DebugStruct<'_, '_> { + fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { + for value in values { + self.fmt.field(value); + } + } + + fn visit_value(&mut self, _: Value<'_>) { + unreachable!(); + } + } + + self.visit(&mut debug); + + debug.fmt.finish() + } + } +} + +impl<'a> StructDef<'a> { + /// Create a new [`StructDef::Static`] instance. + /// + /// This should be used when a struct's fields are fixed and known ahead of time. + /// + /// # Examples + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_static("Foo", Fields::Unnamed(2)); + /// ``` + pub const fn new_static(name: &'static str, fields: Fields<'static>) -> StructDef<'a> { + StructDef::Static { name, fields } + } + + /// Create a new [`StructDef::Dynamic`] instance. + /// + /// This is used when the struct's fields may vary at runtime. + /// + /// # Examples + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(3)); + /// ``` + pub const fn new_dynamic(name: &'a str, fields: Fields<'a>) -> StructDef<'a> { + StructDef::Dynamic { name, fields } + } + + /// Returns the struct's name + /// + /// # Examples + /// + /// With a static struct + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_static("Foo", Fields::Unnamed(1)); + /// assert_eq!("Foo", def.name()); + /// ``` + /// + /// With a dynamic struct + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(2)); + /// assert_eq!("Foo", def.name()); + /// ``` + pub const fn name(&self) -> &'a str { + match self { + StructDef::Static { name, .. } => name, + StructDef::Dynamic { name, .. } => name, + } + } + + /// Returns the struct's fields + /// + /// # Examples + /// + /// With a static struct + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_static("Foo", Fields::Unnamed(3)); + /// assert!(matches!(def.fields(), Fields::Unnamed(_))); + /// ``` + /// + /// With a dynamic struct + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(1)); + /// assert!(matches!(def.fields(), Fields::Unnamed(_))); + /// ``` + pub const fn fields(&self) -> &Fields<'a> { + match self { + StructDef::Static { fields, .. } => fields, + StructDef::Dynamic { fields, .. } => fields, + } + } + + /// Returns `true` if the struct is [statically defined](StructDef::Static). + /// + /// # Examples + /// + /// With a static struct + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_static("Foo", Fields::Unnamed(2)); + /// assert!(def.is_static()); + /// ``` + /// + /// With a dynamic struct + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(4)); + /// assert!(!def.is_static()); + /// ``` + pub const fn is_static(&self) -> bool { + matches!(self, StructDef::Static { .. }) + } + + /// Returns `true` if the struct is [dynamically defined](StructDef::Dynamic). + /// + /// # Examples + /// + /// With a static struct + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_static("Foo", Fields::Unnamed(1)); + /// assert!(!def.is_dynamic()); + /// ``` + /// + /// With a dynamic struct + /// + /// ``` + /// use valuable::{StructDef, Fields}; + /// + /// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(1)); + /// assert!(def.is_dynamic()); + /// ``` + pub const fn is_dynamic(&self) -> bool { + matches!(self, StructDef::Dynamic { .. }) + } +} + +macro_rules! deref { + ( + $( + $(#[$attrs:meta])* + $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<T: ?Sized + Structable> Structable for $ty { + fn definition(&self) -> StructDef<'_> { + T::definition(&**self) + } + } + )* + }; +} + +deref! { + &T, + &mut T, + #[cfg(feature = "alloc")] + alloc::boxed::Box<T>, + #[cfg(feature = "alloc")] + alloc::rc::Rc<T>, + #[cfg(not(valuable_no_atomic_cas))] + #[cfg(feature = "alloc")] + alloc::sync::Arc<T>, +} diff --git a/vendor/valuable/src/tuplable.rs b/vendor/valuable/src/tuplable.rs new file mode 100644 index 000000000..8c7169ff2 --- /dev/null +++ b/vendor/valuable/src/tuplable.rs @@ -0,0 +1,339 @@ +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<usize>), + }, +} + +macro_rules! deref { + ( + $( + $(#[$attrs:meta])* + $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<T: ?Sized + Tuplable> Tuplable for $ty { + fn definition(&self) -> TupleDef { + T::definition(&**self) + } + } + )* + }; +} + +deref! { + &T, + &mut T, + #[cfg(feature = "alloc")] + alloc::boxed::Box<T>, + #[cfg(feature = "alloc")] + alloc::rc::Rc<T>, + #[cfg(not(valuable_no_atomic_cas))] + #[cfg(feature = "alloc")] + alloc::sync::Arc<T>, +} + +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<usize>)) -> 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 { .. }) + } +} diff --git a/vendor/valuable/src/valuable.rs b/vendor/valuable/src/valuable.rs new file mode 100644 index 000000000..e8fa5ddcf --- /dev/null +++ b/vendor/valuable/src/valuable.rs @@ -0,0 +1,339 @@ +use crate::{Slice, Value, Visit}; + +use core::fmt; +use core::num::Wrapping; + +/// A type that can be converted to a [`Value`]. +/// +/// `Valuable` types are inspected by defining a [`Visit`] implementation and +/// using it when calling [`Valuable::visit`]. See [`Visit`] documentation for +/// more details. +/// +/// The `Valuable` procedural macro makes implementing `Valuable` easy. Users +/// can add add [`#[derive(Valuable)]`][macro] to their types. +/// +/// `Valuable` provides implementations for many Rust primitives and standard +/// library types. +/// +/// Types implementing `Valuable` may also implement one of the more specific +/// traits: [`Structable`], [`Enumerable`], [`Listable`], and [`Mappable`]. These traits +/// should be implemented when the type is a nested container of other `Valuable` types. +/// +/// [`Value`]: Value +/// [`Visit`]: Visit +/// [`Valuable::visit`]: Valuable::visit +/// [`Structable`]: crate::Structable +/// [`Enumerable`]: crate::Enumerable +/// [`Listable`]: crate::Listable +/// [`Mappable`]: crate::Mappable +/// [macro]: macro@crate::Valuable +pub trait Valuable { + /// Converts self into a [`Value`] instance. + /// + /// # Examples + /// + /// ``` + /// use valuable::Valuable; + /// + /// let _ = "hello".as_value(); + /// ``` + fn as_value(&self) -> Value<'_>; + + /// Calls the relevant method on [`Visit`] to extract data from `self`. + /// + /// This method is used to extract type-specific data from the value and is + /// intended to be an implementation detail. For example, `Vec` implements + /// `visit` by calling [`visit_value()`] on each of its elements. Structs + /// implement `visit` by calling [`visit_named_fields()`] or + /// [`visit_unnamed_fields()`]. + /// + /// Usually, users will call the [`visit`] function instead. + /// + /// [`Visit`]: Visit + /// [`visit`]: visit() + /// [`visit_value()`]: Visit::visit_value() + /// [`visit_named_fields()`]: Visit::visit_named_fields() + /// [`visit_unnamed_fields()`]: Visit::visit_unnamed_fields() + fn visit(&self, visit: &mut dyn Visit); + + /// Calls [`Visit::visit_primitive_slice()`] with `self`. + /// + /// This method is an implementation detail used to optimize visiting + /// primitive slices. + /// + /// [`Visit::visit_primitive_slice()`]: Visit::visit_primitive_slice + fn visit_slice(slice: &[Self], visit: &mut dyn Visit) + where + Self: Sized, + { + for item in slice { + visit.visit_value(item.as_value()); + } + } +} + +macro_rules! deref { + ( + $( + $(#[$attrs:meta])* + $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<T: ?Sized + Valuable> Valuable for $ty { + fn as_value(&self) -> Value<'_> { + T::as_value(&**self) + } + + fn visit(&self, visit: &mut dyn Visit) { + T::visit(&**self, visit); + } + } + )* + }; +} + +deref! { + &T, + &mut T, + #[cfg(feature = "alloc")] + alloc::boxed::Box<T>, + #[cfg(feature = "alloc")] + alloc::rc::Rc<T>, + #[cfg(not(valuable_no_atomic_cas))] + #[cfg(feature = "alloc")] + alloc::sync::Arc<T>, +} + +macro_rules! valuable { + ( + $( + $variant:ident($ty:ty), + )* + ) => { + $( + impl Valuable for $ty { + fn as_value(&self) -> Value<'_> { + Value::$variant(*self) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(self.as_value()); + } + + fn visit_slice(slice: &[Self], visit: &mut dyn Visit) + where + Self: Sized, + { + visit.visit_primitive_slice(Slice::$variant(slice)); + } + } + )* + }; +} + +valuable! { + Bool(bool), + Char(char), + F32(f32), + F64(f64), + I8(i8), + I16(i16), + I32(i32), + I64(i64), + I128(i128), + Isize(isize), + U8(u8), + U16(u16), + U32(u32), + U64(u64), + U128(u128), + Usize(usize), +} + +macro_rules! nonzero { + ( + $( + $variant:ident($ty:ident), + )* + ) => { + $( + impl Valuable for core::num::$ty { + fn as_value(&self) -> Value<'_> { + Value::$variant(self.get()) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(self.as_value()); + } + } + )* + }; +} + +nonzero! { + I8(NonZeroI8), + I16(NonZeroI16), + I32(NonZeroI32), + I64(NonZeroI64), + I128(NonZeroI128), + Isize(NonZeroIsize), + U8(NonZeroU8), + U16(NonZeroU16), + U32(NonZeroU32), + U64(NonZeroU64), + U128(NonZeroU128), + Usize(NonZeroUsize), +} + +#[cfg(not(valuable_no_atomic))] +macro_rules! atomic { + ( + $( + $(#[$attrs:meta])* + $variant:ident($ty:ident), + )* + ) => { + $( + $(#[$attrs])* + impl Valuable for core::sync::atomic::$ty { + fn as_value(&self) -> Value<'_> { + // Use SeqCst to match Debug and serde which use SeqCst. + // https://github.com/rust-lang/rust/blob/1.52.1/library/core/src/sync/atomic.rs#L1361-L1366 + // https://github.com/serde-rs/serde/issues/1496 + Value::$variant(self.load(core::sync::atomic::Ordering::SeqCst)) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(self.as_value()); + } + } + )* + }; +} + +#[cfg(not(valuable_no_atomic))] +atomic! { + Bool(AtomicBool), + I8(AtomicI8), + I16(AtomicI16), + I32(AtomicI32), + #[cfg(not(valuable_no_atomic_64))] + I64(AtomicI64), + Isize(AtomicIsize), + U8(AtomicU8), + U16(AtomicU16), + U32(AtomicU32), + #[cfg(not(valuable_no_atomic_64))] + U64(AtomicU64), + Usize(AtomicUsize), +} + +impl<T: Valuable> Valuable for Wrapping<T> { + fn as_value(&self) -> Value<'_> { + self.0.as_value() + } + + fn visit(&self, visit: &mut dyn Visit) { + self.0.visit(visit); + } +} + +impl Valuable for () { + fn as_value(&self) -> Value<'_> { + Value::Tuplable(self) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_unnamed_fields(&[]); + } +} + +impl<T: Valuable> Valuable for Option<T> { + fn as_value(&self) -> Value<'_> { + match self { + Some(v) => v.as_value(), + None => Value::Unit, + } + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(self.as_value()); + } +} + +impl Valuable for &'_ str { + fn as_value(&self) -> Value<'_> { + Value::String(self) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(Value::String(self)); + } + + fn visit_slice(slice: &[Self], visit: &mut dyn Visit) + where + Self: Sized, + { + visit.visit_primitive_slice(Slice::Str(slice)); + } +} + +#[cfg(feature = "alloc")] +impl Valuable for alloc::string::String { + fn as_value(&self) -> Value<'_> { + Value::String(&self[..]) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(Value::String(self)); + } + + fn visit_slice(slice: &[Self], visit: &mut dyn Visit) + where + Self: Sized, + { + visit.visit_primitive_slice(Slice::String(slice)); + } +} + +#[cfg(feature = "std")] +impl Valuable for &std::path::Path { + fn as_value(&self) -> Value<'_> { + Value::Path(self) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(Value::Path(self)); + } +} + +#[cfg(feature = "std")] +impl Valuable for std::path::PathBuf { + fn as_value(&self) -> Value<'_> { + Value::Path(self) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(Value::Path(self)); + } +} + +#[cfg(feature = "std")] +impl Valuable for dyn std::error::Error + 'static { + fn as_value(&self) -> Value<'_> { + Value::Error(self) + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(self.as_value()); + } +} + +impl fmt::Debug for dyn Valuable + '_ { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let value = self.as_value(); + value.fmt(fmt) + } +} diff --git a/vendor/valuable/src/value.rs b/vendor/valuable/src/value.rs new file mode 100644 index 000000000..2db9cd10a --- /dev/null +++ b/vendor/valuable/src/value.rs @@ -0,0 +1,877 @@ +use crate::{Enumerable, Listable, Mappable, Structable, Tuplable, Valuable, Visit}; + +use core::fmt; + +macro_rules! value { + ( + $( + $(#[$attrs:meta])* + $variant:ident($ty:ty), + )* + ) => { + /// Any Rust value + /// + /// The `Value` enum is used to pass single values to the + /// [visitor][`Visit`]. Primitive types are enumerated and other types + /// are represented at trait objects. + /// + /// Values are converted to `Value` instances using + /// [`Valuable::as_value()`]. + /// + /// # Examples + /// + /// Convert a primitive type + /// + /// ``` + /// use valuable::{Value, Valuable}; + /// + /// let num = 123; + /// let val = num.as_value(); + /// + /// assert!(matches!(val, Value::I32(v) if v == 123)); + /// ``` + /// + /// Converting a struct + /// + /// ``` + /// use valuable::{Value, Valuable}; + /// + /// #[derive(Valuable, Debug)] + /// struct HelloWorld { + /// message: String, + /// } + /// + /// let hello = HelloWorld { + /// message: "greetings".to_string(), + /// }; + /// + /// let val = hello.as_value(); + /// + /// assert!(matches!(val, Value::Structable(_v))); + /// + /// // The Value `Debug` output matches the struct's + /// assert_eq!( + /// format!("{:?}", val), + /// format!("{:?}", hello), + /// ); + /// ``` + /// + /// [visitor]: Visit + #[non_exhaustive] + #[derive(Clone, Copy)] + pub enum Value<'a> { + $( + $(#[$attrs])* + $variant($ty), + )* + + /// A Rust `()` or `None` value. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::Unit; + /// ``` + Unit, + } + + $( + $(#[$attrs])* + impl<'a> From<$ty> for Value<'a> { + fn from(src: $ty) -> Value<'a> { + Value::$variant(src) + } + } + )* + + impl<'a> From<()> for Value<'a> { + fn from(_: ()) -> Value<'a> { + Value::Tuplable(&()) + } + } + + impl fmt::Debug for Value<'_> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + use Value::*; + + // Doc comments are expanded into the branch arms, which results + // in a warning. It isn't a big deal, so silence it. + #[allow(unused_doc_comments)] + match self { + $( + $(#[$attrs])* + $variant(v) => fmt::Debug::fmt(v, fmt), + )* + Unit => ().fmt(fmt), + } + } + } + } +} + +value! { + /// A Rust `bool` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::Bool(true); + /// ``` + Bool(bool), + + /// A Rust `char` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::Char('h'); + /// ``` + Char(char), + + /// A Rust `f32` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::F32(3.1415); + /// ``` + F32(f32), + + /// A Rust `f64` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::F64(3.1415); + /// ``` + F64(f64), + + /// A Rust `i8` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::I8(42); + /// ``` + I8(i8), + + /// A Rust `i16` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::I16(42); + /// ``` + I16(i16), + + /// A Rust `i32` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::I32(42); + /// ``` + I32(i32), + + /// A Rust `i64` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::I64(42); + /// ``` + I64(i64), + + /// A Rust `i128` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::I128(42); + /// ``` + I128(i128), + + /// A Rust `isize` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::Isize(42); + /// ``` + Isize(isize), + + /// A Rust `&str` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::String("hello"); + /// ``` + String(&'a str), + + /// A Rust `u8` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::U8(42); + /// ``` + U8(u8), + + /// A Rust `u16` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::U16(42); + /// ``` + U16(u16), + + /// A Rust `u32` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::U32(42); + /// ``` + U32(u32), + + /// A Rust `u64` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::U64(42); + /// ``` + U64(u64), + + /// A Rust `u128` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::U128(42); + /// ``` + U128(u128), + + /// A Rust `usize` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let v = Value::Usize(42); + /// ``` + Usize(usize), + + /// A Rust `&Path` value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// use std::path::Path; + /// + /// let path = Path::new("a.txt"); + /// let v = Value::Path(path); + /// ``` + #[cfg(feature = "std")] + Path(&'a std::path::Path), + + /// A Rust error value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// use std::io; + /// + /// let err: io::Error = io::ErrorKind::Other.into(); + /// let v = Value::Error(&err); + /// ``` + #[cfg(feature = "std")] + Error(&'a (dyn std::error::Error +'static)), + + /// A Rust list value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let vals = vec![1, 2, 3, 4, 5]; + /// let v = Value::Listable(&vals); + /// ``` + Listable(&'a dyn Listable), + + /// A Rust map value + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("foo", 1); + /// map.insert("bar", 2); + /// + /// let v = Value::Mappable(&map); + /// ``` + Mappable(&'a dyn Mappable), + + /// A Rust struct value + /// + /// # Examples + /// + /// ``` + /// use valuable::{Value, Valuable}; + /// + /// #[derive(Valuable)] + /// struct MyStruct { + /// field: u32, + /// } + /// + /// let my_struct = MyStruct { + /// field: 123, + /// }; + /// + /// let v = Value::Structable(&my_struct); + /// ``` + Structable(&'a dyn Structable), + + /// A Rust enum value + /// + /// # Examples + /// + /// ``` + /// use valuable::{Value, Valuable}; + /// + /// #[derive(Valuable)] + /// enum MyEnum { + /// Foo, + /// Bar, + /// } + /// + /// let my_enum = MyEnum::Foo; + /// let v = Value::Enumerable(&my_enum); + /// ``` + Enumerable(&'a dyn Enumerable), + + /// A tuple value + /// + /// # Examples + /// + /// ``` + /// use valuable::{Value, Valuable}; + /// + /// let my_tuple = (123, 456); + /// let v = Value::Tuplable(&my_tuple); + /// ``` + Tuplable(&'a dyn Tuplable), +} + +impl Valuable for Value<'_> { + fn as_value(&self) -> Value<'_> { + *self + } + + fn visit(&self, visit: &mut dyn Visit) { + visit.visit_value(*self); + } +} + +impl Default for Value<'_> { + fn default() -> Self { + Value::Unit + } +} + +macro_rules! convert { + ( + $( + $(#[$attrs:meta])* + $ty:ty => $as:ident, + )* + ) => { + impl<'a> Value<'a> { + /// Return a `bool` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::Bool(true).as_bool(), Some(true)); + /// assert_eq!(Value::Char('c').as_bool(), None); + /// ``` + pub fn as_bool(&self) -> Option<bool> { + match *self { + Value::Bool(v) => Some(v), + _ => None, + } + } + + /// Return a `char` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::Char('c').as_char(), Some('c')); + /// assert_eq!(Value::Bool(true).as_char(), None); + /// ``` + pub fn as_char(&self) -> Option<char> { + match *self { + Value::Char(v) => Some(v), + _ => None, + } + } + + /// Return a `f32` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::F32(3.1415).as_f32(), Some(3.1415)); + /// assert_eq!(Value::Bool(true).as_f32(), None); + /// ``` + pub fn as_f32(&self) -> Option<f32> { + match *self { + Value::F32(v) => Some(v), + _ => None, + } + } + + /// Return a `f64` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::F64(3.1415).as_f64(), Some(3.1415)); + /// assert_eq!(Value::Bool(true).as_f64(), None); + /// ``` + pub fn as_f64(&self) -> Option<f64> { + match *self { + Value::F64(v) => Some(v), + _ => None, + } + } + + $( + $(#[$attrs])* + pub fn $as(&self) -> Option<$ty> { + use Value::*; + use core::convert::TryInto; + + match *self { + I8(v) => v.try_into().ok(), + I16(v) => v.try_into().ok(), + I32(v) => v.try_into().ok(), + I64(v) => v.try_into().ok(), + I128(v) => v.try_into().ok(), + Isize(v) => v.try_into().ok(), + U8(v) => v.try_into().ok(), + U16(v) => v.try_into().ok(), + U32(v) => v.try_into().ok(), + U64(v) => v.try_into().ok(), + U128(v) => v.try_into().ok(), + Usize(v) => v.try_into().ok(), + _ => None, + } + } + )* + + /// Return a `&str` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::String("hello").as_str(), Some("hello")); + /// assert_eq!(Value::Bool(true).as_str(), None); + /// ``` + pub fn as_str(&self) -> Option<&str> { + match *self { + Value::String(v) => Some(v), + _ => None, + } + } + + /// Return a `&Path` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// use std::path::Path; + /// + /// let path = Path::new("a.txt"); + /// + /// assert!(Value::Path(path).as_path().is_some()); + /// assert!(Value::Bool(true).as_path().is_none()); + /// ``` + #[cfg(feature = "std")] + pub fn as_path(&self) -> Option<&std::path::Path> { + match *self { + Value::Path(v) => Some(v), + _ => None, + } + } + + /// Return a `&dyn Error` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// use std::io; + /// + /// let err: io::Error = io::ErrorKind::Other.into(); + /// + /// assert!(Value::Error(&err).as_error().is_some()); + /// assert!(Value::Bool(true).as_error().is_none()); + /// ``` + #[cfg(feature = "std")] + pub fn as_error(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + Value::Error(v) => Some(v), + _ => None, + } + } + + + /// Return a `&dyn Listable` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let list = vec![1, 2, 3, 4]; + /// + /// assert!(Value::Listable(&list).as_listable().is_some()); + /// assert!(Value::Bool(true).as_listable().is_none()); + /// ``` + pub fn as_listable(&self) -> Option<&dyn Listable> { + match *self { + Value::Listable(v) => Some(v), + _ => None, + } + } + + /// Return a `&dyn Mappable` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("foo", 123); + /// map.insert("bar", 456); + /// + /// assert!(Value::Mappable(&map).as_mappable().is_some()); + /// assert!(Value::Bool(true).as_mappable().is_none()); + /// ``` + pub fn as_mappable(&self) -> Option<&dyn Mappable> { + match *self { + Value::Mappable(v) => Some(v), + _ => None, + } + } + + /// Return a `&dyn Structable` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::{Value, Valuable}; + /// + /// #[derive(Valuable)] + /// struct Hello { + /// message: &'static str, + /// } + /// + /// let hello = Hello { message: "Hello world" }; + /// + /// assert!(Value::Structable(&hello).as_structable().is_some()); + /// assert!(Value::Bool(true).as_structable().is_none()); + /// ``` + pub fn as_structable(&self) -> Option<&dyn Structable> { + match *self { + Value::Structable(v) => Some(v), + _ => None, + } + } + + /// Return a `&dyn Enumerable` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::{Value, Valuable}; + /// + /// #[derive(Valuable)] + /// enum Greet { + /// Hello, + /// World, + /// } + /// + /// let greet = Greet::Hello; + /// + /// assert!(Value::Enumerable(&greet).as_enumerable().is_some()); + /// assert!(Value::Bool(true).as_enumerable().is_none()); + /// ``` + pub fn as_enumerable(&self) -> Option<&dyn Enumerable> { + match *self { + Value::Enumerable(v) => Some(v), + _ => None, + } + } + + /// Return a `&dyn Tuplable` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// let my_tuple = (123, 456); + /// + /// assert!(Value::Tuplable(&my_tuple).as_tuplable().is_some()); + /// assert!(Value::Bool(true).as_tuplable().is_none()); + /// ``` + pub fn as_tuplable(&self) -> Option<&dyn Tuplable> { + match *self { + Value::Tuplable(v) => Some(v), + _ => None, + } + } + } + } +} + +convert! { + /// Return a `i8` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::I8(42).as_i8(), Some(42)); + /// assert_eq!(Value::I32(42).as_i8(), Some(42)); + /// + /// assert_eq!(Value::I64(i64::MAX).as_i8(), None); + /// assert_eq!(Value::Bool(true).as_i8(), None); + /// ``` + i8 => as_i8, + + /// Return a `i16` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::I16(42).as_i16(), Some(42)); + /// assert_eq!(Value::I32(42).as_i16(), Some(42)); + /// + /// assert_eq!(Value::I64(i64::MAX).as_i16(), None); + /// assert_eq!(Value::Bool(true).as_i16(), None); + /// ``` + i16 => as_i16, + + /// Return a `i32` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::I32(42).as_i32(), Some(42)); + /// assert_eq!(Value::I64(42).as_i32(), Some(42)); + /// + /// assert_eq!(Value::I64(i64::MAX).as_i32(), None); + /// assert_eq!(Value::Bool(true).as_i32(), None); + /// ``` + i32 => as_i32, + + /// Return a `i64` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::I64(42).as_i64(), Some(42)); + /// assert_eq!(Value::I128(42).as_i64(), Some(42)); + /// + /// assert_eq!(Value::I128(i128::MAX).as_i64(), None); + /// assert_eq!(Value::Bool(true).as_i64(), None); + /// ``` + i64 => as_i64, + + /// Return a `i128` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::I128(42).as_i128(), Some(42)); + /// assert_eq!(Value::U128(42).as_i128(), Some(42)); + /// + /// assert_eq!(Value::U128(u128::MAX).as_i128(), None); + /// assert_eq!(Value::Bool(true).as_i128(), None); + /// ``` + i128 => as_i128, + + /// Return a `isize` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::Isize(42).as_isize(), Some(42)); + /// assert_eq!(Value::Usize(42).as_isize(), Some(42)); + /// + /// assert_eq!(Value::Usize(usize::MAX).as_isize(), None); + /// assert_eq!(Value::Bool(true).as_isize(), None); + /// ``` + isize => as_isize, + + /// Return a `u8` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::U8(42).as_u8(), Some(42)); + /// assert_eq!(Value::U32(42).as_u8(), Some(42)); + /// + /// assert_eq!(Value::U32(u32::MAX).as_u8(), None); + /// assert_eq!(Value::Bool(true).as_u8(), None); + /// ``` + u8 => as_u8, + + /// Return a `u16` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::U16(42).as_u16(), Some(42)); + /// assert_eq!(Value::U32(42).as_u16(), Some(42)); + /// + /// assert_eq!(Value::U32(u32::MAX).as_u16(), None); + /// assert_eq!(Value::Bool(true).as_u16(), None); + /// ``` + u16 => as_u16, + + /// Return a `u32` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::U32(42).as_u32(), Some(42)); + /// assert_eq!(Value::U64(42).as_u32(), Some(42)); + /// + /// assert_eq!(Value::U64(u64::MAX).as_u32(), None); + /// assert_eq!(Value::Bool(true).as_u32(), None); + /// ``` + u32 => as_u32, + + /// Return a `u64` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::U64(42).as_u64(), Some(42)); + /// assert_eq!(Value::U128(42).as_u64(), Some(42)); + /// + /// assert_eq!(Value::U128(u128::MAX).as_u64(), None); + /// assert_eq!(Value::Bool(true).as_u64(), None); + /// ``` + u64 => as_u64, + + /// Return a `u128` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::U128(42).as_u128(), Some(42)); + /// assert_eq!(Value::I32(42).as_u128(), Some(42)); + /// + /// assert_eq!(Value::I32(-5).as_u128(), None); + /// assert_eq!(Value::Bool(true).as_u128(), None); + /// ``` + u128 => as_u128, + + /// Return a `usize` representation of `self`, if possible. + /// + /// # Examples + /// + /// ``` + /// use valuable::Value; + /// + /// assert_eq!(Value::Usize(42).as_usize(), Some(42)); + /// assert_eq!(Value::I8(42).as_usize(), Some(42)); + /// + /// assert_eq!(Value::I8(-5).as_usize(), None); + /// assert_eq!(Value::Bool(true).as_usize(), None); + /// ``` + usize => as_usize, +} diff --git a/vendor/valuable/src/visit.rs b/vendor/valuable/src/visit.rs new file mode 100644 index 000000000..f91a04cad --- /dev/null +++ b/vendor/valuable/src/visit.rs @@ -0,0 +1,459 @@ +use crate::*; + +/// Traverse a value's fields and variants. +/// +/// Each method of the `Visit` trait is a hook that enables the implementor to +/// observe value fields. By default, most methods are implemented as a no-op. +/// The `visit_primitive_slice` default implementation will iterate the slice, +/// calling `visit_value` with each item. +/// +/// To recurse, the implementor must implement methods to visit the arguments. +/// +/// # Examples +/// +/// Recursively printing a Rust value. +/// +/// ``` +/// use valuable::{NamedValues, Valuable, Value, Visit}; +/// +/// struct Print(String); +/// +/// impl Print { +/// fn indent(&self) -> Print { +/// Print(format!("{} ", self.0)) +/// } +/// } +/// +/// impl Visit for Print { +/// fn visit_value(&mut self, value: Value<'_>) { +/// match value { +/// Value::Structable(v) => { +/// let def = v.definition(); +/// // Print the struct name +/// println!("{}{}:", self.0, def.name()); +/// +/// // Visit fields +/// let mut visit = self.indent(); +/// v.visit(&mut visit); +/// } +/// Value::Enumerable(v) => { +/// let def = v.definition(); +/// let variant = v.variant(); +/// // Print the enum name +/// println!("{}{}::{}:", self.0, def.name(), variant.name()); +/// +/// // Visit fields +/// let mut visit = self.indent(); +/// v.visit(&mut visit); +/// } +/// Value::Listable(v) => { +/// println!("{}", self.0); +/// +/// // Visit fields +/// let mut visit = self.indent(); +/// v.visit(&mut visit); +/// } +/// Value::Mappable(v) => { +/// println!("{}", self.0); +/// +/// // Visit fields +/// let mut visit = self.indent(); +/// v.visit(&mut visit); +/// } +/// // Primitive or unknown type, just render Debug +/// v => println!("{:?}", v), +/// } +/// } +/// +/// fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { +/// for (field, value) in named_values { +/// print!("{}- {}: ", self.0, field.name()); +/// value.visit(self); +/// } +/// } +/// +/// fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { +/// for value in values { +/// print!("{}- ", self.0); +/// value.visit(self); +/// } +/// } +/// +/// fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) { +/// print!("{}- {:?}: ", self.0, key); +/// value.visit(self); +/// } +/// } +/// +/// #[derive(Valuable)] +/// struct Person { +/// name: String, +/// age: u32, +/// addresses: Vec<Address>, +/// } +/// +/// #[derive(Valuable)] +/// struct Address { +/// street: String, +/// city: String, +/// zip: String, +/// } +/// +/// let person = Person { +/// name: "Angela Ashton".to_string(), +/// age: 31, +/// addresses: vec![ +/// Address { +/// street: "123 1st Ave".to_string(), +/// city: "Townsville".to_string(), +/// zip: "12345".to_string(), +/// }, +/// Address { +/// street: "555 Main St.".to_string(), +/// city: "New Old Town".to_string(), +/// zip: "55555".to_string(), +/// }, +/// ], +/// }; +/// +/// let mut print = Print("".to_string()); +/// valuable::visit(&person, &mut print); +/// ``` +pub trait Visit { + /// Visit a single value. + /// + /// The `visit_value` method is called once when visiting single primitive + /// values. When visiting `Listable` types, the `visit_value` method is + /// called once per item in the listable type. + /// + /// Note, in the case of Listable types containing primitive types, + /// `visit_primitive_slice` can be implemented instead for less overhead. + /// + /// # Examples + /// + /// Visiting a single value. + /// + /// ``` + /// use valuable::{Valuable, Visit, Value}; + /// + /// struct Print; + /// + /// impl Visit for Print { + /// fn visit_value(&mut self, value: Value<'_>) { + /// println!("{:?}", value); + /// } + /// } + /// + /// let my_val = 123; + /// my_val.visit(&mut Print); + /// ``` + /// + /// Visiting multiple values in a list. + /// + /// ``` + /// use valuable::{Valuable, Value, Visit}; + /// + /// struct PrintList { comma: bool }; + /// + /// impl Visit for PrintList { + /// fn visit_value(&mut self, value: Value<'_>) { + /// match value { + /// Value::Listable(v) => v.visit(self), + /// value => { + /// if self.comma { + /// println!(", {:?}", value); + /// } else { + /// print!("{:?}", value); + /// self.comma = true; + /// } + /// } + /// } + /// } + /// } + /// + /// let my_list = vec![1, 2, 3, 4, 5]; + /// valuable::visit(&my_list, &mut PrintList { comma: false }); + /// ``` + fn visit_value(&mut self, value: Value<'_>); + + /// Visit a struct or enum's named fields. + /// + /// When the struct/enum is statically defined, all fields are known ahead + /// of time and `visit_named_fields` is called once with all field values. + /// When the struct/enum is dynamic, then the `visit_named_fields` method + /// may be called multiple times. + /// + /// See [`Structable`] and [`Enumerable`] for static vs. dynamic details. + /// + /// # Examples + /// + /// Visiting all fields in a struct. + /// + /// ``` + /// use valuable::{NamedValues, Valuable, Value, Visit}; + /// + /// #[derive(Valuable)] + /// struct MyStruct { + /// hello: String, + /// world: u32, + /// } + /// + /// struct Print; + /// + /// impl Visit for Print { + /// fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { + /// for (field, value) in named_values { + /// println!("{:?}: {:?}", field, value); + /// } + /// } + /// + /// fn visit_value(&mut self, value: Value<'_>) { + /// match value { + /// Value::Structable(v) => v.visit(self), + /// _ => {} // do nothing for other types + /// } + /// } + /// } + /// + /// let my_struct = MyStruct { + /// hello: "Hello world".to_string(), + /// world: 42, + /// }; + /// + /// valuable::visit(&my_struct, &mut Print); + /// ``` + fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { + let _ = named_values; + } + + /// Visit a struct or enum's unnamed fields. + /// + /// When the struct/enum is statically defined, all fields are known ahead + /// of time and `visit_unnamed_fields` is called once with all field values. + /// When the struct/enum is dynamic, then the `visit_unnamed_fields` method + /// may be called multiple times. + /// + /// See [`Structable`] and [`Enumerable`] for static vs. dynamic details. + /// + /// # Examples + /// + /// Visiting all fields in a struct. + /// + /// ``` + /// use valuable::{Valuable, Value, Visit}; + /// + /// #[derive(Valuable)] + /// struct MyStruct(String, u32); + /// + /// struct Print; + /// + /// impl Visit for Print { + /// fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { + /// for value in values { + /// println!("{:?}", value); + /// } + /// } + /// + /// fn visit_value(&mut self, value: Value<'_>) { + /// match value { + /// Value::Structable(v) => v.visit(self), + /// _ => {} // do nothing for other types + /// } + /// } + /// } + /// + /// let my_struct = MyStruct("Hello world".to_string(), 42); + /// + /// valuable::visit(&my_struct, &mut Print); + /// ``` + fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { + let _ = values; + } + + /// Visit a primitive slice. + /// + /// This method exists as an optimization when visiting [`Listable`] types. + /// By default, `Listable` types are visited by passing each item to + /// `visit_value`. However, if the listable stores a **primitive** type + /// within contiguous memory, then `visit_primitive_slice` is called + /// instead. + /// + /// When implementing `visit_primitive_slice`, be aware that the method may + /// be called multiple times for a single `Listable` type. + /// + /// # Examples + /// + /// A vec calls `visit_primitive_slice` one time, but a `VecDeque` will call + /// `visit_primitive_slice` twice. + /// + /// ``` + /// use valuable::{Valuable, Value, Visit, Slice}; + /// use std::collections::VecDeque; + /// + /// struct Count(u32); + /// + /// impl Visit for Count { + /// fn visit_primitive_slice(&mut self, slice: Slice<'_>) { + /// self.0 += 1; + /// } + /// + /// fn visit_value(&mut self, value: Value<'_>) { + /// match value { + /// Value::Listable(v) => v.visit(self), + /// _ => {} // do nothing for other types + /// } + /// } + /// } + /// + /// let vec = vec![1, 2, 3, 4, 5]; + /// + /// let mut count = Count(0); + /// valuable::visit(&vec, &mut count); + /// assert_eq!(1, count.0); + /// + /// let mut vec_deque = VecDeque::from(vec); + /// + /// let mut count = Count(0); + /// valuable::visit(&vec_deque, &mut count); + /// + /// assert_eq!(2, count.0); + /// ``` + fn visit_primitive_slice(&mut self, slice: Slice<'_>) { + for value in slice { + self.visit_value(value); + } + } + + /// Visit a `Mappable`'s entries. + /// + /// The `visit_entry` method is called once for each entry contained by a + /// `Mappable.` + /// + /// # Examples + /// + /// Visit a map's entries + /// + /// ``` + /// use valuable::{Valuable, Value, Visit}; + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("hello", 123); + /// map.insert("world", 456); + /// + /// struct Print; + /// + /// impl Visit for Print { + /// fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) { + /// println!("{:?} => {:?}", key, value); + /// } + /// + /// fn visit_value(&mut self, value: Value<'_>) { + /// match value { + /// Value::Mappable(v) => v.visit(self), + /// _ => {} // do nothing for other types + /// } + /// } + /// } + /// + /// valuable::visit(&map, &mut Print); + /// ``` + fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) { + let _ = (key, value); + } +} + +macro_rules! deref { + ( + $( + $(#[$attrs:meta])* + $ty:ty, + )* + ) => { + $( + $(#[$attrs])* + impl<T: ?Sized + Visit> Visit for $ty { + fn visit_value(&mut self, value: Value<'_>) { + T::visit_value(&mut **self, value) + } + + fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { + T::visit_named_fields(&mut **self, named_values) + } + + fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) { + T::visit_unnamed_fields(&mut **self, values) + } + + fn visit_primitive_slice(&mut self, slice: Slice<'_>) { + T::visit_primitive_slice(&mut **self, slice) + } + + fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) { + T::visit_entry(&mut **self, key, value) + } + } + )* + }; +} + +deref! { + &mut T, + #[cfg(feature = "alloc")] + alloc::boxed::Box<T>, +} + +/// Inspects a value by calling the relevant [`Visit`] methods with `value`'s +/// data. +/// +/// This method calls [`Visit::visit_value()`] with the provided [`Valuable`] +/// instance. See [`Visit`] documentation for more details. +/// +/// # Examples +/// +/// Extract a single field from a struct. Note: if the same field is repeatedly +/// extracted from a struct, it is preferable to obtain the associated +/// [`NamedField`] once and use it repeatedly. +/// +/// ``` +/// use valuable::{NamedValues, Valuable, Value, Visit}; +/// +/// #[derive(Valuable)] +/// struct MyStruct { +/// foo: usize, +/// bar: usize, +/// } +/// +/// struct GetFoo(usize); +/// +/// impl Visit for GetFoo { +/// fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { +/// if let Some(foo) = named_values.get_by_name("foo") { +/// if let Some(val) = foo.as_usize() { +/// self.0 = val; +/// } +/// } +/// } +/// +/// fn visit_value(&mut self, value: Value<'_>) { +/// if let Value::Structable(v) = value { +/// v.visit(self); +/// } +/// } +/// } +/// +/// let my_struct = MyStruct { +/// foo: 123, +/// bar: 456, +/// }; +/// +/// let mut get_foo = GetFoo(0); +/// valuable::visit(&my_struct, &mut get_foo); +/// +/// assert_eq!(123, get_foo.0); +/// ``` +/// +/// [`Visit`]: Visit [`NamedField`]: crate::NamedField +pub fn visit(value: &impl Valuable, visit: &mut dyn Visit) { + visit.visit_value(value.as_value()); +} |