1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub struct JohnsonSolidId(u8);
7
8impl JohnsonSolidId {
9 #[must_use]
11 pub const fn new(number: u8) -> Option<Self> {
12 if number >= 1 && number <= 92 {
13 Some(Self(number))
14 } else {
15 None
16 }
17 }
18
19 #[must_use]
21 pub const fn number(self) -> u8 {
22 self.0
23 }
24
25 #[must_use]
27 pub fn label(self) -> String {
28 format!("J{}", self.0)
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub struct JohnsonSolid {
35 id: JohnsonSolidId,
36}
37
38impl JohnsonSolid {
39 #[must_use]
41 pub const fn new(id: JohnsonSolidId) -> Self {
42 Self { id }
43 }
44
45 #[must_use]
47 pub const fn id(self) -> JohnsonSolidId {
48 self.id
49 }
50
51 #[must_use]
53 pub const fn name(self) -> Option<&'static str> {
54 match self.id.number() {
55 1 => Some("square pyramid"),
56 2 => Some("pentagonal pyramid"),
57 3 => Some("triangular cupola"),
58 4 => Some("square cupola"),
59 5 => Some("pentagonal cupola"),
60 6 => Some("pentagonal rotunda"),
61 92 => Some("triangular hebesphenorotunda"),
62 _ => None,
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::{JohnsonSolid, JohnsonSolidId};
70
71 #[test]
72 fn validates_johnson_solid_ids() {
73 let id = JohnsonSolidId::new(1).expect("valid id");
74 let solid = JohnsonSolid::new(id);
75
76 assert_eq!(id.number(), 1);
77 assert_eq!(id.label(), "J1");
78 assert_eq!(solid.name(), Some("square pyramid"));
79 assert_eq!(JohnsonSolidId::new(93), None);
80 }
81}