Skip to main content

http_msgsign/components/
params.rs

1use indexmap::IndexMap;
2use sfv::{Dictionary, FieldType, Item, List, ListEntry};
3use std::collections::HashSet;
4use std::fmt::{Debug, Display, Formatter};
5use std::hash::{Hash, Hasher};
6
7use crate::base64::Base64EncodedString;
8use crate::components::values::Value;
9use crate::errors::{InvalidComponentParameter, InvalidFormat, InvalidSerializer, SerializeError};
10
11pub mod param {
12    use crate::components::params::{Bs, Key, Name, Req, Sf, Tr};
13
14    pub fn key(key: impl Into<String>) -> Key {
15        Key(key.into())
16    }
17    pub fn name(name: impl Into<String>) -> Name {
18        Name(name.into())
19    }
20    pub const fn sf() -> Sf {
21        Sf
22    }
23    pub const fn bs() -> Bs {
24        Bs
25    }
26    pub const fn tr() -> Tr {
27        Tr
28    }
29    pub const fn req() -> Req {
30        Req
31    }
32}
33
34#[derive(Debug, Clone, Eq, PartialEq)]
35pub struct Serializer {
36    methods: IndexMap<String, SerializerType>,
37    require_request: bool,
38}
39
40impl Hash for Serializer {
41    fn hash<H: Hasher>(&self, state: &mut H) {
42        self.to_string().hash(state)
43    }
44}
45
46impl Serializer {
47    pub fn serialize(&self, mut value: Value) -> Result<Value, SerializeError> {
48        for (_, ser) in &self.methods {
49            value = ser.serialize(value)?;
50        }
51        Ok(value)
52    }
53
54    pub fn require_request(&self) -> bool {
55        self.require_request
56    }
57
58    pub fn name(&self) -> Option<&str> {
59        let Some(SerializerType::Name(name)) = self.methods.get(Name::IDENT) else {
60            return None;
61        };
62        Some(name.0.as_str())
63    }
64}
65
66impl Display for Serializer {
67    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
68        let p = self
69            .methods
70            .iter()
71            .map(|(_, ser)| ser.to_string())
72            .collect::<Vec<_>>()
73            .join("");
74        write!(f, "{}", p)
75    }
76}
77
78#[macro_export]
79macro_rules! params {
80    [] => { $crate::components::params::FieldParameter::default() };
81    [$($param:ident),*] => {
82        $crate::components::params::FieldParameter::default()
83            $(.add_param($crate::components::params::param::$param()))*
84    };
85    [$key:ident($arg:tt)] => {
86        $crate::components::params::FieldParameter::default()
87            .add_param($crate::components::params::param::$key($arg))
88    };
89    [$key:ident($arg:tt), $($param:ident),*] => {
90        $crate::components::params::FieldParameter::default()
91            .add_param($crate::components::params::param::$key($arg))
92            $(.add_param($crate::components::params::param::$param()))*
93    };
94}
95
96pub struct FieldParameter {
97    builder: Result<Serializer, InvalidSerializer>,
98}
99
100impl Default for FieldParameter {
101    fn default() -> Self {
102        Self {
103            builder: Ok(Serializer {
104                methods: IndexMap::new(),
105                require_request: false,
106            }),
107        }
108    }
109}
110
111impl FieldParameter {
112    pub fn add_param<P>(self, param: P) -> Self
113    where
114        P: Into<SerializerType> + DefinedParam,
115    {
116        self.and_then(|mut ser| {
117            let ident = P::IDENT;
118            let param = param.into();
119
120            if let SerializerType::Req(_) = param {
121                ser.require_request = true;
122            }
123
124            if ser.methods.insert(ident.to_string(), param).is_some() {
125                return Err(InvalidSerializer::Duplicated(ident.to_string()));
126            }
127
128            Ok(ser)
129        })
130    }
131
132    pub fn into_serializer(self) -> Result<Serializer, InvalidSerializer> {
133        self.builder.and_then(|ser| {
134            let methods = &ser.methods;
135            methods.iter().try_for_each(|(_, interrogator)| {
136                if methods.iter().any(|(contain, _)| {
137                    interrogator.incompatible()
138                        .iter()
139                        .any(|reject| *contain == *reject)
140                }) {
141                    let contains = methods.iter()
142                        .map(|(key, _)| key.as_str())
143                        .collect::<HashSet<_>>();
144                    let incompatible = interrogator.incompatible()
145                        .iter()
146                        .copied()
147                        .collect::<HashSet<_>>();
148                    let interrogator = interrogator.as_str();
149                    let Some(reject) = (&contains & &incompatible).iter()
150                        .map(|st| st.to_string())
151                        .reduce(|mut acc, s| {
152                            acc += &format!(", {}", s);
153                            acc
154                        })
155                    else {
156                        unreachable!("At the time this error occurs, some incompatibility information should have been obtained.")
157                    };
158                    return Err(InvalidSerializer::Incompatible {
159                        interrogator,
160                        reject,
161                    })
162                }
163                Ok(())
164            })?;
165            Ok(ser)
166        })
167    }
168
169    // Helper
170    fn and_then<F>(self, f: F) -> Self
171    where
172        F: FnOnce(Serializer) -> Result<Serializer, InvalidSerializer>,
173    {
174        Self {
175            builder: self.builder.and_then(f),
176        }
177    }
178}
179
180impl TryFrom<sfv::Parameters> for Serializer {
181    type Error = InvalidSerializer;
182
183    fn try_from(value: sfv::Parameters) -> Result<Self, Self::Error> {
184        let ser = value
185            .into_iter()
186            .map(SerializerType::try_from)
187            .flat_map(|ser| match ser {
188                Ok(ser) => Ok((ser.as_str().to_string(), ser)),
189                Err(err) => Err(err),
190            })
191            .collect::<IndexMap<_, _>>();
192
193        let require_request = ser.contains_key(Req::IDENT);
194
195        Ok(Self {
196            methods: ser,
197            require_request,
198        })
199    }
200}
201
202#[derive(Debug, Clone, Eq, PartialEq, Hash)]
203pub enum SerializerType {
204    Sf(Sf),
205    Key(Key),
206    Bs(Bs),
207    Tr(Tr),
208    Req(Req),
209    Name(Name),
210}
211
212impl SerializerType {
213    pub const fn incompatible(&self) -> &[&str] {
214        match self {
215            SerializerType::Sf(_) => &["key", "bs"],
216            SerializerType::Key(_) => &["sf", "bs"],
217            SerializerType::Bs(_) => &["sf", "key"],
218            _ => &[],
219        }
220    }
221
222    pub const fn as_str(&self) -> &'static str {
223        match self {
224            SerializerType::Sf(_) => "sf",
225            SerializerType::Key(_) => "key",
226            SerializerType::Bs(_) => "bs",
227            SerializerType::Tr(_) => "tr",
228            SerializerType::Req(_) => "req",
229            SerializerType::Name(_) => "name",
230        }
231    }
232}
233
234impl Display for SerializerType {
235    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
236        match self {
237            SerializerType::Sf(ser) => Display::fmt(ser, f),
238            SerializerType::Key(ser) => Display::fmt(ser, f),
239            SerializerType::Bs(ser) => Display::fmt(ser, f),
240            SerializerType::Tr(ser) => Display::fmt(ser, f),
241            SerializerType::Req(ser) => Display::fmt(ser, f),
242            SerializerType::Name(ser) => Display::fmt(ser, f),
243        }
244    }
245}
246
247impl ValueSerializer for SerializerType {
248    fn serialize(&self, value: Value) -> Result<Value, SerializeError> {
249        match self {
250            SerializerType::Sf(ser) => ser.serialize(value),
251            SerializerType::Key(ser) => ser.serialize(value),
252            SerializerType::Bs(ser) => ser.serialize(value),
253            _ => Ok(value),
254        }
255    }
256}
257
258impl TryFrom<(sfv::Key, sfv::BareItem)> for SerializerType {
259    type Error = InvalidComponentParameter;
260
261    fn try_from((key, item): (sfv::Key, sfv::BareItem)) -> Result<Self, Self::Error> {
262        match (key.as_str(), item) {
263            ("sf", sfv::BareItem::Boolean(bool)) if bool => Ok(Self::Sf(Sf)),
264            ("key", sfv::BareItem::String(key)) => Ok(Self::Key(Key(key.into()))),
265            ("bs", sfv::BareItem::Boolean(bool)) if bool => Ok(Self::Bs(Bs)),
266            ("req", sfv::BareItem::Boolean(bool)) if bool => Ok(Self::Req(Req)),
267            ("tr", sfv::BareItem::Boolean(bool)) if bool => Ok(Self::Tr(Tr)),
268            ("name", sfv::BareItem::String(name)) => Ok(Self::Name(Name(name.into()))),
269            (_, value) => Err(InvalidComponentParameter(key, value)),
270        }
271    }
272}
273
274pub trait DefinedParam: 'static + Sync + Send {
275    const IDENT: &'static str;
276}
277
278pub trait ValueSerializer: 'static + Sync + Send {
279    fn serialize(&self, value: Value) -> Result<Value, SerializeError>;
280}
281
282#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
283pub struct Sf;
284
285impl From<Sf> for SerializerType {
286    fn from(value: Sf) -> Self {
287        SerializerType::Sf(value)
288    }
289}
290
291impl Display for Sf {
292    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
293        write!(f, ";sf")
294    }
295}
296
297impl DefinedParam for Sf {
298    const IDENT: &'static str = "sf";
299}
300
301impl ValueSerializer for Sf {
302    fn serialize(&self, value: Value) -> Result<Value, SerializeError> {
303        let Value::String(st) = value else {
304            return Err(SerializeError::InvalidSerializableValue {
305                param_type: ";sf".to_string(),
306                current_type: "ByteSequence",
307            });
308        };
309
310        let value = if let Ok(item) = sfv::Parser::new(&st).parse::<Item>() {
311            Ok(item.serialize())
312        } else if let Ok(dict) = sfv::Parser::new(&st).parse::<Dictionary>() {
313            Ok(dict.serialize().unwrap_or_default())
314        } else if let Ok(list) = sfv::Parser::new(&st).parse::<List>() {
315            Ok(list.serialize().unwrap_or_default())
316        } else {
317            Err(SerializeError::FailedParseToSfv)
318        }?;
319
320        Ok(Value::String(value))
321    }
322}
323
324#[derive(Debug, Clone, Hash, Eq, PartialEq)]
325pub struct Key(String);
326
327impl From<Key> for SerializerType {
328    fn from(value: Key) -> Self {
329        SerializerType::Key(value)
330    }
331}
332
333impl Display for Key {
334    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
335        write!(f, ";key=\"{}\"", self.0)
336    }
337}
338
339impl DefinedParam for Key {
340    const IDENT: &'static str = "key";
341}
342
343impl ValueSerializer for Key {
344    fn serialize(&self, value: Value) -> Result<Value, SerializeError> {
345        let key = self.0.as_str();
346        let Value::String(st) = value else {
347            return Err(SerializeError::InvalidSerializableValue {
348                param_type: format!(";key=\"{}\"", self.0),
349                current_type: "ByteSequence",
350            });
351        };
352
353        let mut dict = sfv::Parser::new(&st)
354            .parse::<Dictionary>()
355            .map_err(InvalidFormat::Dictionary)?;
356
357        let Some(entry) = dict.shift_remove(key) else {
358            return Err(SerializeError::EntryNotExistsInDictionary(key.to_string()));
359        };
360
361        let value = match entry {
362            ListEntry::Item(item) => item.serialize(),
363            entry @ ListEntry::InnerList(_) => vec![entry].serialize().unwrap_or_default(),
364        };
365
366        Ok(Value::String(value))
367    }
368}
369
370#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
371pub struct Bs;
372
373impl From<Bs> for SerializerType {
374    fn from(value: Bs) -> Self {
375        SerializerType::Bs(value)
376    }
377}
378
379impl Display for Bs {
380    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
381        write!(f, ";bs")
382    }
383}
384
385impl DefinedParam for Bs {
386    const IDENT: &'static str = "bs";
387}
388
389impl ValueSerializer for Bs {
390    fn serialize(&self, value: Value) -> Result<Value, SerializeError> {
391        let byte_seq = match value {
392            Value::String(st) => vec![Base64EncodedString::new(st)],
393            Value::BytesList(list) => list
394                .into_iter()
395                .map(Base64EncodedString::new)
396                .collect::<Vec<_>>(),
397        };
398
399        let value = byte_seq
400            .into_iter()
401            .map(|seq| seq.to_sfv())
402            .collect::<Vec<String>>()
403            .join(", ");
404
405        Ok(Value::String(value))
406    }
407}
408
409#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
410pub struct Tr;
411
412impl From<Tr> for SerializerType {
413    fn from(value: Tr) -> Self {
414        SerializerType::Tr(value)
415    }
416}
417
418impl Display for Tr {
419    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
420        write!(f, ";tr")
421    }
422}
423
424impl DefinedParam for Tr {
425    const IDENT: &'static str = "tr";
426}
427
428#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
429pub struct Req;
430
431impl From<Req> for SerializerType {
432    fn from(value: Req) -> Self {
433        SerializerType::Req(value)
434    }
435}
436
437impl Display for Req {
438    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
439        write!(f, ";req")
440    }
441}
442
443impl DefinedParam for Req {
444    const IDENT: &'static str = "req";
445}
446
447#[derive(Debug, Clone, Hash, Eq, PartialEq)]
448pub struct Name(String);
449
450impl From<Name> for SerializerType {
451    fn from(value: Name) -> Self {
452        SerializerType::Name(value)
453    }
454}
455
456impl Display for Name {
457    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
458        write!(f, ";name=\"{}\"", self.0)
459    }
460}
461
462impl DefinedParam for Name {
463    const IDENT: &'static str = "name";
464}
465
466#[cfg(test)]
467mod test {
468    use super::*;
469
470    #[test]
471    fn test_incompatible_serializers() {
472        let ser = params![sf, bs].into_serializer();
473        assert!(ser.is_err());
474
475        let ser = params![key("a"), sf].into_serializer();
476        assert!(ser.is_err());
477
478        let ser = params![key("a"), bs].into_serializer();
479        assert!(ser.is_err());
480
481        let ser = params![key("a"), sf, bs].into_serializer();
482        assert!(ser.is_err());
483
484        let ser = params![key("a")].into_serializer();
485        assert!(ser.is_ok());
486    }
487
488    #[test]
489    #[should_panic]
490    fn test_duplicated_serializers() {
491        let _ = params![sf, sf].into_serializer().unwrap();
492    }
493
494    #[test]
495    #[should_panic]
496    fn test_report_incompatible_serializers() {
497        let _ = params![sf, bs].into_serializer().unwrap();
498    }
499
500    #[test]
501    fn test_sf_serializer() {
502        let val = Value::String(r#" "london",   "berlin" "#.to_string());
503        let ser = params![sf].into_serializer().unwrap();
504        let val = ser.serialize(val).unwrap();
505        let Value::String(visible) = val else {
506            panic!("Expected String, but got {:?}", val);
507        };
508
509        // Normalized to List in sf-list.
510        assert_eq!(visible, r#""london", "berlin""#);
511    }
512
513    #[test]
514    fn test_key_serializer() {
515        let dict = Value::String(r#" a=1, b=2;x=1;y=2, c=(a   b    c);valid, d"#.to_string());
516
517        // extract key=`a` from dict
518        let ser = params![key("a")].into_serializer().unwrap();
519        let val = ser.serialize(dict.clone()).unwrap();
520        let Value::String(visible) = val else {
521            panic!("Expected String, but got {:?}", val);
522        };
523
524        // it's mean integer in sf-integer
525        assert_eq!(visible, r#"1"#);
526
527        // extract key=`b` from dict
528        let ser = params![key("b")].into_serializer().unwrap();
529        let val = ser.serialize(dict.clone()).unwrap();
530        let Value::String(visible) = val else {
531            panic!("Expected String, but got {:?}", val);
532        };
533
534        // it's mean integer(2) with parameters x=1, y=2
535        assert_eq!(visible, r#"2;x=1;y=2"#);
536
537        // extract key=`c` from dict
538        let ser = params![key("c")].into_serializer().unwrap();
539        let val = ser.serialize(dict.clone()).unwrap();
540        let Value::String(visible) = val else {
541            panic!("Expected String, but got {:?}", val);
542        };
543
544        // it's mean inner-list in sfv
545        assert_eq!(visible, r#"(a b c);valid"#);
546
547        // extract key=`d` from dict
548        let ser = params![key("d")].into_serializer().unwrap();
549        let val = ser.serialize(dict.clone()).unwrap();
550        let Value::String(visible) = val else {
551            panic!("Expected String, but got {:?}", val);
552        };
553
554        // it's mean true in sf-boolean
555        assert_eq!(visible, "?1");
556    }
557
558    //noinspection SpellCheckingInspection
559    #[test]
560    fn test_bs_serializer() {
561        let val = Value::String(r#"value, with, lots, of, commas"#.to_string());
562        let ser = params![bs].into_serializer().unwrap();
563        let val = ser.serialize(val).unwrap();
564        let Value::String(val) = val else {
565            panic!("Expected String, but got {:?}", val);
566        };
567
568        // it's mean ByteSequence(Base64) in sf-byte-sequence
569        assert_eq!(val, ":dmFsdWUsIHdpdGgsIGxvdHMsIG9mLCBjb21tYXM=:");
570    }
571
572    //noinspection SpellCheckingInspection
573    #[test]
574    fn test_nothing_operation_param() {
575        let list = Value::String(r#" "london",   "berlin" "#.to_string());
576        let ser = params![tr].into_serializer().unwrap();
577        let val = ser.serialize(list.clone()).unwrap();
578        let Value::String(val) = val else {
579            panic!("Expected String, but got {:?}", val);
580        };
581
582        // If you've read RFC9421, this test will seem a bit odd.
583        // You would think that the whitespace on both ends should be gone,
584        // but rest assured that it is done when the values from the HeaderMap are normalized.
585        assert_eq!(val, r#" "london",   "berlin" "#);
586
587        let ser = params![req].into_serializer().unwrap();
588        let val = ser.serialize(list.clone()).unwrap();
589        let Value::String(val) = val else {
590            panic!("Expected String, but got {:?}", val);
591        };
592
593        assert_eq!(val, r#" "london",   "berlin" "#);
594    }
595}