1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::io::{Read, Seek};

use crate::error::TychoResult;
use crate::partial::reader::PartialReader;
use crate::partial::types::{PartialStruct, PartialList, PartialMap, PartialArray, PartialCompression};
use crate::read::element::read_element_ident;
use crate::read::length::read_length;
use crate::read::string::read_tstring;
use crate::read::value::{read_value, read_value_ident};
use crate::types::ident::{ElementIdent, ValueIdent};
use crate::Value;

#[derive(Debug, Clone)]
/// A partial, unread, element with a pointer.
pub enum PartialElement {
    Unit,
    Value(Value),
    Option(Option<Box<PartialElement>>),
    Variant(String, Box<PartialElement>),
    Struct(PartialStruct),
    List(PartialList),
    Map(PartialMap),
    Array(PartialArray),
    Compression(PartialCompression),
}

pub fn read_partial_element<R: Read + Seek>(reader: &mut PartialReader<R>) -> TychoResult<PartialElement> {
    let ident = read_element_ident(reader)?;

    match ident {
        ElementIdent::Unit => Ok(PartialElement::Unit),
        ElementIdent::Value => {
            let prefix = read_value_ident(reader)?;
            let value = read_value(reader, &prefix)?;
            Ok(PartialElement::Value(value))
        },

        ElementIdent::None => Ok(PartialElement::Option(None)),
        ElementIdent::Some => read_partial_element(reader),

        ElementIdent::Variant => {
            let name = read_tstring(reader)?;
            let value =read_partial_element(reader)?;

            Ok(PartialElement::Variant(name, Box::new(value)))
        }

        ElementIdent::Struct => {
            let size = read_length(reader)? as u64;
            let pos = reader.pointer.clone();
            reader.jump(&size)?;
            Ok(PartialElement::Struct(PartialStruct::new(reader.pointer(pos, size), 0, ())))
        },

        ElementIdent::List => {
            let size = read_length(reader)? as u64;
            let pos = reader.pointer.clone();
            reader.jump(&size)?;
            Ok(PartialElement::List(PartialList::new(reader.pointer(pos, size), 0, ())))
        },

        ElementIdent::Array => {
            let array_type = read_value_ident(reader)?;

            if array_type == ValueIdent::Null {
                return Ok(PartialElement::Array(PartialArray::empty(reader.empty_pointer(),array_type)))
            }

            let size = read_length(reader)? as u64;
            let pos = reader.pointer.clone();
            reader.jump(&size)?;
            Ok(PartialElement::Array(PartialArray::new(reader.pointer(pos, size), 0, array_type)))
        },

        ElementIdent::Map => {
            let key_type = read_value_ident(reader)?;

            if key_type == ValueIdent::Null {
                return Ok(PartialElement::Map(PartialMap::empty(reader.empty_pointer(), key_type)))
            }

            let size = read_length(reader)? as u64;
            let pos = reader.pointer.clone();
            reader.jump(&size)?;
            Ok(PartialElement::Map(PartialMap::new(reader.pointer(pos, size), 0, key_type)))
        },

        ElementIdent::Compression => {
            let size = read_length(reader)? as u64;
            let pos = reader.pointer.clone();
            reader.jump(&size)?;
            Ok(PartialElement::Compression(PartialCompression::new(reader.pointer(pos, size))))
        }
    }
}