Skip to main content

blockworx_doc/
values.rs

1//! Shared value enums: the closed vocabularies entity registers draw from.
2//! Serde variant names are wire tags — never rename or repurpose a variant;
3//! deprecate and add instead. Rationale: `docs/doc-ng-design-notes.md`.
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Copy, PartialEq, Eq, Default, Debug, Serialize, Deserialize)]
8pub enum LabelSide {
9    #[default]
10    Top,
11    Center,
12    Bottom,
13}
14
15/// The 9-accent palette; `Accent0` is the meaningful default ("plain").
16#[derive(Clone, Copy, PartialEq, Eq, Default, Debug, Serialize, Deserialize)]
17pub enum Role {
18    #[default]
19    Accent0,
20    Accent1,
21    Accent2,
22    Accent3,
23    Accent4,
24    Accent5,
25    Accent6,
26    Accent7,
27    Accent8,
28}
29
30#[derive(Clone, Copy, PartialEq, Eq, Default, Debug, Serialize, Deserialize)]
31pub enum PinDir {
32    #[default]
33    Input,
34    InOut,
35    Output,
36}
37
38/// Which block edge a pin occupies. `West` is the zero: every auto-placed
39/// port starts there.
40#[derive(Clone, Copy, PartialEq, Eq, Hash, Default, Debug, Serialize, Deserialize)]
41pub enum PinSide {
42    #[default]
43    West,
44    East,
45}
46
47impl PinSide {
48    #[must_use]
49    pub fn flip(self) -> Self {
50        match self {
51            Self::West => Self::East,
52            Self::East => Self::West,
53        }
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    /// The zero-value model reads these defaults as its meaningful zeros;
62    /// changing one changes every default-initialized register.
63    #[test]
64    fn defaults_are_the_meaningful_zeros() {
65        assert_eq!(Role::default(), Role::Accent0);
66        assert_eq!(LabelSide::default(), LabelSide::Top);
67        assert_eq!(PinDir::default(), PinDir::Input);
68        assert_eq!(PinSide::default(), PinSide::West);
69    }
70
71    #[test]
72    fn flipping_a_side_is_an_involution() {
73        for side in [PinSide::West, PinSide::East] {
74            assert_ne!(side.flip(), side);
75            assert_eq!(side.flip().flip(), side);
76        }
77    }
78
79    /// Variant names are wire tags. This pins every one until the port's
80    /// golden-bytes tests take over (`docs/doc-ng-port-playbook.md`, step 11).
81    #[test]
82    fn serde_names_are_stable() {
83        fn name<T: Serialize>(value: &T) -> String {
84            serde_json::to_string(value).expect("value enums serialize infallibly")
85        }
86
87        let roles = [
88            Role::Accent0,
89            Role::Accent1,
90            Role::Accent2,
91            Role::Accent3,
92            Role::Accent4,
93            Role::Accent5,
94            Role::Accent6,
95            Role::Accent7,
96            Role::Accent8,
97        ];
98        for (i, role) in roles.into_iter().enumerate() {
99            assert_eq!(name(&role), format!("\"Accent{i}\""));
100        }
101
102        assert_eq!(name(&LabelSide::Top), "\"Top\"");
103        assert_eq!(name(&LabelSide::Center), "\"Center\"");
104        assert_eq!(name(&LabelSide::Bottom), "\"Bottom\"");
105
106        assert_eq!(name(&PinDir::Input), "\"Input\"");
107        assert_eq!(name(&PinDir::InOut), "\"InOut\"");
108        assert_eq!(name(&PinDir::Output), "\"Output\"");
109
110        assert_eq!(name(&PinSide::West), "\"West\"");
111        assert_eq!(name(&PinSide::East), "\"East\"");
112    }
113}