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 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 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 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 assert_eq!(visible, r#"1"#);
526
527 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 assert_eq!(visible, r#"2;x=1;y=2"#);
536
537 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 assert_eq!(visible, r#"(a b c);valid"#);
546
547 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 assert_eq!(visible, "?1");
556 }
557
558 #[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 assert_eq!(val, ":dmFsdWUsIHdpdGgsIGxvdHMsIG9mLCBjb21tYXM=:");
570 }
571
572 #[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 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}