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