meme_id/schemes/
adjective_noun.rs

1use core::fmt;
2
3use crate::{
4    dict::{Adjective, Mapper, Noun},
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 AdjectiveNoun {
12    pub adjective: &'static str,
13    pub noun: &'static str,
14}
15
16impl AdjectiveNoun {
17    /// Encodes bits into `adjective noun verb adverb` scheme
18    #[inline]
19    pub fn encode(bits: u16) -> Self {
20        encode(bits)
21    }
22
23    /// Transform to hyphenated.
24    #[inline]
25    pub fn hyphenated(self) -> Hyphenated<Self> {
26        Hyphenated(self)
27    }
28}
29
30impl fmt::Display for AdjectiveNoun {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        write!(f, "The {} {}", self.adjective, self.noun)
33    }
34}
35
36impl fmt::Display for Hyphenated<AdjectiveNoun> {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        write!(f, "{}-{}", self.0.adjective, self.0.noun)
39    }
40}
41
42/// Encodes bits into `adjective-noun` scheme
43/// For 16-bit ids.
44pub fn encode(bits: u16) -> AdjectiveNoun {
45    let (adjective, bits) = Adjective::encode_word(bits.into());
46    let (noun, bits) = Noun::encode_word(bits);
47
48    debug_assert_eq!(bits, 0);
49
50    AdjectiveNoun { adjective, noun }
51}
52
53/// Decodes `adjective-noun` scheme
54/// For 16-bit ids.
55pub fn decode(s: &str) -> Result<u16, Error> {
56    let mut iter = string_to_words(s);
57
58    skip_one_of(&mut iter, &["a", "the"]);
59
60    let adjective = iter.next().ok_or(Error::NotEnoughWords {
61        expected: 2,
62        actual: 0,
63    })?;
64    let noun = iter.next().ok_or(Error::NotEnoughWords {
65        expected: 2,
66        actual: 1,
67    })?;
68
69    if iter.next().is_some() {
70        return Err(Error::TrailingWords);
71    }
72
73    let mut bits = 0;
74    bits = Noun::decode_word(noun, bits).ok_or(Error::Unrecognized { word: noun })?;
75    bits =
76        Adjective::decode_word(adjective, bits).ok_or(Error::Unrecognized { word: adjective })?;
77    Ok(bits as u16)
78}
79
80#[cfg(feature = "serde")]
81pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
82where
83    T: Copy + Into<u16>,
84    S: serde::ser::Serializer,
85{
86    use alloc::string::ToString;
87    use serde::Serialize;
88
89    let an = encode((*value).into());
90    an.to_string().serialize(serializer)
91}
92
93#[cfg(feature = "serde")]
94pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
95where
96    u16: Into<T>,
97    D: serde::de::Deserializer<'de>,
98{
99    use alloc::borrow::Cow;
100
101    let s = <Cow<str> as serde::de::Deserialize>::deserialize(deserializer)?;
102    match decode(&*s) {
103        Err(err) => Err(serde::de::Error::custom(err)),
104        Ok(id) => Ok(id.into()),
105    }
106}