meme_id/schemes/
adjective_noun.rs1use 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 #[inline]
19 pub fn encode(bits: u16) -> Self {
20 encode(bits)
21 }
22
23 #[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
42pub 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
53pub 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}