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}