meme_id/schemes/
phrase.rs

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    /// Encodes bits into `adjective noun verb adverb` scheme
24    #[inline]
25    pub fn encode(bits: u64) -> Self {
26        encode(bits)
27    }
28
29    /// Transform to hyphenated.
30    #[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
70/// Encodes bits into a phrase.
71/// For 64-bit ids.
72pub 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
93/// Decodes a phrase.
94/// For 64-bit ids.
95pub 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}