1use core::fmt;
2
3use crate::{
4 dict::{Adjective, Mapper, ObjectPronoun, Singular, Verb},
5 Hyphenated,
6};
7
8use super::{string_to_words, Error};
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct Punk {
12 pub verbs: [&'static str; 4],
13 pub pronouns: [&'static str; 4],
14 pub adjectives: [&'static str; 4],
15}
16
17impl Punk {
18 #[inline]
20 pub fn encode(bits: u64) -> Self {
21 encode(bits)
22 }
23
24 #[inline]
26 pub fn hyphenated(self) -> Hyphenated<Self> {
27 Hyphenated(self)
28 }
29}
30
31impl fmt::Display for Punk {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(
34 f,
35 "{}{} {}{}, {}{} {}{}\n{}{} {}{}, {}{} {}{}\n{}{}, {}{}\n{}{}, {}{}",
36 &self.verbs[0].chars().next().unwrap().to_uppercase(),
37 &self.verbs[0][1..],
38 &self.pronouns[0].chars().next().unwrap().to_uppercase(),
39 &self.pronouns[0][1..],
40 &self.verbs[1].chars().next().unwrap().to_uppercase(),
41 &self.verbs[1][1..],
42 &self.pronouns[1].chars().next().unwrap().to_uppercase(),
43 &self.pronouns[1][1..],
44 &self.verbs[2].chars().next().unwrap().to_uppercase(),
45 &self.verbs[2][1..],
46 &self.pronouns[2].chars().next().unwrap().to_uppercase(),
47 &self.pronouns[2][1..],
48 &self.verbs[3].chars().next().unwrap().to_uppercase(),
49 &self.verbs[3][1..],
50 &self.pronouns[3].chars().next().unwrap().to_uppercase(),
51 &self.pronouns[3][1..],
52 &self.adjectives[0].chars().next().unwrap().to_uppercase(),
53 &self.adjectives[0][1..],
54 &self.adjectives[1].chars().next().unwrap().to_uppercase(),
55 &self.adjectives[1][1..],
56 &self.adjectives[2].chars().next().unwrap().to_uppercase(),
57 &self.adjectives[2][1..],
58 &self.adjectives[3].chars().next().unwrap().to_uppercase(),
59 &self.adjectives[3][1..],
60 )
61 }
62}
63
64impl fmt::Display for Hyphenated<Punk> {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 write!(
67 f,
68 "{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}",
69 &self.0.verbs[0],
70 &self.0.pronouns[0],
71 &self.0.verbs[1],
72 &self.0.pronouns[1],
73 &self.0.verbs[2],
74 &self.0.pronouns[2],
75 &self.0.verbs[3],
76 &self.0.pronouns[3],
77 &self.0.adjectives[0],
78 &self.0.adjectives[1],
79 &self.0.adjectives[2],
80 &self.0.adjectives[3],
81 )
82 }
83}
84
85pub fn encode(bits: u64) -> Punk {
88 let (verbs, bits) = Verb::<Singular>::encode_words(bits.into());
89 let (pronouns, bits) = ObjectPronoun::encode_words(bits.into());
90 let (adjectives, bits) = Adjective::encode_words(bits.into());
91
92 debug_assert_eq!(bits, 0);
93
94 Punk {
95 verbs,
96 pronouns,
97 adjectives,
98 }
99}
100
101pub fn decode(s: &str) -> Result<u64, Error> {
104 let mut split = string_to_words(s);
105
106 let verb1 = split.next().ok_or(Error::NotEnoughWords {
107 expected: 12,
108 actual: 0,
109 })?;
110 let pronoun1 = split.next().ok_or(Error::NotEnoughWords {
111 expected: 12,
112 actual: 1,
113 })?;
114 let verb2 = split.next().ok_or(Error::NotEnoughWords {
115 expected: 12,
116 actual: 2,
117 })?;
118 let pronoun2 = split.next().ok_or(Error::NotEnoughWords {
119 expected: 12,
120 actual: 3,
121 })?;
122 let verb3 = split.next().ok_or(Error::NotEnoughWords {
123 expected: 12,
124 actual: 4,
125 })?;
126 let pronoun3 = split.next().ok_or(Error::NotEnoughWords {
127 expected: 12,
128 actual: 5,
129 })?;
130 let verb4 = split.next().ok_or(Error::NotEnoughWords {
131 expected: 12,
132 actual: 6,
133 })?;
134 let pronoun4 = split.next().ok_or(Error::NotEnoughWords {
135 expected: 12,
136 actual: 7,
137 })?;
138 let adjective1 = split.next().ok_or(Error::NotEnoughWords {
139 expected: 12,
140 actual: 8,
141 })?;
142 let adjective2 = split.next().ok_or(Error::NotEnoughWords {
143 expected: 12,
144 actual: 9,
145 })?;
146 let adjective3 = split.next().ok_or(Error::NotEnoughWords {
147 expected: 12,
148 actual: 10,
149 })?;
150 let adjective4 = split.next().ok_or(Error::NotEnoughWords {
151 expected: 12,
152 actual: 11,
153 })?;
154
155 if split.next().is_some() {
156 return Err(Error::TrailingWords);
157 }
158
159 let adjectives = [adjective4, adjective3, adjective2, adjective1];
160 let pronouns = [pronoun4, pronoun3, pronoun2, pronoun1];
161 let verbs = [verb4, verb3, verb2, verb1];
162
163 let mut bits = 0;
164 bits = Adjective::decode_words(adjectives, bits).map_err(|i| Error::Unrecognized {
165 word: adjectives[i],
166 })?;
167 bits = ObjectPronoun::decode_words(pronouns, bits)
168 .map_err(|i| Error::Unrecognized { word: pronouns[i] })?;
169 bits = Verb::<Singular>::decode_words(verbs, bits)
170 .map_err(|i| Error::Unrecognized { word: verbs[i] })?;
171
172 Ok(bits as u64)
173}
174
175#[cfg(feature = "serde")]
176pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
177where
178 T: Copy + Into<u64>,
179 S: serde::ser::Serializer,
180{
181 use alloc::string::ToString;
182 use serde::Serialize;
183
184 let an = encode((*value).into());
185 an.to_string().serialize(serializer)
186}
187
188#[cfg(feature = "serde")]
189pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
190where
191 u64: Into<T>,
192 D: serde::de::Deserializer<'de>,
193{
194 use alloc::borrow::Cow;
195
196 let s = <Cow<str> as serde::de::Deserialize>::deserialize(deserializer)?;
197 match decode(&*s) {
198 Err(err) => Err(serde::de::Error::custom(err)),
199 Ok(id) => Ok(id.into()),
200 }
201}