orientdb_client/common/protocol/v37/
deserializer.rs

1use super::super::parser::{
2    parse_bool, parse_optimized_identity, parse_string_varint, parse_varint,
3};
4
5use super::Protocol37;
6use crate::common::protocol::constants;
7use crate::common::protocol::deserializer::DocumentDeserializer;
8use crate::common::types::bag::RidBag;
9use crate::common::types::document::ODocument;
10use crate::common::types::projection::Projection;
11use crate::common::types::value::OValue;
12
13use crate::{OrientError, OrientResult};
14
15use chrono::TimeZone;
16use chrono::Utc;
17use nom::IResult;
18
19use nom::number::streaming::{be_f32, be_f64, be_i64, be_i8, be_u8};
20use nom::{cond, do_parse, many_m_n, named, try_parse};
21use std::collections::HashMap;
22
23impl DocumentDeserializer for Protocol37 {
24    fn decode_document(input: &[u8]) -> OrientResult<ODocument> {
25        let (rm, doc) = parse_document(input)
26            .map_err(|e| OrientError::Decoder(format!("Error decoding document: {:?}", e)))?;
27        assert_eq!(rm.len(), 0);
28        Ok(doc)
29    }
30    fn decode_projection(input: &[u8]) -> OrientResult<Projection> {
31        let (rm, projection) = parse_projection(input)
32            .map_err(|e| OrientError::Decoder(format!("Error decoding projection: {:?}", e)))?;
33
34        assert_eq!(rm.len(), 0);
35        Ok(projection)
36    }
37}
38
39fn parse_document(input: &[u8]) -> IResult<&[u8], ODocument> {
40    let (remaining, class_name) = try_parse!(input, parse_string_varint);
41    let mut doc = ODocument::new(class_name);
42    let (mut remaining, fields) = try_parse!(remaining, parse_varint);
43    for _ in 0..fields {
44        let (rm, (field, value)) = parse_field(remaining, &|e| {
45            let (remaining, value) = try_parse!(e, parse_document);
46            Ok((remaining, OValue::Document(value)))
47        })?;
48        doc.set_raw(field, value);
49        remaining = rm;
50    }
51    Ok((remaining, doc))
52}
53
54fn parse_projection(input: &[u8]) -> IResult<&[u8], Projection> {
55    let (mut remaining, fields) = try_parse!(input, parse_varint);
56
57    let mut projection = Projection::default();
58    for _ in 0..fields {
59        let (rm, (field, value)) = parse_field(remaining, &|e| {
60            let (remaining, value) = try_parse!(e, parse_projection);
61            Ok((remaining, OValue::EmbeddedMap(value.take_map())))
62        })?;
63        projection.insert(field, value);
64        remaining = rm;
65    }
66    let (mut remaining, m_fields) = try_parse!(remaining, parse_varint);
67
68    // metadata
69    for _ in 0..m_fields {
70        let (rm, (_field, _value)) = parse_field(remaining, &|e| {
71            let (remaining, value) = try_parse!(e, parse_projection);
72            Ok((remaining, OValue::EmbeddedMap(value.take_map())))
73        })?;
74        remaining = rm;
75    }
76
77    Ok((remaining, projection))
78}
79
80fn parse_value<'a, F>(remaining: &'a [u8], embedded: &F) -> IResult<&'a [u8], OValue>
81where
82    F: Fn(&[u8]) -> IResult<&[u8], OValue>,
83{
84    let (remaining, f_type) = try_parse!(remaining, be_i8);
85    let (remaining, value) = match f_type {
86        constants::BYTE => {
87            let (remaining, value) = try_parse!(remaining, be_i8);
88            (remaining, OValue::I8(value))
89        }
90        constants::BOOLEAN => {
91            let (remaining, value) = try_parse!(remaining, parse_bool);
92            (remaining, OValue::Boolean(value))
93        }
94        constants::LONG => {
95            let (remaining, value) = try_parse!(remaining, parse_varint);
96            (remaining, OValue::I64(value))
97        }
98        constants::INTEGER => {
99            let (remaining, value) = try_parse!(remaining, parse_varint);
100            (remaining, OValue::I32(value as i32))
101        }
102        constants::SHORT => {
103            let (remaining, value) = try_parse!(remaining, parse_varint);
104            (remaining, OValue::I16(value as i16))
105        }
106        constants::FLOAT => {
107            let (remaining, value) = try_parse!(remaining, be_f32);
108            (remaining, OValue::F32(value))
109        }
110        constants::DOUBLE => {
111            let (remaining, value) = try_parse!(remaining, be_f64);
112            (remaining, OValue::F64(value))
113        }
114        constants::STRING => {
115            let (remaining, value) = try_parse!(remaining, parse_string_varint);
116            (remaining, OValue::String(value))
117        }
118        constants::LINK => {
119            let (remaining, value) = try_parse!(remaining, parse_optimized_identity);
120            (remaining, OValue::Link(value))
121        }
122        constants::EMBEDDED => embedded(remaining)?,
123        constants::LINKLIST | constants::LINKSET => {
124            let (mut remaining, size) = try_parse!(remaining, parse_varint);
125            let mut links = Vec::new();
126            for _ in 0..size {
127                let (rm, rid) = try_parse!(remaining, parse_optimized_identity);
128                remaining = rm;
129                links.push(rid);
130            }
131            (remaining, OValue::LinkList(links.into()))
132        }
133        constants::EMBEDDEDLIST | constants::EMBEDDEDSET => {
134            let (mut remaining, size) = try_parse!(remaining, parse_varint);
135            let mut elements = Vec::new();
136            for _ in 0..size {
137                let (rm, elem) = parse_value(remaining, embedded)?;
138                remaining = rm;
139                elements.push(elem)
140            }
141            (remaining, OValue::EmbeddedList(elements))
142        }
143        constants::EMBEDDEDMAP => {
144            let (mut remaining, size) = try_parse!(remaining, parse_varint);
145            let mut elements = HashMap::new();
146            for _ in 0..size {
147                let (rm, (k, v)) = parse_field(remaining, embedded)?;
148                remaining = rm;
149                elements.insert(k, v);
150            }
151            (remaining, OValue::EmbeddedMap(elements))
152        }
153        constants::DATE => {
154            let (remaining, timestamp) = try_parse!(remaining, parse_varint);
155            (
156                remaining,
157                OValue::Date(Utc.timestamp(timestamp * 86400, 0).date()),
158            )
159        }
160        constants::DATETIME => {
161            let (remaining, timestamp) = try_parse!(remaining, parse_varint);
162            (
163                remaining,
164                OValue::DateTime(
165                    Utc.timestamp(timestamp / 1000, (timestamp % 1000) as u32 * 1_000_000),
166                ),
167            )
168        }
169        constants::LINKBAG => {
170            // just read for now and skip it
171            let (remaining, (embedded, tree)) = try_parse!(remaining, parse_bags);
172            let bag = embedded.unwrap_or_else(|| tree.expect("Cannot find tree or embedded bags"));
173            (remaining, OValue::RidBag(bag))
174        }
175        constants::NULL => (remaining, OValue::Null),
176        _ => panic!("Unsupported field type {}", f_type),
177    };
178
179    Ok((remaining, value))
180}
181
182fn parse_field<'a, F>(remaining: &'a [u8], embedded: &F) -> IResult<&'a [u8], (String, OValue)>
183where
184    F: Fn(&[u8]) -> IResult<&[u8], OValue>,
185{
186    let (remaining, name) = try_parse!(remaining, parse_string_varint);
187    let (remaining, value) = parse_value(remaining, embedded)?;
188    Ok((remaining, (name, value)))
189}
190
191// fn parse_field(remaining: &[u8]) -> IResult<&[u8], (String, OValue)> {
192//     let (remaining, name) = try_parse!(remaining, parse_string_varint);
193//     let (remaining, value) = try_parse!(remaining, parse_value);
194//     Ok((remaining, (name, value)))
195// }
196
197named!(pub parse_bags<&[u8],(Option<RidBag>,Option<RidBag>)>,
198    do_parse!(
199        _uuid1 : be_i64 >>
200        _uuid2 : be_i64 >>
201        bag_type : be_u8 >>
202        embedded : cond!(bag_type == 1,parse_bags_embedded ) >>
203        tree : cond!(bag_type == 2,parse_bags_tree ) >>
204        (embedded,tree)
205    )
206);
207
208named!(pub parse_bags_embedded<&[u8],RidBag>,
209    do_parse!(
210        size : parse_varint >>
211        bags : many_m_n!(0 as usize ,size as usize,parse_optimized_identity) >>
212        (RidBag::Embedded(bags))
213    )
214);
215
216// // TODO read changes
217named!(pub parse_bags_tree<&[u8],RidBag>,
218    do_parse!(
219        _file_id : parse_varint >>
220        _page_index : parse_varint >>
221        _page_offset : parse_varint >>
222        bag_size : parse_varint >>
223        _changes_size : parse_varint >>
224        (RidBag::Tree(bag_size as i32))
225    )
226);