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#[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 [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 [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 [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}