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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use alloc::boxed::Box;
use alloc::vec::Vec;
use crate::pointer::NP_Value;
use crate::error::NP_Error;
use crate::pointer::{any::NP_Any, NP_Ptr, DeepType};
use crate::memory::NP_Memory;
use crate::{NP_Factory, schema::{NP_TypeKeys, NP_Schema}};
use alloc::{borrow::ToOwned, rc::Rc};
pub struct NP_Buffer {
pub memory: Rc<NP_Memory>,
schema: Rc<NP_Schema>
}
pub struct NP_Compact_Data {
pub old_buffer_size: u32,
pub new_buffer_size: u32,
pub wasted_bytes: u32
}
impl NP_Buffer {
pub fn new(model: Rc<NP_Schema>, memory: Rc<NP_Memory>) -> Self {
NP_Buffer {
memory: memory,
schema: model
}
}
pub fn root<T: NP_Value + Default>(&mut self) -> Result<NP_Ptr<T>, NP_Error> {
let buffer = NP_Ptr::new_standard_ptr(1, Rc::clone(&self.schema), Rc::clone(&self.memory));
if T::type_idx().0 == NP_TypeKeys::Any as i64 || buffer.schema.type_data.0 == NP_TypeKeys::Any as i64 {
return Ok(buffer);
}
if T::type_idx().0 == buffer.schema.type_data.0 {
return Ok(buffer);
}
let mut err = "TypeError: Attempted to cast type (".to_owned();
err.push_str(T::type_idx().1.as_str());
err.push_str(") to schema of type (");
err.push_str(buffer.schema.type_data.1.as_str());
err.push_str(")");
Err(NP_Error::new(err))
}
pub fn deep_set<X: NP_Value + Default>(&mut self, path: &str, value: X) -> Result<(), NP_Error> {
let vec_path: Vec<&str> = path.split(".").filter(|v| { v.len() > 0 }).collect();
let pointer: NP_Ptr<NP_Any> = NP_Ptr::new_standard_ptr(1, Rc::clone(&self.schema), Rc::clone(&self.memory));
pointer._deep_set::<X>(DeepType::All, vec_path, 0, value)
}
pub fn deep_clear(&self, path: &str) -> Result<(), NP_Error> {
let vec_path: Vec<&str> = path.split(".").filter(|v| { v.len() > 0 }).collect();
let pointer: NP_Ptr<NP_Any> = NP_Ptr::new_standard_ptr(1, Rc::clone(&self.schema), Rc::clone(&self.memory));
pointer._deep_clear(vec_path, 0)
}
pub fn deep_get<X: NP_Value + Default>(&self, path: &str) -> Result<Option<Box<X>>, NP_Error> {
let vec_path: Vec<&str> = path.split(".").filter(|v| { v.len() > 0 }).collect();
let pointer: NP_Ptr<NP_Any> = NP_Ptr::new_standard_ptr(1, Rc::clone(&self.schema), Rc::clone(&self.memory));
pointer._deep_get::<X>(DeepType::All, vec_path, 0)
}
#[doc(hidden)]
pub fn _deep_set_scalar<X: NP_Value + Default>(&mut self, path: &str, value: X) -> Result<(), NP_Error> {
let vec_path: Vec<&str> = path.split(".").filter(|v| { v.len() > 0 }).collect();
let pointer: NP_Ptr<NP_Any> = NP_Ptr::new_standard_ptr(1, Rc::clone(&self.schema), Rc::clone(&self.memory));
pointer._deep_set::<X>(DeepType::Scalar, vec_path, 0, value)
}
#[doc(hidden)]
pub fn _deep_get_scalar<X: NP_Value + Default>(&self, path: &str) -> Result<Option<Box<X>>, NP_Error> {
let vec_path: Vec<&str> = path.split(".").filter(|v| { v.len() > 0 }).collect();
let pointer: NP_Ptr<NP_Any> = NP_Ptr::new_standard_ptr(1, Rc::clone(&self.schema), Rc::clone(&self.memory));
pointer._deep_get::<X>(DeepType::Scalar, vec_path, 0)
}
pub fn maybe_compact<F>(self, new_capacity: Option<u32>, mut callback: F) -> Result<NP_Buffer, NP_Error> where F: FnMut(NP_Compact_Data) -> bool {
let wasted_bytes = self.calc_wasted_bytes()?;
let old_size = self.memory.read_bytes().len() as u32;
let compact_data = NP_Compact_Data {
old_buffer_size: old_size,
new_buffer_size: if old_size > wasted_bytes { old_size - wasted_bytes } else { 0 },
wasted_bytes: wasted_bytes
};
let do_compact = callback(compact_data);
Ok(if do_compact {
self.compact(new_capacity)?
} else {
self
})
}
pub fn compact(self, new_capacity: Option<u32>) -> Result<NP_Buffer, NP_Error> {
let capacity = match new_capacity {
Some(x) => { x as usize },
None => self.memory.read_bytes().len()
};
let old_root = NP_Ptr::<NP_Any>::new_standard_ptr(1, Rc::clone(&self.schema), self.memory);
let new_bytes = Rc::new(NP_Memory::new(NP_Factory::new_buffer(Some(capacity))));
let new_root = NP_Ptr::<NP_Any>::new_standard_ptr(1, Rc::clone(&self.schema), Rc::clone(&new_bytes));
old_root._compact(new_root)?;
Ok(NP_Buffer {
memory: new_bytes,
schema: self.schema
})
}
pub fn calc_wasted_bytes(&self) -> Result<u32, NP_Error> {
let root: NP_Ptr<NP_Any> = NP_Ptr::new_standard_ptr(1, Rc::clone(&self.schema), Rc::clone(&self.memory));
let real_bytes = root.calc_size()? + 1u32;
let total_bytes = self.memory.read_bytes().len() as u32;
if total_bytes >= real_bytes {
return Ok(total_bytes - real_bytes);
} else {
return Err(NP_Error::new("Error calclating bytes!"));
}
}
}