osiris_typed/types/
value.rs1use 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}