icbiadb/types/bv/
bvobject.rs

1use serde::{Deserialize, Serialize};
2
3use crate::prelude::{BvContains, BvEndsWith, BvStartsWith};
4use crate::utils::{normalize_type_name, serialize_to_bytevec};
5
6use super::{BvString, ByteVec};
7
8/// Wrapper for serialized objects by bincode
9#[derive(Default, Serialize, Deserialize, Clone, Debug)]
10pub struct BvObject {
11    type_name: BvString,
12    raw: ByteVec,
13}
14
15impl BvObject {
16    pub fn from<T: Sized + serde::ser::Serialize>(o: T) -> Self {
17        BvObject {
18            type_name: normalize_type_name(std::any::type_name::<T>().as_bytes()).into(),
19            raw: serialize_to_bytevec(&o),
20        }
21    }
22
23    pub fn from_raw(t: Vec<u8>, v: Vec<u8>) -> Self {
24        BvObject {
25            type_name: t.into(),
26            raw: v.into(),
27        }
28    }
29
30    pub fn from_tuple(t: (&[u8], &[u8])) -> Self {
31        BvObject {
32            type_name: t.0.into(),
33            raw: t.1.into(),
34        }
35    }
36
37    pub fn type_name(&self) -> &BvString {
38        &self.type_name
39    }
40
41    pub fn raw(&self) -> &ByteVec {
42        &self.raw
43    }
44
45    pub fn mut_raw(&mut self) -> &mut ByteVec {
46        &mut self.raw
47    }
48
49    pub fn extract<T: Sized + serde::de::DeserializeOwned>(&self) -> T {
50        self.raw.extract()
51    }
52
53    pub fn is_str(&self) -> bool {
54        self.type_name == "str"
55    }
56
57    pub fn is_int(&self) -> bool {
58        match self.type_name.as_slice() {
59            // i8-i128
60            [105, 56] => true,
61            [105, 49, 54] => true,
62            [105, 51, 50] => true,
63            [105, 54, 52] => true,
64            [105, 49, 50, 56] => true,
65            _ => false,
66        }
67    }
68
69    pub fn is_uint(&self) -> bool {
70        match self.type_name.as_slice() {
71            // u8-u128
72            [117, 56] => true,
73            [117, 49, 54] => true,
74            [117, 51, 50] => true,
75            [117, 54, 52] => true,
76            [117, 49, 50, 56] => true,
77            _ => false,
78        }
79    }
80
81    pub fn is_float(&self) -> bool {
82        match self.type_name.as_slice() {
83            // f32-f64
84            [102, 51, 50] => true,
85            [102, 54, 52] => true,
86            _ => false,
87        }
88    }
89
90    pub fn as_str(&self) -> &str {
91        std::str::from_utf8(&self.raw.as_slice()[8..]).unwrap()
92    }
93
94    pub fn as_slice(&self) -> &[u8] {
95        self.raw.as_slice()
96    }
97
98    pub fn as_str_slice(&self) -> &[u8] {
99        &self.raw.as_slice()[8..]
100    }
101}
102
103impl std::ops::Deref for BvObject {
104    type Target = ByteVec;
105
106    fn deref(&self) -> &Self::Target {
107        &self.raw
108    }
109}
110
111impl std::ops::DerefMut for BvObject {
112    fn deref_mut(&mut self) -> &mut Self::Target {
113        &mut self.raw
114    }
115}
116
117impl std::convert::From<(&[u8], &[u8])> for BvObject {
118    fn from(other: (&[u8], &[u8])) -> Self {
119        BvObject::from_tuple(other)
120    }
121}
122
123impl std::convert::From<&BvObject> for BvObject {
124    fn from(other: &BvObject) -> Self {
125        BvObject {
126            type_name: other.type_name().into(),
127            raw: other.raw().into(),
128        }
129    }
130}
131
132impl BvStartsWith<&String> for BvObject {
133    fn starts_with(&self, other: &String) -> bool {
134        self.is_str() && self.raw.starts_with(other.as_bytes())
135    }
136}
137
138impl BvStartsWith<&[u8]> for BvObject {
139    fn starts_with(&self, other: &[u8]) -> bool {
140        self.is_str() && self.raw.starts_with(other)
141    }
142}
143
144impl BvStartsWith<&str> for BvObject {
145    fn starts_with(&self, other: &str) -> bool {
146        self.is_str() && self.raw.starts_with(other)
147    }
148}
149
150impl BvContains<&String> for BvObject {
151    fn contains(&self, other: &String) -> bool {
152        self.is_str() && self.raw.contains(other.as_bytes())
153    }
154}
155
156impl BvContains<&[u8]> for BvObject {
157    fn contains(&self, other: &[u8]) -> bool {
158        self.is_str() && self.raw.contains(other)
159    }
160}
161
162impl BvContains<&str> for BvObject {
163    fn contains(&self, other: &str) -> bool {
164        self.is_str() && self.raw.contains(other)
165    }
166}
167
168impl BvEndsWith<&String> for BvObject {
169    fn ends_with(&self, other: &String) -> bool {
170        self.is_str() && self.raw.ends_with(other.as_bytes())
171    }
172}
173
174impl BvEndsWith<&[u8]> for BvObject {
175    fn ends_with(&self, other: &[u8]) -> bool {
176        self.is_str() && self.raw.ends_with(other)
177    }
178}
179
180impl BvEndsWith<&str> for BvObject {
181    fn ends_with(&self, other: &str) -> bool {
182        self.is_str() && self.raw.ends_with(other)
183    }
184}
185
186impl std::fmt::Display for BvObject {
187    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
188        write!(
189            f,
190            "BvObject {{ type_name: {}, value: {:?} }}",
191            self.type_name.as_str(),
192            self.raw
193        )
194    }
195}
196
197impl PartialEq<BvObject> for BvObject {
198    fn eq(&self, other: &BvObject) -> bool {
199        self.raw == other.as_slice()
200    }
201}
202
203impl PartialEq<&BvObject> for BvObject {
204    fn eq(&self, other: &&BvObject) -> bool {
205        self.raw == other.as_slice()
206    }
207}
208
209impl PartialEq<bool> for &BvObject {
210    fn eq(&self, other: &bool) -> bool {
211        if *other {
212            self.raw[0] == 1
213        } else {
214            self.raw[0] == 0
215        }
216    }
217}
218
219impl PartialEq<[u8]> for BvObject {
220    fn eq(&self, other: &[u8]) -> bool {
221        if self.is_str() {
222            &self.raw[8..] == other
223        } else {
224            self.raw == other
225        }
226    }
227}
228
229impl PartialEq<str> for BvObject {
230    fn eq(&self, other: &str) -> bool {
231        self.is_str() && &self.raw[8..] == other.as_bytes()
232    }
233}
234
235impl PartialEq<String> for BvObject {
236    fn eq(&self, other: &String) -> bool {
237        self.is_str() && &self.raw[8..] == other.as_bytes()
238    }
239}
240
241impl PartialEq<&String> for BvObject {
242    fn eq(&self, other: &&String) -> bool {
243        self.is_str() && &self.raw[8..] == other.as_bytes()
244    }
245}
246
247impl PartialEq<i16> for BvObject {
248    fn eq(&self, other: &i16) -> bool {
249        self.is_int() && self.raw.as_i16() == *other
250    }
251}
252
253impl PartialOrd<i16> for BvObject {
254    fn partial_cmp(&self, other: &i16) -> Option<std::cmp::Ordering> {
255        if !self.is_int() {
256            return None;
257        }
258
259        Some(self.raw.as_i16().cmp(other))
260    }
261}
262
263impl PartialEq<i32> for BvObject {
264    fn eq(&self, other: &i32) -> bool {
265        self.is_int() && self.raw.as_i32() == *other
266    }
267}
268
269impl PartialOrd<i32> for BvObject {
270    fn partial_cmp(&self, other: &i32) -> Option<std::cmp::Ordering> {
271        if !self.is_int() {
272            return None;
273        }
274
275        Some(self.raw.as_i32().cmp(other))
276    }
277}
278
279impl PartialEq<i64> for BvObject {
280    fn eq(&self, other: &i64) -> bool {
281        self.is_int() && self.raw.as_i64() == *other
282    }
283}
284
285impl PartialOrd<i64> for BvObject {
286    fn partial_cmp(&self, other: &i64) -> Option<std::cmp::Ordering> {
287        if !self.is_int() {
288            return None;
289        }
290
291        Some(self.raw.as_i64().cmp(other))
292    }
293}
294
295impl PartialEq<i128> for BvObject {
296    fn eq(&self, other: &i128) -> bool {
297        self.is_uint() && self.raw.as_i128() == *other
298    }
299}
300
301impl PartialOrd<i128> for BvObject {
302    fn partial_cmp(&self, other: &i128) -> Option<std::cmp::Ordering> {
303        if !self.is_uint() {
304            return None;
305        }
306
307        Some(self.raw.as_i128().cmp(other))
308    }
309}
310
311impl PartialEq<u16> for BvObject {
312    fn eq(&self, other: &u16) -> bool {
313        self.is_uint() && self.raw.as_u16() == *other
314    }
315}
316
317impl PartialOrd<u16> for BvObject {
318    fn partial_cmp(&self, other: &u16) -> Option<std::cmp::Ordering> {
319        if !self.is_uint() {
320            return None;
321        }
322
323        Some(self.raw.as_u16().cmp(other))
324    }
325}
326
327impl PartialEq<u32> for BvObject {
328    fn eq(&self, other: &u32) -> bool {
329        self.is_uint() && self.raw.as_u32() == *other
330    }
331}
332
333impl PartialOrd<u32> for BvObject {
334    fn partial_cmp(&self, other: &u32) -> Option<std::cmp::Ordering> {
335        if !self.is_uint() {
336            return None;
337        }
338
339        Some(self.raw.as_u32().cmp(other))
340    }
341}
342
343impl PartialEq<u64> for BvObject {
344    fn eq(&self, other: &u64) -> bool {
345        self.is_uint() && self.raw.as_u64() == *other
346    }
347}
348
349impl PartialOrd<u64> for BvObject {
350    fn partial_cmp(&self, other: &u64) -> Option<std::cmp::Ordering> {
351        if !self.is_uint() {
352            return None;
353        }
354
355        Some(self.raw.as_u64().cmp(other))
356    }
357}
358
359impl PartialEq<usize> for BvObject {
360    fn eq(&self, other: &usize) -> bool {
361        self.is_uint() && self.raw.as_usize() == *other
362    }
363}
364
365impl PartialOrd<usize> for BvObject {
366    fn partial_cmp(&self, other: &usize) -> Option<std::cmp::Ordering> {
367        if !self.is_uint() {
368            return None;
369        }
370
371        Some(self.raw.as_usize().cmp(other))
372    }
373}
374
375impl PartialEq<u128> for BvObject {
376    fn eq(&self, other: &u128) -> bool {
377        self.is_uint() && self.raw.as_u128() == *other
378    }
379}
380
381impl PartialOrd<u128> for BvObject {
382    fn partial_cmp(&self, other: &u128) -> Option<std::cmp::Ordering> {
383        if !self.is_uint() {
384            return None;
385        }
386
387        Some(self.raw.as_u128().cmp(other))
388    }
389}
390
391impl PartialEq<f32> for BvObject {
392    fn eq(&self, other: &f32) -> bool {
393        self.is_float() && self.raw.as_f32() == *other
394    }
395}
396
397impl PartialOrd<f32> for BvObject {
398    fn partial_cmp(&self, other: &f32) -> Option<std::cmp::Ordering> {
399        if !self.is_float() {
400            return None;
401        }
402
403        let value = self.raw.as_f32();
404        if value > *other {
405            Some(std::cmp::Ordering::Greater)
406        } else if value < *other {
407            Some(std::cmp::Ordering::Less)
408        } else {
409            Some(std::cmp::Ordering::Equal)
410        }
411    }
412}
413
414impl PartialEq<f64> for BvObject {
415    fn eq(&self, other: &f64) -> bool {
416        self.is_float() && self.raw.as_f64() == *other
417    }
418}
419
420impl PartialOrd<f64> for BvObject {
421    fn partial_cmp(&self, other: &f64) -> Option<std::cmp::Ordering> {
422        if !self.is_float() {
423            return None;
424        }
425
426        let value = self.raw.as_f64();
427        if value > *other {
428            Some(std::cmp::Ordering::Greater)
429        } else if value < *other {
430            Some(std::cmp::Ordering::Less)
431        } else {
432            Some(std::cmp::Ordering::Equal)
433        }
434    }
435}
436
437impl PartialEq<i8> for &BvObject {
438    fn eq(&self, other: &i8) -> bool {
439        self.is_int() && self.raw.as_i8() == *other
440    }
441}
442
443impl PartialEq<i16> for &BvObject {
444    fn eq(&self, other: &i16) -> bool {
445        self.is_int() && self.raw.as_i16() == *other
446    }
447}
448
449impl PartialOrd<i16> for &BvObject {
450    fn partial_cmp(&self, other: &i16) -> Option<std::cmp::Ordering> {
451        if !self.is_int() {
452            return None;
453        }
454
455        Some(self.raw.as_i16().cmp(other))
456    }
457}
458
459impl PartialEq<i32> for &BvObject {
460    fn eq(&self, other: &i32) -> bool {
461        self.is_int() && self.raw.as_i32() == *other
462    }
463}
464
465impl PartialOrd<i32> for &BvObject {
466    fn partial_cmp(&self, other: &i32) -> Option<std::cmp::Ordering> {
467        if !self.is_int() {
468            return None;
469        }
470
471        Some(self.raw.as_i32().cmp(other))
472    }
473}
474
475impl PartialEq<i64> for &BvObject {
476    fn eq(&self, other: &i64) -> bool {
477        self.is_int() && self.raw.as_i64() == *other
478    }
479}
480
481impl PartialOrd<i64> for &BvObject {
482    fn partial_cmp(&self, other: &i64) -> Option<std::cmp::Ordering> {
483        if !self.is_int() {
484            return None;
485        }
486
487        Some(self.raw.as_i64().cmp(other))
488    }
489}
490
491impl PartialEq<i128> for &BvObject {
492    fn eq(&self, other: &i128) -> bool {
493        self.is_int() && self.raw.as_i128() == *other
494    }
495}
496
497impl PartialOrd<i128> for &BvObject {
498    fn partial_cmp(&self, other: &i128) -> Option<std::cmp::Ordering> {
499        if !self.is_int() {
500            return None;
501        }
502
503        Some(self.raw.as_i128().cmp(other))
504    }
505}
506
507impl PartialEq<u16> for &BvObject {
508    fn eq(&self, other: &u16) -> bool {
509        self.is_uint() && self.raw.as_u16() == *other
510    }
511}
512
513impl PartialOrd<u16> for &BvObject {
514    fn partial_cmp(&self, other: &u16) -> Option<std::cmp::Ordering> {
515        if !self.is_uint() {
516            return None;
517        }
518
519        Some(self.raw.as_u16().cmp(other))
520    }
521}
522
523impl PartialEq<u32> for &BvObject {
524    fn eq(&self, other: &u32) -> bool {
525        self.is_uint() && self.raw.as_u32() == *other
526    }
527}
528
529impl PartialOrd<u32> for &BvObject {
530    fn partial_cmp(&self, other: &u32) -> Option<std::cmp::Ordering> {
531        if !self.is_uint() {
532            return None;
533        }
534
535        Some(self.raw.as_u32().cmp(other))
536    }
537}
538
539impl PartialEq<u64> for &BvObject {
540    fn eq(&self, other: &u64) -> bool {
541        self.is_uint() && self.raw.as_u64() == *other
542    }
543}
544
545impl PartialOrd<u64> for &BvObject {
546    fn partial_cmp(&self, other: &u64) -> Option<std::cmp::Ordering> {
547        if !self.is_uint() {
548            return None;
549        }
550
551        Some(self.raw.as_u64().cmp(other))
552    }
553}
554
555impl PartialEq<u128> for &BvObject {
556    fn eq(&self, other: &u128) -> bool {
557        self.is_uint() && self.raw.as_u128() == *other
558    }
559}
560
561impl PartialOrd<u128> for &BvObject {
562    fn partial_cmp(&self, other: &u128) -> Option<std::cmp::Ordering> {
563        if !self.is_uint() {
564            return None;
565        }
566
567        Some(self.raw.as_u128().cmp(other))
568    }
569}
570
571impl PartialEq<usize> for &BvObject {
572    fn eq(&self, other: &usize) -> bool {
573        self.is_uint() && self.raw.as_usize() == *other
574    }
575}
576
577impl PartialOrd<usize> for &BvObject {
578    fn partial_cmp(&self, other: &usize) -> Option<std::cmp::Ordering> {
579        if !self.is_uint() {
580            return None;
581        }
582
583        Some(self.raw.as_usize().cmp(other))
584    }
585}
586
587impl PartialEq<f32> for &BvObject {
588    fn eq(&self, other: &f32) -> bool {
589        self.is_float() && self.raw.as_f32() == *other
590    }
591}
592
593impl PartialOrd<f32> for &BvObject {
594    fn partial_cmp(&self, other: &f32) -> Option<std::cmp::Ordering> {
595        if !self.is_float() {
596            return None;
597        }
598
599        let value = self.raw.as_f32();
600        if value > *other {
601            Some(std::cmp::Ordering::Greater)
602        } else if value < *other {
603            Some(std::cmp::Ordering::Less)
604        } else {
605            Some(std::cmp::Ordering::Equal)
606        }
607    }
608}
609
610impl PartialEq<f64> for &BvObject {
611    fn eq(&self, other: &f64) -> bool {
612        self.is_float() && self.raw.as_f64() == *other
613    }
614}
615
616impl PartialOrd<f64> for &BvObject {
617    fn partial_cmp(&self, other: &f64) -> Option<std::cmp::Ordering> {
618        if !self.is_float() {
619            return None;
620        }
621
622        let value = self.raw.as_f64();
623        if value > *other {
624            Some(std::cmp::Ordering::Greater)
625        } else if value < *other {
626            Some(std::cmp::Ordering::Less)
627        } else {
628            Some(std::cmp::Ordering::Equal)
629        }
630    }
631}