osiris_typed/types/
value.rs

1use osiris_data::data::atomic::Word;
2use osiris_data::data::composite::Array;
3use osiris_data::data::identification::Address;
4
5use crate::parser::Parse;
6use crate::types::DataType;
7use crate::types::numeral::{Number, Numeral, Size};
8use crate::types::pointers::{Range, Reference};
9
10
11#[derive(Clone, Debug, Default, PartialEq)]
12pub enum Value {
13    #[default]
14    None,
15    Reference(Reference),
16    Boolean(bool),
17    Range(Range),
18    Numeral(Numeral),
19    String(String),
20}
21
22pub type ArrayToValueParser = Parse<Array, Value>;
23
24fn array_to_string(array: &Array) -> String {
25    let mut string = String::new();
26    for element in array.as_slice() {
27        string.push_str(element.to_u64().to_string().as_str());
28    }
29    string
30}
31
32impl Value {
33    fn next_word(input: &Array) -> (Array, Option<Word>) {
34        match input.next(&mut Address::new(0)) {
35            None => (input.clone(), None),
36            Some(w) => (input.sub_from_end(Address::new(1)), Some(w))
37        }
38    }
39
40    pub fn parse_to_none(input: &Array) -> (Array, Value) { (input.clone(), Value::None) }
41    pub fn parse_to_reference(input: &Array) -> (Array, Value) {
42        let (output, Some(word)) = Self::next_word(input) else { return (input.clone(), Value::None); };
43        (output, Value::Reference(Reference::new(Address::from_word(word))))
44    }
45    pub fn parse_to_boolean(input: &Array) -> (Array, Value) {
46        let (output, Some(word)) = Self::next_word(input) else { return (input.clone(), Value::None); };
47        (output, Value::Boolean(word.to_u64() != 0))
48    }
49    pub fn parse_to_range(input: &Array) -> (Array, Value) {
50        let (input, Value::Reference(first)) = Self::parse_to_reference(input) else { return (input.clone(), Value::None); };
51        let (input, Value::Reference(second)) = Self::parse_to_reference(&input) else { return (input.clone(), Value::None); };
52        (input.sub_from_end(Address::new(2)), Value::Range(Range { start: first, end: second }))
53    }
54    pub fn parse_to_size(input: &Array) -> (Array, Value) {
55        let (output, Some(size)) = Self::next_word(input) else { return (input.clone(), Value::None); };
56        (output, Value::Numeral(Numeral::Size(Size::from(size))))
57    }
58    pub fn parse_to_float(input: &Array) -> (Array, Value) {
59        let (output, Some(float)) = Self::next_word(input) else { return (input.clone(), Value::None); };
60        (output, Value::Numeral(Numeral::Number(Number::float_from_word(float))))
61    }
62    pub fn parse_to_integer(input: &Array) -> (Array, Value) {
63        let (output, Some(integer)) = Self::next_word(input) else { return (input.clone(), Value::None); };
64        (output, Value::Numeral(Numeral::Number(Number::integer_from_word(integer))))
65    }
66    pub fn parse_to_string(input: &Array) -> (Array, Value) {
67        let str = array_to_string(input);
68        (input.sub_from_end(Address::new(str.bytes().len() as u64)), Value::String(str))
69    }
70}
71
72fn string_to_array(string: &str) -> Array {
73    let mut array = Array::new(0);
74    array.push(Word::from_usize(string.len()));
75    let mut buffer = [u8::default(); 8];
76    let mut buffer_length: usize = 0;
77    for byte in string.bytes() {
78        buffer[buffer_length] = byte;
79        buffer_length += 1;
80        if buffer_length == 8 {
81            array.push(Word::from_be_bytes(buffer));
82            buffer_length = 0;
83        }
84    }
85    if buffer_length != 0 {
86        array.push(Word::from_be_bytes(buffer));
87    }
88    array
89}
90
91impl DataType for Value {
92    fn typename(&self) -> String {
93        match self {
94            Value::None => "None".to_string(),
95            Value::Reference(r) => r.typename(),
96            Value::Range(r) => r.typename(),
97            Value::Numeral(n) => n.typename(),
98            Value::Boolean(_) => "Boolean".to_string(),
99            Value::String(_) => "String".to_string(),
100        }
101    }
102
103    fn to_array(&self) -> Array {
104        match self {
105            Value::None => Array::new(0),
106            Value::Reference(r) => r.to_array(),
107            Value::Range(r) => r.to_array(),
108            Value::Numeral(s) => s.to_array(),
109            Value::Boolean(b) => if *b { Array::from(&[Word::new(-1i64 as u64)]) } else { Array::from(&[Word::new(0)]) },
110            Value::String(s) => string_to_array(s),
111        }
112    }
113
114    fn size(&self) -> usize {
115        match self {
116            Value::None => 0,
117            Value::Reference(_) => 1,
118            Value::Boolean(_) => 1,
119            Value::Numeral(_) => 1,
120            Value::Range(_) => 2,
121            Value::String(s) => s.len(),
122        }
123    }
124}