1use crate::datagram::datagram::*;
24use crate::datagram::iterator::*;
25use crate::dctype::*;
26use crate::hashgen::*;
27use std::mem::{discriminant, size_of};
28
29#[derive(Clone)]
33pub struct DCNumericRange {
34 pub min: DCNumber,
35 pub max: DCNumber,
36}
37
38impl From<std::ops::Range<i64>> for DCNumericRange {
39 fn from(value: std::ops::Range<i64>) -> Self {
40 Self {
41 min: DCNumber::Integer(value.start),
42 max: DCNumber::Integer(value.end),
43 }
44 }
45}
46
47impl From<std::ops::Range<u64>> for DCNumericRange {
48 fn from(value: std::ops::Range<u64>) -> Self {
49 Self {
50 min: DCNumber::UnsignedInteger(value.start),
51 max: DCNumber::UnsignedInteger(value.end),
52 }
53 }
54}
55
56impl From<std::ops::Range<f64>> for DCNumericRange {
57 fn from(value: std::ops::Range<f64>) -> Self {
58 Self {
59 min: DCNumber::FloatingPoint(value.start),
60 max: DCNumber::FloatingPoint(value.end),
61 }
62 }
63}
64
65impl DCNumericRange {
66 pub fn contains(&self, num: DCNumber) -> bool {
67 if discriminant(&self.min) == discriminant(&num) {
69 return false;
70 }
71
72 match self.min {
73 DCNumber::Integer(min) => {
74 let num = match num {
75 DCNumber::Integer(i) => i,
76 _ => panic!("Check above makes this panic unreachable."),
77 };
78
79 let max = match self.max {
80 DCNumber::Integer(i) => i,
81 _ => panic!("Check above makes this panic unreachable."),
82 };
83
84 min <= num && num <= max
85 }
86 DCNumber::UnsignedInteger(min) => {
87 let num = match num {
88 DCNumber::UnsignedInteger(i) => i,
89 _ => panic!("Check above makes this panic unreachable."),
90 };
91
92 let max = match self.max {
93 DCNumber::UnsignedInteger(i) => i,
94 _ => panic!("Check above makes this panic unreachable."),
95 };
96
97 min <= num && num <= max
98 }
99 DCNumber::FloatingPoint(min) => {
100 let num = match num {
101 DCNumber::FloatingPoint(i) => i,
102 _ => panic!("Check above makes this panic unreachable."),
103 };
104
105 let max = match self.max {
106 DCNumber::FloatingPoint(i) => i,
107 _ => panic!("Check above makes this panic unreachable."),
108 };
109
110 min <= num && num <= max
111 }
112 }
113 }
114}
115
116pub struct DCNumericType {
117 base_type: DCTypeDefinition,
118 divisor: u16,
119 orig_modulus: f64,
121 orig_range: Option<DCNumericRange>,
122 modulus: f64,
124 range: Option<DCNumericRange>,
125 explicit_cast: Option<DCTypeDefinition>,
127}
128
129impl From<DCTypeEnum> for DCNumericType {
130 fn from(value: DCTypeEnum) -> Self {
131 Self {
132 base_type: {
133 let mut parent_struct = DCTypeDefinition::from(value);
134
135 macro_rules! set_parent_size {
136 ($t:ty) => {
137 parent_struct.size = size_of::<$t>().try_into().unwrap()
138 };
139 }
140
141 match parent_struct.data_type {
142 DCTypeEnum::TChar | DCTypeEnum::TInt8 | DCTypeEnum::TUInt8 => {
143 set_parent_size!(u8)
144 }
145 DCTypeEnum::TInt16 | DCTypeEnum::TUInt16 => {
146 set_parent_size!(u16)
147 }
148 DCTypeEnum::TInt32 | DCTypeEnum::TUInt32 => {
149 set_parent_size!(u32)
150 }
151 DCTypeEnum::TInt64 | DCTypeEnum::TUInt64 => {
152 set_parent_size!(u64)
153 }
154 DCTypeEnum::TFloat32 => {
155 set_parent_size!(f32)
156 }
157 DCTypeEnum::TFloat64 => {
158 set_parent_size!(f64)
159 }
160 _ => panic!("Invalid data type!"),
161 }
162 parent_struct
163 },
164 divisor: 1_u16,
165 orig_modulus: 0.0_f64,
166 orig_range: None,
167 modulus: 0.0_f64,
168 range: None,
169 explicit_cast: None,
170 }
171 }
172}
173
174impl LegacyDCHash for DCNumericType {
175 fn generate_hash(&self, hashgen: &mut DCHashGenerator) {
176 self.base_type.generate_hash(hashgen);
177
178 hashgen.add_int(self.divisor.into());
179
180 if self.has_modulus() {
181 hashgen.add_int(self.modulus as i32);
182 }
183 if let Some(range) = &self.range {
184 hashgen.add_int(range.min.into());
185 hashgen.add_int(range.max.into());
186 }
187 }
188}
189
190impl DCNumericType {
191 #[inline]
192 pub fn has_modulus(&self) -> bool {
193 self.orig_modulus != 0.0
194 }
195
196 #[inline]
197 pub fn has_range(&self) -> bool {
198 self.orig_range.is_some()
199 }
200
201 #[inline]
202 pub fn get_divisor(&self) -> u16 {
203 self.divisor
204 }
205
206 #[inline]
207 pub fn get_modulus(&self) -> f64 {
208 self.orig_modulus
209 }
210
211 #[inline]
212 pub fn get_range(&self) -> Option<DCNumericRange> {
213 self.orig_range.clone()
214 }
215
216 #[inline]
217 pub fn get_explicit_cast(&self) -> Option<DCTypeDefinition> {
218 self.explicit_cast.clone()
219 }
220
221 pub fn set_divisor(&mut self, divisor: u16) -> Result<(), String> {
222 if divisor == 0 {
223 return Err("Cannot set the divisor to 0.".into());
224 }
225 self.divisor = divisor;
226
227 if self.has_range() {
228 self.set_range(self.orig_range.clone().unwrap())?;
229 }
230
231 if self.has_modulus() {
232 self.set_modulus(self.orig_modulus)?;
233 }
234 Ok(())
235 }
236
237 pub fn set_modulus(&mut self, modulus: f64) -> Result<(), String> {
238 if modulus <= 0.0_f64 {
239 return Err("Modulus value cannot be less than or equal to 0.0.".into());
240 }
241 self.orig_modulus = modulus;
242 self.modulus = modulus * f64::from(self.divisor);
243
244 Ok(()) }
246
247 pub fn set_range(&mut self, range: DCNumericRange) -> Result<(), String> {
248 self.range = Some(range); Ok(())
250 }
251
252 pub fn set_explicit_cast(&mut self, dtype: DCTypeDefinition) -> Result<(), String> {
253 self.explicit_cast = Some(dtype);
254 Ok(()) }
256
257 pub fn within_range(&self, _data: Vec<u8>, _length: u64) -> Result<(), String> {
258 todo!();
259 }
260
261 fn data_to_number(&self, data: Vec<u8>) -> Result<(bool, DCNumber), IteratorError> {
262 if self.base_type.size != data.len().try_into().unwrap() {
263 return Ok((false, DCNumber::Integer(0_i64)));
264 }
265
266 let mut dg = Datagram::default();
267 dg.add_data(data).expect("Failed to convert data to datagram.");
268
269 let mut dgi: DatagramIterator = dg.into();
270
271 match self.base_type.data_type {
272 DCTypeEnum::TInt8 => Ok((true, DCNumber::Integer(i64::from(dgi.read_i8()?)))),
273 DCTypeEnum::TInt16 => Ok((true, DCNumber::Integer(i64::from(dgi.read_i16()?)))),
274 DCTypeEnum::TInt32 => Ok((true, DCNumber::Integer(i64::from(dgi.read_i32()?)))),
275 DCTypeEnum::TInt64 => Ok((true, DCNumber::Integer(dgi.read_i64()?))),
276 DCTypeEnum::TChar | DCTypeEnum::TUInt8 => {
277 Ok((true, DCNumber::UnsignedInteger(u64::from(dgi.read_u8()?))))
278 }
279 DCTypeEnum::TUInt16 => Ok((true, DCNumber::UnsignedInteger(u64::from(dgi.read_u16()?)))),
280 DCTypeEnum::TUInt32 => Ok((true, DCNumber::UnsignedInteger(u64::from(dgi.read_u32()?)))),
281 DCTypeEnum::TUInt64 => Ok((true, DCNumber::UnsignedInteger(dgi.read_u64()?))),
282 DCTypeEnum::TFloat32 => Ok((true, DCNumber::FloatingPoint(f64::from(dgi.read_f32()?)))),
283 DCTypeEnum::TFloat64 => Ok((true, DCNumber::FloatingPoint(dgi.read_f64()?))),
284 _ => Ok((false, DCNumber::Integer(0_i64))),
285 }
286 }
287}