valuable/
enumerable.rs

1use crate::field::*;
2use crate::*;
3
4#[cfg(feature = "alloc")]
5use alloc::format;
6use core::fmt;
7
8/// An enum-like [`Valuable`] sub-type.
9///
10/// Implemented by [`Valuable`] types that have an enum-like shape. Fields may
11/// be named or unnamed (tuple). Values that implement `Enumerable` must return
12/// [`Value::Enumerable`] from their [`Valuable::as_value`] implementation.
13///
14/// # Inspecting
15///
16/// The [`variant()`] method returns the `Enumerable` instance's variant. The
17/// `Enumerable` may also have unnamed fields (tuple) or named fields.
18/// Inspecting the field values is done by visiting the enum. When visiting an
19/// `Enumerable`, either the [`visit_named_fields()`] or the
20/// [`visit_unnamed_fields()`] methods of [`Visit`] are called. Each method may
21/// be called multiple times per `Enumerable`, but the two methods are never
22/// mixed.
23///
24/// [`variant()`]: Enumerable::variant
25/// [`visit_named_fields()`]: Visit::visit_named_fields
26/// [`visit_unnamed_fields()`]: Visit::visit_unnamed_fields
27///
28/// ```
29/// use valuable::{Valuable, Value, Visit};
30///
31/// #[derive(Valuable)]
32/// enum MyEnum {
33///     Foo,
34///     Bar(u32),
35/// }
36///
37/// struct PrintVariant;
38///
39/// impl Visit for PrintVariant {
40///     fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
41///         for value in values {
42///             println!(" - {:?}", value);
43///         }
44///     }
45///
46///     fn visit_value(&mut self, value: Value<'_>) {
47///         match value {
48///             Value::Enumerable(v) => {
49///                 println!("{}", v.variant().name());
50///                 v.visit(self)
51///             }
52///             _ => {}
53///         }
54///     }
55/// }
56///
57/// let my_enum = MyEnum::Bar(123);
58///
59/// valuable::visit(&my_enum, &mut PrintVariant);
60/// ```
61///
62/// If the enum is **statically** defined, then all variants, and variant fields
63/// are known ahead of time and may be accessed via the [`EnumDef`] instance
64/// returned by [`definition()`].
65///
66/// [`definition()`]: Enumerable::definition
67///
68/// # Implementing
69///
70/// Implementing `Enumerable` is usually done by adding `#[derive(Valuable)]` to
71/// a Rust `enum` definition.
72///
73/// ```
74/// use valuable::{Valuable, Enumerable, EnumDef};
75///
76/// #[derive(Valuable)]
77/// enum MyEnum {
78///     Foo,
79///     Bar(u32),
80/// }
81///
82/// let my_enum = MyEnum::Bar(123);
83///
84/// let variants = match my_enum.definition() {
85///     EnumDef::Static { name, variants, .. } => {
86///         assert_eq!("MyEnum", name);
87///         variants
88///     }
89///     _ => unreachable!(),
90/// };
91///
92/// assert_eq!(2, variants.len());
93/// assert_eq!("Foo", variants[0].name());
94/// assert!(variants[0].fields().is_unnamed());
95/// ```
96pub trait Enumerable: Valuable {
97    /// Returns the enum's definition.
98    ///
99    /// See [`EnumDef`] documentation for more details.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use valuable::{Enumerable, Valuable};
105    ///
106    /// #[derive(Valuable)]
107    /// enum MyEnum {
108    ///     Foo,
109    ///     Bar(u32),
110    /// }
111    ///
112    /// let my_enum = MyEnum::Bar(123);
113    ///
114    /// assert_eq!("MyEnum", my_enum.definition().name());
115    /// ```
116    fn definition(&self) -> EnumDef<'_>;
117
118    /// Returns the `enum`'s current variant.
119    ///
120    /// # Examples
121    ///
122    /// ```
123    /// use valuable::{Enumerable, Valuable};
124    ///
125    /// #[derive(Valuable)]
126    /// enum MyEnum {
127    ///     Foo,
128    ///     Bar(u32),
129    /// }
130    ///
131    /// let my_enum = MyEnum::Foo;
132    /// assert_eq!("Foo", my_enum.variant().name());
133    /// ```
134    fn variant(&self) -> Variant<'_>;
135}
136
137/// An enum's variants, variant fields, and other enum-level information.
138///
139/// Returned by [`Enumerable::definition()`], `EnumDef` provides the caller with
140/// information about the enum's definition.
141#[non_exhaustive]
142#[derive(Debug)]
143pub enum EnumDef<'a> {
144    /// The enum is statically-defined, all variants and variant-level fields
145    /// are known ahead of time.
146    ///
147    /// Most `Enumerable` definitions for Rust enum types will be
148    /// `EnumDef::Static`.
149    ///
150    /// # Examples
151    ///
152    /// A statically defined enum
153    ///
154    /// ```
155    /// use valuable::{Valuable, Enumerable, EnumDef};
156    ///
157    /// #[derive(Valuable)]
158    /// enum MyEnum {
159    ///     Foo,
160    ///     Bar(u32),
161    /// }
162    ///
163    /// let my_enum = MyEnum::Bar(123);
164    ///
165    /// let variants = match my_enum.definition() {
166    ///     EnumDef::Static { name, variants, .. } => {
167    ///         assert_eq!("MyEnum", name);
168    ///         variants
169    ///     }
170    ///     _ => unreachable!(),
171    /// };
172    ///
173    /// assert_eq!(2, variants.len());
174    /// assert_eq!("Foo", variants[0].name());
175    /// assert_eq!("Bar", variants[1].name());
176    /// ```
177    #[non_exhaustive]
178    Static {
179        /// The enum's name
180        name: &'static str,
181
182        /// The enum's variants
183        variants: &'static [VariantDef<'static>],
184    },
185
186    /// The enum is dynamically-defined, not all variants and fields are known
187    /// ahead of time.
188    ///
189    /// # Examples
190    ///
191    /// The enum variant is tracked as a string
192    ///
193    /// ```
194    /// use valuable::{Enumerable, EnumDef, Fields, VariantDef, Valuable, Value, Variant, Visit};
195    ///
196    /// /// A dynamic enum
197    /// struct DynEnum {
198    ///     // The enum name
199    ///     name: String,
200    ///
201    ///     // The current variant
202    ///     variant: String,
203    /// }
204    ///
205    /// impl Valuable for DynEnum {
206    ///     fn as_value(&self) -> Value<'_> {
207    ///         Value::Enumerable(self)
208    ///     }
209    ///
210    ///     fn visit(&self, _visit: &mut dyn Visit) {
211    ///         // No variant fields, so there is nothing to call here.
212    ///     }
213    /// }
214    ///
215    /// impl Enumerable for DynEnum {
216    ///     fn definition(&self) -> EnumDef<'_> {
217    ///         EnumDef::new_dynamic(&self.name, &[])
218    ///     }
219    ///
220    ///     fn variant(&self) -> Variant<'_> {
221    ///         Variant::Dynamic(VariantDef::new(&self.variant, Fields::Unnamed(0)))
222    ///     }
223    /// }
224    /// ```
225    #[non_exhaustive]
226    Dynamic {
227        /// The enum's name
228        name: &'a str,
229
230        /// The enum's variants
231        variants: &'a [VariantDef<'a>],
232    },
233}
234
235/// An enum variant definition.
236///
237/// Included with [`EnumDef`] returned by [`Enumerable::definition()`],
238/// `VariantDef` provides the caller with information about a specific variant.
239#[derive(Debug)]
240pub struct VariantDef<'a> {
241    /// Variant name
242    name: &'a str,
243
244    /// Variant fields
245    fields: Fields<'a>,
246}
247
248/// An enum variant
249///
250/// Returned by [`Enumerable::variant()`], `Variant` represents a single enum
251/// variant.
252#[derive(Debug)]
253pub enum Variant<'a> {
254    /// The variant is statically defined by the associated enum.
255    Static(&'static VariantDef<'static>),
256
257    /// The variant is dynamically defined and not included as part of
258    /// [`Enumerable::definition()`].
259    Dynamic(VariantDef<'a>),
260}
261
262impl<'a> EnumDef<'a> {
263    /// Create a new [`EnumDef::Static`] instance.
264    ///
265    /// This should be used when an enum's variants are fixed and known ahead of
266    /// time.
267    ///
268    /// # Examples
269    ///
270    /// ```
271    /// use valuable::{EnumDef, Fields, VariantDef};
272    ///
273    /// static VARIANTS: &[VariantDef<'static>] = &[
274    ///     VariantDef::new("Bar", Fields::Unnamed(1)),
275    /// ];
276    ///
277    /// let def = EnumDef::new_static( "Foo", VARIANTS);
278    /// ```
279    pub const fn new_static(
280        name: &'static str,
281        variants: &'static [VariantDef<'static>],
282    ) -> EnumDef<'a> {
283        EnumDef::Static { name, variants }
284    }
285
286    /// Create a new [`EnumDef::Dynamic`] instance.
287    ///
288    /// This is used when the enum's variants may vary at runtime.
289    ///
290    /// # Examples
291    ///
292    /// ```
293    /// use valuable::{EnumDef, Fields, VariantDef};
294    ///
295    /// let def = EnumDef::new_dynamic(
296    ///     "Foo",
297    ///     &[VariantDef::new("Bar", Fields::Unnamed(1))]
298    /// );
299    /// ```
300    pub const fn new_dynamic(name: &'a str, variants: &'a [VariantDef<'a>]) -> EnumDef<'a> {
301        EnumDef::Dynamic { name, variants }
302    }
303
304    /// Returns the enum's name
305    ///
306    /// # Examples
307    ///
308    /// ```
309    /// use valuable::{Enumerable, Valuable};
310    ///
311    /// #[derive(Valuable)]
312    /// enum Foo {
313    ///     Bar,
314    ///     Baz,
315    /// }
316    ///
317    /// let def = Foo::Bar.definition();
318    /// assert_eq!("Foo", def.name());
319    /// ```
320    pub fn name(&self) -> &str {
321        match self {
322            EnumDef::Static { name, .. } => name,
323            EnumDef::Dynamic { name, .. } => name,
324        }
325    }
326
327    /// Returns the enum's variants
328    ///
329    /// # Examples
330    ///
331    /// ```
332    /// use valuable::{Enumerable, Valuable};
333    ///
334    /// #[derive(Valuable)]
335    /// enum Foo {
336    ///     Bar,
337    ///     Baz,
338    /// }
339    ///
340    /// let def = Foo::Bar.definition();
341    /// let variants = def.variants();
342    ///
343    /// assert_eq!(2, variants.len());
344    /// assert_eq!("Bar", variants[0].name());
345    /// ```
346    pub fn variants(&self) -> &[VariantDef<'_>] {
347        match self {
348            EnumDef::Static { variants, .. } => variants,
349            EnumDef::Dynamic { variants, .. } => variants,
350        }
351    }
352
353    /// Returns `true` if the enum is [statically defined](EnumDef::Static).
354    ///
355    /// # Examples
356    ///
357    /// With a static enum
358    ///
359    /// ```
360    /// use valuable::{Enumerable, Valuable};
361    ///
362    /// #[derive(Valuable)]
363    /// enum Foo {
364    ///     Bar,
365    ///     Baz,
366    /// }
367    ///
368    /// let def = Foo::Bar.definition();
369    /// assert!(def.is_static());
370    /// ```
371    ///
372    /// With a dynamic enum
373    ///
374    /// ```
375    /// use valuable::{EnumDef, Fields, VariantDef};
376    ///
377    /// let def = EnumDef::new_dynamic("Foo", &[]);
378    /// assert!(!def.is_static());
379    /// ```
380    pub fn is_static(&self) -> bool {
381        matches!(self, EnumDef::Static { .. })
382    }
383
384    /// Returns `true` if the enum is [dynamically defined](EnumDef::Dynamic).
385    ///
386    /// # Examples
387    ///
388    /// With a static enum
389    ///
390    /// ```
391    /// use valuable::{Enumerable, Valuable};
392    ///
393    /// #[derive(Valuable)]
394    /// enum Foo {
395    ///     Bar,
396    ///     Baz,
397    /// }
398    ///
399    /// let def = Foo::Bar.definition();
400    /// assert!(!def.is_dynamic());
401    /// ```
402    ///
403    /// With a dynamic enum
404    ///
405    /// ```
406    /// use valuable::{EnumDef, Fields, VariantDef};
407    ///
408    /// let def = EnumDef::new_dynamic("Foo", &[]);
409    /// assert!(def.is_dynamic());
410    /// ```
411    pub fn is_dynamic(&self) -> bool {
412        matches!(self, EnumDef::Dynamic { .. })
413    }
414}
415
416impl<'a> VariantDef<'a> {
417    /// Creates a new `VariantDef` instance.
418    ///
419    /// # Examples
420    ///
421    /// ```
422    /// use valuable::{Fields, VariantDef};
423    ///
424    /// let def = VariantDef::new("Foo", Fields::Unnamed(2));
425    /// ```
426    pub const fn new(name: &'a str, fields: Fields<'a>) -> VariantDef<'a> {
427        VariantDef { name, fields }
428    }
429
430    /// Returns the variant's name
431    ///
432    /// # Examples
433    ///
434    /// ```
435    /// use valuable::{Fields, VariantDef};
436    ///
437    /// let def = VariantDef::new("Foo", Fields::Unnamed(2));
438    /// assert_eq!("Foo", def.name());
439    /// ```
440    pub fn name(&self) -> &str {
441        self.name
442    }
443
444    /// Returns the variant's fields
445    ///
446    /// # Examples
447    ///
448    /// ```
449    /// use valuable::{Fields, VariantDef};
450    ///
451    /// let def = VariantDef::new("Foo", Fields::Unnamed(3));
452    /// assert!(matches!(def.fields(), Fields::Unnamed(_)));
453    /// ```
454    pub fn fields(&self) -> &Fields<'_> {
455        &self.fields
456    }
457}
458
459impl Variant<'_> {
460    /// Returns the variant's name
461    ///
462    /// # Examples
463    ///
464    /// ```
465    /// use valuable::{Fields, Variant, VariantDef};
466    ///
467    /// static VARIANT: &VariantDef<'static> = &VariantDef::new(
468    ///     "Foo", Fields::Unnamed(2));
469    ///
470    /// let variant = Variant::Static(VARIANT);
471    /// assert_eq!("Foo", variant.name());
472    /// ```
473    pub fn name(&self) -> &str {
474        match self {
475            Variant::Static(v) => v.name(),
476            Variant::Dynamic(v) => v.name(),
477        }
478    }
479
480    /// Returns the variant's fields
481    pub fn fields(&self) -> &Fields<'_> {
482        match self {
483            Variant::Static(v) => v.fields(),
484            Variant::Dynamic(v) => v.fields(),
485        }
486    }
487
488    /// Returns `true` if the variant has associated named fields.
489    ///
490    /// # Examples
491    ///
492    /// With named fields
493    ///
494    /// ```
495    /// use valuable::{Fields, NamedField, Variant, VariantDef};
496    ///
497    /// static VARIANT: &VariantDef<'static> = &VariantDef::new(
498    ///     "Foo", Fields::Named(&[NamedField::new("hello")]));
499    ///
500    /// let variant = Variant::Static(VARIANT);
501    /// assert!(variant.is_named_fields());
502    /// ```
503    ///
504    /// With unnamed fields
505    ///
506    /// ```
507    /// use valuable::{Fields, Variant, VariantDef};
508    ///
509    /// static VARIANT: &VariantDef<'static> = &VariantDef::new(
510    ///     "Foo", Fields::Unnamed(1));
511    ///
512    /// let variant = Variant::Static(VARIANT);
513    /// assert!(!variant.is_named_fields());
514    /// ```
515    pub fn is_named_fields(&self) -> bool {
516        self.fields().is_named()
517    }
518
519    /// Returns `true` if the variant has associated unnamed fields.
520    ///
521    /// # Examples
522    ///
523    /// With named fields
524    ///
525    /// ```
526    /// use valuable::{Fields, NamedField, Variant, VariantDef};
527    ///
528    /// static VARIANT: &VariantDef<'static> = &VariantDef::new(
529    ///     "Foo", Fields::Named(&[NamedField::new("hello")]));
530    ///
531    /// let variant = Variant::Static(VARIANT);
532    /// assert!(!variant.is_unnamed_fields());
533    /// ```
534    ///
535    /// With unnamed fields
536    ///
537    /// ```
538    /// use valuable::{Fields, Variant, VariantDef};
539    ///
540    /// static VARIANT: &VariantDef<'static> = &VariantDef::new(
541    ///     "Foo", Fields::Unnamed(1));
542    ///
543    /// let variant = Variant::Static(VARIANT);
544    /// assert!(variant.is_unnamed_fields());
545    /// ```
546    pub fn is_unnamed_fields(&self) -> bool {
547        !self.is_named_fields()
548    }
549}
550
551impl fmt::Debug for dyn Enumerable + '_ {
552    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
553        let variant = self.variant();
554        #[cfg(feature = "alloc")]
555        let name = format!("{}::{}", self.definition().name(), variant.name());
556        #[cfg(not(feature = "alloc"))]
557        let name = variant.name();
558
559        if variant.is_named_fields() {
560            struct DebugEnum<'a, 'b> {
561                fmt: fmt::DebugStruct<'a, 'b>,
562            }
563
564            let mut debug = DebugEnum {
565                fmt: fmt.debug_struct(&name),
566            };
567
568            impl Visit for DebugEnum<'_, '_> {
569                fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
570                    for (field, value) in named_values {
571                        self.fmt.field(field.name(), value);
572                    }
573                }
574
575                fn visit_value(&mut self, _: Value<'_>) {
576                    unreachable!();
577                }
578            }
579
580            self.visit(&mut debug);
581
582            debug.fmt.finish()
583        } else {
584            struct DebugEnum<'a, 'b> {
585                fmt: fmt::DebugTuple<'a, 'b>,
586            }
587
588            let mut debug = DebugEnum {
589                fmt: fmt.debug_tuple(&name),
590            };
591
592            impl Visit for DebugEnum<'_, '_> {
593                fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
594                    for value in values {
595                        self.fmt.field(value);
596                    }
597                }
598
599                fn visit_value(&mut self, _: Value<'_>) {
600                    unreachable!();
601                }
602            }
603
604            self.visit(&mut debug);
605
606            debug.fmt.finish()
607        }
608    }
609}
610
611macro_rules! deref {
612    (
613        $(
614            $(#[$attrs:meta])*
615            $ty:ty,
616        )*
617    ) => {
618        $(
619            $(#[$attrs])*
620            impl<T: ?Sized + Enumerable> Enumerable for $ty {
621                fn definition(&self) -> EnumDef<'_> {
622                    T::definition(&**self)
623                }
624
625                fn variant(&self) -> Variant<'_> {
626                    T::variant(&**self)
627                }
628            }
629        )*
630    };
631}
632
633deref! {
634    &T,
635    &mut T,
636    #[cfg(feature = "alloc")]
637    alloc::boxed::Box<T>,
638    #[cfg(feature = "alloc")]
639    alloc::rc::Rc<T>,
640    #[cfg(not(valuable_no_atomic_cas))]
641    #[cfg(feature = "alloc")]
642    alloc::sync::Arc<T>,
643}
644
645static RESULT_VARIANTS: &[VariantDef<'static>] = &[
646    VariantDef::new("Ok", Fields::Unnamed(1)),
647    VariantDef::new("Err", Fields::Unnamed(1)),
648];
649
650impl<T, E> Enumerable for Result<T, E>
651where
652    T: Valuable,
653    E: Valuable,
654{
655    fn definition(&self) -> EnumDef<'_> {
656        EnumDef::new_static("Result", RESULT_VARIANTS)
657    }
658
659    fn variant(&self) -> Variant<'_> {
660        match self {
661            Ok(_) => Variant::Static(&RESULT_VARIANTS[0]),
662            Err(_) => Variant::Static(&RESULT_VARIANTS[1]),
663        }
664    }
665}
666
667impl<T, E> Valuable for Result<T, E>
668where
669    T: Valuable,
670    E: Valuable,
671{
672    fn as_value(&self) -> Value<'_> {
673        Value::Enumerable(self)
674    }
675
676    fn visit(&self, visitor: &mut dyn Visit) {
677        match self {
678            Ok(val) => visitor.visit_unnamed_fields(&[val.as_value()]),
679            Err(val) => visitor.visit_unnamed_fields(&[val.as_value()]),
680        }
681    }
682}