Skip to main content

blockworx/schema/
enums.rs

1//! Schema copies of the small vocabulary enums. serde spells them
2//! kebab-case in JSON, and [`FromStr`](std::str::FromStr) / [`AsRef<str>`]
3//! agree with it, so a legacy file and a current one say `in-out` the same
4//! way.
5//! The bridges to the doc crate's own enums live app-side as plain functions
6//! in `crate::edit::lower` (`pin_side`, `label_side`, `pin_dir`, …).
7
8use serde::{Deserialize, Serialize};
9
10macro_rules! kebab_enum {
11    ($schema:ident { $($variant:ident = $kebab:literal),+ $(,)? } $(default $default:ident)?) => {
12        #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize $(, kebab_enum!(@default $default))?)]
13        #[serde(rename_all = "kebab-case")]
14        pub enum $schema {
15            $($variant),+
16        }
17
18        impl $schema {
19            /// The kebab-case spelling used on both wires.
20            #[allow(dead_code)]
21            pub fn as_str(self) -> &'static str {
22                match self { $(Self::$variant => $kebab),+ }
23            }
24        }
25
26        impl std::str::FromStr for $schema {
27            type Err = String;
28            fn from_str(s: &str) -> Result<Self, String> {
29                match s {
30                    $($kebab => Ok(Self::$variant),)+
31                    _ => Err(format!(
32                        concat!("expected one of ", $("`", $kebab, "` ",)+),
33                    )),
34                }
35            }
36        }
37    };
38    (@default $default:ident) => { Default };
39}
40
41kebab_enum!(PinSide { East = "east", West = "west" });
42kebab_enum!(PinType { Input = "input", Output = "output", InOut = "in-out" });
43kebab_enum!(LabelSide { Top = "top", Center = "center", Bottom = "bottom" });