orientdb_client/common/protocol/v37/
serializer.rs

1use super::super::buffer::OBuffer;
2use super::Protocol37;
3use crate::common::protocol::serializer::DocumentSerializer;
4use crate::common::types::document::ODocument;
5use crate::common::types::value::OValue;
6use crate::common::OrientResult;
7
8impl DocumentSerializer for Protocol37 {
9    fn encode_document(doc: &ODocument) -> OrientResult<OBuffer> {
10        let mut doc_buf = OBuffer::new();
11        encode_document(doc, &mut doc_buf)?;
12        Ok(doc_buf)
13    }
14}
15
16fn encode_document(doc: &ODocument, buf: &mut OBuffer) -> OrientResult<()> {
17    buf.write_string(doc.class_name())?;
18    buf.write_varint(doc.len() as i64)?;
19
20    for (k, v) in doc.iter() {
21        write_field(buf, k, v)?;
22    }
23    Ok(())
24}
25fn write_field<'a>(buf: &mut OBuffer, name: &'a str, value: &'a OValue) -> OrientResult<()> {
26    buf.write_string(name)?;
27
28    buf.put_i8(value.get_type_id())?;
29
30    write_value(buf, name, value)?;
31
32    Ok(())
33}
34
35fn write_value<'a>(buf: &mut OBuffer, owner: &'a str, value: &'a OValue) -> OrientResult<()> {
36    match value {
37        OValue::String(ref s) => buf.write_string(s),
38        OValue::Boolean(v) => {
39            buf.write_bool(*v)?;
40            Ok(())
41        }
42        OValue::I16(v) => buf.write_varint(i64::from(*v)),
43        OValue::I32(v) => buf.write_varint(i64::from(*v)),
44        OValue::I64(v) => buf.write_varint(*v),
45        OValue::Link(ref v) => {
46            buf.write_varint(i64::from(v.cluster))?;
47            buf.write_varint(v.position)?;
48            Ok(())
49        }
50        OValue::EmbeddedList(ref v) => {
51            buf.write_varint(v.len() as i64)?;
52
53            for (idx, elem) in v.iter().enumerate() {
54                buf.put_i8(elem.get_type_id())?;
55                write_value(buf, &format!("{}_{}", owner, idx), elem)?;
56            }
57
58            Ok(())
59        }
60        OValue::Document(ref doc) => {
61            encode_document(doc, buf)?;
62            Ok(())
63        }
64
65        OValue::LinkList(ref list) => {
66            buf.write_varint(list.links.len() as i64)?;
67
68            for link in list.links.iter() {
69                buf.write_varint(i64::from(link.cluster))?;
70                buf.write_varint(link.position)?;
71            }
72            Ok(())
73        }
74        OValue::EmbeddedMap(ref map) => {
75            buf.write_varint(map.len() as i64)?;
76            for (k, v) in map {
77                write_field(buf, k, v)?;
78            }
79            Ok(())
80        }
81        #[cfg(feature = "uuid")]
82        OValue::Uuid(ref uuid) => {
83            buf.write_string(&uuid.to_string())?;
84            Ok(())
85        }
86        _ => panic!("Field {} not supported", owner),
87    }?;
88    Ok(())
89}
90
91#[cfg(test)]
92mod tests {
93
94    use super::Protocol37;
95    use crate::common::protocol::deserializer::DocumentDeserializer;
96    use crate::common::protocol::serializer::DocumentSerializer;
97    use crate::common::types::document::ODocument;
98    use crate::common::types::rid::ORecordID;
99    use crate::common::types::value::{IntoOValue, LinkList, OValue};
100    use std::collections::HashMap;
101
102    #[test]
103    fn doc_ser_test() {
104        let mut doc = ODocument::new("Test");
105
106        // Simple field
107        doc.set("age", 20 as i16);
108        doc.set("year", 1983);
109        doc.set("balance", 10000 as i64);
110        doc.set("confirmed", true);
111        doc.set("name", String::from("John"));
112
113        // Complex Field
114        doc.set("city", ORecordID::new(10, 0));
115
116        let map: HashMap<String, i32> = [("Norway", 100), ("Denmark", 50), ("Iceland", 10)]
117            .iter()
118            .map(|e| (String::from(e.0), e.1))
119            .collect();
120
121        let test_map = map.clone();
122
123        doc.set("tags", vec!["name", "happy", "friends"]);
124        doc.set("map", map);
125
126        let mut doc_embedded = ODocument::new("EmbeddedClass");
127        doc_embedded.set("name", "Foo");
128
129        let doc_embedded_cloned = doc_embedded.clone();
130
131        doc.set("embedded", doc_embedded);
132
133        let links: LinkList = vec![ORecordID::new(10, 10)].into();
134        doc.set("links", links);
135
136        let encoded = Protocol37::encode_document(&doc).unwrap();
137        let doc = Protocol37::decode_document(encoded.as_slice()).unwrap();
138
139        assert_eq!("Test", doc.class_name());
140        assert_eq!(Some(&OValue::I16(20)), doc.get_raw("age"));
141        assert_eq!(Some(&OValue::I32(1983)), doc.get_raw("year"));
142        assert_eq!(Some(&OValue::I64(10000)), doc.get_raw("balance"));
143        assert_eq!(Some(&OValue::Boolean(true)), doc.get_raw("confirmed"));
144        assert_eq!(
145            Some(&OValue::String(String::from("John"))),
146            doc.get_raw("name")
147        );
148
149        assert_eq!(
150            Some(&OValue::Link(ORecordID::new(10, 0))),
151            doc.get_raw("city")
152        );
153
154        let tags = OValue::EmbeddedList(vec![
155            OValue::String(String::from("name")),
156            OValue::String(String::from("happy")),
157            OValue::String(String::from("friends")),
158        ]);
159        assert_eq!(Some(&tags), doc.get_raw("tags"));
160
161        let embedded = OValue::EmbeddedMap(
162            test_map
163                .iter()
164                .map(|(k, v)| (k.clone(), v.into_ovalue()))
165                .collect(),
166        );
167
168        assert_eq!(Some(&embedded), doc.get_raw("map"));
169
170        assert_eq!(
171            Some(&OValue::Document(doc_embedded_cloned)),
172            doc.get_raw("embedded")
173        );
174
175        assert_eq!(
176            Some(&OValue::LinkList(vec![ORecordID::new(10, 10)].into())),
177            doc.get_raw("links")
178        );
179    }
180}