y_octo/doc/types/
value.rs

1use std::fmt::Display;
2
3use super::*;
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum Value {
7    Any(Any),
8    Doc(Doc),
9    Array(Array),
10    Map(Map),
11    Text(Text),
12    XMLElement(XMLElement),
13    XMLFragment(XMLFragment),
14    XMLHook(XMLHook),
15    XMLText(XMLText),
16}
17
18impl Value {
19    pub fn to_any(&self) -> Option<Any> {
20        match self {
21            Value::Any(any) => Some(any.clone()),
22            _ => None,
23        }
24    }
25
26    pub fn to_array(&self) -> Option<Array> {
27        match self {
28            Value::Array(array) => Some(array.clone()),
29            _ => None,
30        }
31    }
32
33    pub fn to_map(&self) -> Option<Map> {
34        match self {
35            Value::Map(map) => Some(map.clone()),
36            _ => None,
37        }
38    }
39
40    pub fn to_text(&self) -> Option<Text> {
41        match self {
42            Value::Text(text) => Some(text.clone()),
43            _ => None,
44        }
45    }
46
47    pub fn from_vec<T: Into<Any>>(el: Vec<T>) -> Self {
48        Value::Any(Any::Array(el.into_iter().map(|item| item.into()).collect::<Vec<_>>()))
49    }
50}
51
52impl From<&Content> for Value {
53    fn from(value: &Content) -> Value {
54        match value {
55            Content::Any(any) => Value::Any(if any.len() == 1 {
56                any[0].clone()
57            } else {
58                Any::Array(any.clone())
59            }),
60            Content::String(s) => Value::Any(Any::String(s.clone())),
61            Content::Json(json) => Value::Any(Any::Array(
62                json.iter()
63                    .map(|item| {
64                        if let Some(s) = item {
65                            Any::String(s.clone())
66                        } else {
67                            Any::Undefined
68                        }
69                    })
70                    .collect::<Vec<_>>(),
71            )),
72            Content::Binary(buf) => Value::Any(Any::Binary(buf.clone())),
73            Content::Embed(v) => Value::Any(v.clone()),
74            Content::Type(ty) => match ty.ty().unwrap().kind {
75                YTypeKind::Array => Value::Array(Array::from_unchecked(ty.clone())),
76                YTypeKind::Map => Value::Map(Map::from_unchecked(ty.clone())),
77                YTypeKind::Text => Value::Text(Text::from_unchecked(ty.clone())),
78                YTypeKind::XMLElement => Value::XMLElement(XMLElement::from_unchecked(ty.clone())),
79                YTypeKind::XMLFragment => Value::XMLFragment(XMLFragment::from_unchecked(ty.clone())),
80                YTypeKind::XMLHook => Value::XMLHook(XMLHook::from_unchecked(ty.clone())),
81                YTypeKind::XMLText => Value::XMLText(XMLText::from_unchecked(ty.clone())),
82                // actually unreachable
83                YTypeKind::Unknown => Value::Any(Any::Undefined),
84            },
85            Content::Doc { guid: _, opts } => Value::Doc(
86                DocOptions::try_from(opts.clone())
87                    .expect("Failed to parse doc options")
88                    .build(),
89            ),
90            Content::Format { .. } => unimplemented!(),
91            // actually unreachable
92            Content::Deleted(_) => Value::Any(Any::Undefined),
93        }
94    }
95}
96
97impl From<Value> for Content {
98    fn from(value: Value) -> Self {
99        match value {
100            Value::Any(any) => Content::from(any),
101            Value::Doc(doc) => Content::Doc {
102                guid: doc.guid().to_owned(),
103                opts: Any::from(doc.options().clone()),
104            },
105            Value::Array(v) => Content::Type(v.0),
106            Value::Map(v) => Content::Type(v.0),
107            Value::Text(v) => Content::Type(v.0),
108            Value::XMLElement(v) => Content::Type(v.0),
109            Value::XMLFragment(v) => Content::Type(v.0),
110            Value::XMLHook(v) => Content::Type(v.0),
111            Value::XMLText(v) => Content::Type(v.0),
112        }
113    }
114}
115
116impl<T: Into<Any>> From<T> for Value {
117    fn from(value: T) -> Self {
118        Value::Any(value.into())
119    }
120}
121
122impl From<Doc> for Value {
123    fn from(value: Doc) -> Self {
124        Value::Doc(value)
125    }
126}
127
128impl Display for Value {
129    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130        match self {
131            Value::Any(any) => write!(f, "{}", any),
132            Value::Text(text) => write!(f, "{}", text),
133            _ => write!(f, ""),
134        }
135    }
136}
137
138impl serde::Serialize for Value {
139    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
140    where
141        S: serde::Serializer,
142    {
143        match self {
144            Self::Any(any) => any.serialize(serializer),
145            Self::Array(array) => array.serialize(serializer),
146            Self::Map(map) => map.serialize(serializer),
147            Self::Text(text) => text.serialize(serializer),
148            // Self::XMLElement(xml_element) => xml_element.serialize(serializer),
149            // Self::XMLFragment(xml_fragment) => xml_fragment.serialize(serializer),
150            // Self::XMLHook(xml_hook) => xml_hook.serialize(serializer),
151            // Self::XMLText(xml_text) => xml_text.serialize(serializer),
152            // Self::Doc(doc) => doc.serialize(serializer),
153            _ => serializer.serialize_none(),
154        }
155    }
156}