compris/hints/
conversion.rs1use super::{
2 super::{annotate::*, normal::*, parse::*},
3 hints::*,
4};
5
6use kutil::std::immutable::*;
7
8impl<AnnotatedT> Variant<AnnotatedT> {
9 pub fn to_hinted_variant(&self, hints: &Hints) -> Result<Option<Variant<AnnotatedT>>, ParseError>
13 where
14 AnnotatedT: Annotated + Clone + Default,
15 {
16 if let Some((key, value)) = self.to_key_value_pair()
17 && let Variant::Text(hint) = key
18 {
19 if hint.inner == hints.integer {
20 let text = value.validate_hinted_text(&hints.integer)?;
21 let integer: i64 = text.inner.parse()?;
22 tracing::trace!("hinted {}: {}", hints.integer, integer);
23 return Ok(Some(Integer::from(integer).with_annotations_from(text).into()));
24 } else if hint.inner == hints.unsigned_integer {
25 let text = value.validate_hinted_text(&hints.unsigned_integer)?;
26 let unsigned_integer: u64 = text.inner.parse()?;
27 tracing::trace!("hinted {}: {}", hints.unsigned_integer, unsigned_integer);
28 return Ok(Some(UnsignedInteger::from(unsigned_integer).with_annotations_from(text).into()));
29 } else if hint.inner == hints.bytes {
30 let text = value.validate_hinted_text(&hints.bytes)?;
31 let blob = Blob::new_from_base64(&text.inner)?;
32 tracing::trace!("hinted {}: {} bytes", hints.bytes, blob.inner.len());
33 return Ok(Some(blob.with_annotations_from(text).into()));
34 } else if hint.inner == hints.map {
35 let list = value.validate_hinted_list(&hints.map)?;
36 let mut new_map = Map::default();
37
38 for item in list {
39 let entry = item.validate_hinted_list(&hints.map)?;
40 if let Some((key, value)) = entry.to_pair() {
41 let key = if let Some(hinted) = key.to_hinted_variant(hints)? { hinted } else { key.clone() };
42
43 let value =
44 if let Some(hinted) = value.to_hinted_variant(hints)? { hinted } else { value.clone() };
45
46 new_map.inner.insert(key, value);
47
48 } else {
53 return Err(ParseError::Hint(format!("malformed {:?}, item length is not 2", hints.map)));
54 }
55 }
56
57 tracing::trace!("hinted {}: {}", hints.map, new_map.inner.len());
58 return Ok(Some(new_map.with_annotations_from(list).into()));
59 } else if hint.inner == hints.escaped_integer {
60 tracing::trace!("escaped hint: {}", hints.integer);
61 return Ok(Some(self.unescape_hint(&hints.integer, key, value)));
62 } else if hint.inner == hints.escaped_unsigned_integer {
63 tracing::trace!("escaped hint: {}", hints.unsigned_integer);
64 return Ok(Some(self.unescape_hint(&hints.unsigned_integer, key, value)));
65 } else if hint.inner == hints.escaped_bytes {
66 tracing::trace!("escaped hint: {}", hints.bytes);
67 return Ok(Some(self.unescape_hint(&hints.bytes, key, value)));
68 } else if hint.inner == hints.escaped_map {
69 tracing::trace!("escaped hint: {}", hints.map);
70 return Ok(Some(self.unescape_hint(&hints.map, key, value)));
71 }
72 }
73
74 Ok(None)
75 }
76
77 fn validate_hinted_text(&self, hint: &str) -> Result<&Text<AnnotatedT>, ParseError> {
78 match self {
79 Variant::Text(text) => Ok(text),
80 _ => Err(ParseError::Hint(format!("malformed {:?}, not text", hint))),
81 }
82 }
83
84 fn validate_hinted_list(&self, hint: &str) -> Result<&List<AnnotatedT>, ParseError> {
85 match self {
86 Variant::List(list) => Ok(list),
87 _ => Err(ParseError::Hint(format!("malformed {:?}, not a list", hint))),
88 }
89 }
90
91 fn unescape_hint(&self, new_key: &str, key: &Variant<AnnotatedT>, variant: &Variant<AnnotatedT>) -> Self
92 where
93 AnnotatedT: Annotated + Clone + Default,
94 {
95 let mut new_map = Map::default();
96 new_map.inner.insert(Variant::from(ByteString::from(new_key)).with_annotations_from(key), variant.clone());
97 new_map.with_annotations_from(self).into()
98 }
99}