1 | // SPDX-License-Identifier: Apache-2.0 |
2 | |
3 | //! A dynamic CBOR value |
4 | |
5 | mod canonical; |
6 | mod integer; |
7 | |
8 | mod de; |
9 | mod error; |
10 | mod ser; |
11 | |
12 | pub use canonical::CanonicalValue; |
13 | pub use error::Error; |
14 | pub use integer::Integer; |
15 | |
16 | use alloc::{boxed::Box, string::String, vec::Vec}; |
17 | |
18 | /// A representation of a dynamic CBOR value that can handled dynamically |
19 | #[non_exhaustive ] |
20 | #[derive(Clone, Debug, PartialEq, PartialOrd)] |
21 | pub enum Value { |
22 | /// An integer |
23 | Integer(Integer), |
24 | |
25 | /// Bytes |
26 | Bytes(Vec<u8>), |
27 | |
28 | /// A float |
29 | Float(f64), |
30 | |
31 | /// A string |
32 | Text(String), |
33 | |
34 | /// A boolean |
35 | Bool(bool), |
36 | |
37 | /// Null |
38 | Null, |
39 | |
40 | /// Tag |
41 | Tag(u64, Box<Value>), |
42 | |
43 | /// An array |
44 | Array(Vec<Value>), |
45 | |
46 | /// A map |
47 | Map(Vec<(Value, Value)>), |
48 | } |
49 | |
50 | impl Value { |
51 | /// Returns true if the `Value` is an `Integer`. Returns false otherwise. |
52 | /// |
53 | /// ``` |
54 | /// # use ciborium::Value; |
55 | /// # |
56 | /// let value = Value::Integer(17.into()); |
57 | /// |
58 | /// assert!(value.is_integer()); |
59 | /// ``` |
60 | pub fn is_integer(&self) -> bool { |
61 | self.as_integer().is_some() |
62 | } |
63 | |
64 | /// If the `Value` is a `Integer`, returns a reference to the associated `Integer` data. |
65 | /// Returns None otherwise. |
66 | /// |
67 | /// ``` |
68 | /// # use ciborium::Value; |
69 | /// # |
70 | /// let value = Value::Integer(17.into()); |
71 | /// |
72 | /// // We can read the number |
73 | /// assert_eq!(17, value.as_integer().unwrap().try_into().unwrap()); |
74 | /// ``` |
75 | pub fn as_integer(&self) -> Option<Integer> { |
76 | match self { |
77 | Value::Integer(int) => Some(*int), |
78 | _ => None, |
79 | } |
80 | } |
81 | |
82 | /// If the `Value` is a `Integer`, returns a the associated `Integer` data as `Ok`. |
83 | /// Returns `Err(Self)` otherwise. |
84 | /// |
85 | /// ``` |
86 | /// # use ciborium::{Value, value::Integer}; |
87 | /// # |
88 | /// let value = Value::Integer(17.into()); |
89 | /// assert_eq!(value.into_integer(), Ok(Integer::from(17))); |
90 | /// |
91 | /// let value = Value::Bool(true); |
92 | /// assert_eq!(value.into_integer(), Err(Value::Bool(true))); |
93 | /// ``` |
94 | pub fn into_integer(self) -> Result<Integer, Self> { |
95 | match self { |
96 | Value::Integer(int) => Ok(int), |
97 | other => Err(other), |
98 | } |
99 | } |
100 | |
101 | /// Returns true if the `Value` is a `Bytes`. Returns false otherwise. |
102 | /// |
103 | /// ``` |
104 | /// # use ciborium::Value; |
105 | /// # |
106 | /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); |
107 | /// |
108 | /// assert!(value.is_bytes()); |
109 | /// ``` |
110 | pub fn is_bytes(&self) -> bool { |
111 | self.as_bytes().is_some() |
112 | } |
113 | |
114 | /// If the `Value` is a `Bytes`, returns a reference to the associated bytes vector. |
115 | /// Returns None otherwise. |
116 | /// |
117 | /// ``` |
118 | /// # use ciborium::Value; |
119 | /// # |
120 | /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); |
121 | /// |
122 | /// assert_eq!(std::str::from_utf8(value.as_bytes().unwrap()).unwrap(), "hello" ); |
123 | /// ``` |
124 | pub fn as_bytes(&self) -> Option<&Vec<u8>> { |
125 | match *self { |
126 | Value::Bytes(ref bytes) => Some(bytes), |
127 | _ => None, |
128 | } |
129 | } |
130 | |
131 | /// If the `Value` is a `Bytes`, returns a mutable reference to the associated bytes vector. |
132 | /// Returns None otherwise. |
133 | /// |
134 | /// ``` |
135 | /// # use ciborium::Value; |
136 | /// # |
137 | /// let mut value = Value::Bytes(vec![104, 101, 108, 108, 111]); |
138 | /// value.as_bytes_mut().unwrap().clear(); |
139 | /// |
140 | /// assert_eq!(value, Value::Bytes(vec![])); |
141 | /// ``` |
142 | pub fn as_bytes_mut(&mut self) -> Option<&mut Vec<u8>> { |
143 | match *self { |
144 | Value::Bytes(ref mut bytes) => Some(bytes), |
145 | _ => None, |
146 | } |
147 | } |
148 | |
149 | /// If the `Value` is a `Bytes`, returns a the associated `Vec<u8>` data as `Ok`. |
150 | /// Returns `Err(Self)` otherwise. |
151 | /// |
152 | /// ``` |
153 | /// # use ciborium::Value; |
154 | /// # |
155 | /// let value = Value::Bytes(vec![104, 101, 108, 108, 111]); |
156 | /// assert_eq!(value.into_bytes(), Ok(vec![104, 101, 108, 108, 111])); |
157 | /// |
158 | /// let value = Value::Bool(true); |
159 | /// assert_eq!(value.into_bytes(), Err(Value::Bool(true))); |
160 | /// ``` |
161 | pub fn into_bytes(self) -> Result<Vec<u8>, Self> { |
162 | match self { |
163 | Value::Bytes(vec) => Ok(vec), |
164 | other => Err(other), |
165 | } |
166 | } |
167 | |
168 | /// Returns true if the `Value` is a `Float`. Returns false otherwise. |
169 | /// |
170 | /// ``` |
171 | /// # use ciborium::Value; |
172 | /// # |
173 | /// let value = Value::Float(17.0.into()); |
174 | /// |
175 | /// assert!(value.is_float()); |
176 | /// ``` |
177 | pub fn is_float(&self) -> bool { |
178 | self.as_float().is_some() |
179 | } |
180 | |
181 | /// If the `Value` is a `Float`, returns a reference to the associated float data. |
182 | /// Returns None otherwise. |
183 | /// |
184 | /// ``` |
185 | /// # use ciborium::Value; |
186 | /// # |
187 | /// let value = Value::Float(17.0.into()); |
188 | /// |
189 | /// // We can read the float number |
190 | /// assert_eq!(value.as_float().unwrap(), 17.0_f64); |
191 | /// ``` |
192 | pub fn as_float(&self) -> Option<f64> { |
193 | match *self { |
194 | Value::Float(f) => Some(f), |
195 | _ => None, |
196 | } |
197 | } |
198 | |
199 | /// If the `Value` is a `Float`, returns a the associated `f64` data as `Ok`. |
200 | /// Returns `Err(Self)` otherwise. |
201 | /// |
202 | /// ``` |
203 | /// # use ciborium::Value; |
204 | /// # |
205 | /// let value = Value::Float(17.); |
206 | /// assert_eq!(value.into_float(), Ok(17.)); |
207 | /// |
208 | /// let value = Value::Bool(true); |
209 | /// assert_eq!(value.into_float(), Err(Value::Bool(true))); |
210 | /// ``` |
211 | pub fn into_float(self) -> Result<f64, Self> { |
212 | match self { |
213 | Value::Float(f) => Ok(f), |
214 | other => Err(other), |
215 | } |
216 | } |
217 | |
218 | /// Returns true if the `Value` is a `Text`. Returns false otherwise. |
219 | /// |
220 | /// ``` |
221 | /// # use ciborium::Value; |
222 | /// # |
223 | /// let value = Value::Text(String::from("hello" )); |
224 | /// |
225 | /// assert!(value.is_text()); |
226 | /// ``` |
227 | pub fn is_text(&self) -> bool { |
228 | self.as_text().is_some() |
229 | } |
230 | |
231 | /// If the `Value` is a `Text`, returns a reference to the associated `String` data. |
232 | /// Returns None otherwise. |
233 | /// |
234 | /// ``` |
235 | /// # use ciborium::Value; |
236 | /// # |
237 | /// let value = Value::Text(String::from("hello" )); |
238 | /// |
239 | /// // We can read the String |
240 | /// assert_eq!(value.as_text().unwrap(), "hello" ); |
241 | /// ``` |
242 | pub fn as_text(&self) -> Option<&str> { |
243 | match *self { |
244 | Value::Text(ref s) => Some(s), |
245 | _ => None, |
246 | } |
247 | } |
248 | |
249 | /// If the `Value` is a `Text`, returns a mutable reference to the associated `String` data. |
250 | /// Returns None otherwise. |
251 | /// |
252 | /// ``` |
253 | /// # use ciborium::Value; |
254 | /// # |
255 | /// let mut value = Value::Text(String::from("hello" )); |
256 | /// value.as_text_mut().unwrap().clear(); |
257 | /// |
258 | /// assert_eq!(value.as_text().unwrap(), &String::from("" )); |
259 | /// ``` |
260 | pub fn as_text_mut(&mut self) -> Option<&mut String> { |
261 | match *self { |
262 | Value::Text(ref mut s) => Some(s), |
263 | _ => None, |
264 | } |
265 | } |
266 | |
267 | /// If the `Value` is a `String`, returns a the associated `String` data as `Ok`. |
268 | /// Returns `Err(Self)` otherwise. |
269 | /// |
270 | /// ``` |
271 | /// # use ciborium::Value; |
272 | /// # |
273 | /// let value = Value::Text(String::from("hello" )); |
274 | /// assert_eq!(value.into_text().as_deref(), Ok("hello" )); |
275 | /// |
276 | /// let value = Value::Bool(true); |
277 | /// assert_eq!(value.into_text(), Err(Value::Bool(true))); |
278 | /// ``` |
279 | pub fn into_text(self) -> Result<String, Self> { |
280 | match self { |
281 | Value::Text(s) => Ok(s), |
282 | other => Err(other), |
283 | } |
284 | } |
285 | |
286 | /// Returns true if the `Value` is a `Bool`. Returns false otherwise. |
287 | /// |
288 | /// ``` |
289 | /// # use ciborium::Value; |
290 | /// # |
291 | /// let value = Value::Bool(false); |
292 | /// |
293 | /// assert!(value.is_bool()); |
294 | /// ``` |
295 | pub fn is_bool(&self) -> bool { |
296 | self.as_bool().is_some() |
297 | } |
298 | |
299 | /// If the `Value` is a `Bool`, returns a copy of the associated boolean value. Returns None |
300 | /// otherwise. |
301 | /// |
302 | /// ``` |
303 | /// # use ciborium::Value; |
304 | /// # |
305 | /// let value = Value::Bool(false); |
306 | /// |
307 | /// assert_eq!(value.as_bool().unwrap(), false); |
308 | /// ``` |
309 | pub fn as_bool(&self) -> Option<bool> { |
310 | match *self { |
311 | Value::Bool(b) => Some(b), |
312 | _ => None, |
313 | } |
314 | } |
315 | |
316 | /// If the `Value` is a `Bool`, returns a the associated `bool` data as `Ok`. |
317 | /// Returns `Err(Self)` otherwise. |
318 | /// |
319 | /// ``` |
320 | /// # use ciborium::Value; |
321 | /// # |
322 | /// let value = Value::Bool(false); |
323 | /// assert_eq!(value.into_bool(), Ok(false)); |
324 | /// |
325 | /// let value = Value::Float(17.); |
326 | /// assert_eq!(value.into_bool(), Err(Value::Float(17.))); |
327 | /// ``` |
328 | pub fn into_bool(self) -> Result<bool, Self> { |
329 | match self { |
330 | Value::Bool(b) => Ok(b), |
331 | other => Err(other), |
332 | } |
333 | } |
334 | |
335 | /// Returns true if the `Value` is a `Null`. Returns false otherwise. |
336 | /// |
337 | /// ``` |
338 | /// # use ciborium::Value; |
339 | /// # |
340 | /// let value = Value::Null; |
341 | /// |
342 | /// assert!(value.is_null()); |
343 | /// ``` |
344 | pub fn is_null(&self) -> bool { |
345 | matches!(self, Value::Null) |
346 | } |
347 | |
348 | /// Returns true if the `Value` is a `Tag`. Returns false otherwise. |
349 | /// |
350 | /// ``` |
351 | /// # use ciborium::Value; |
352 | /// # |
353 | /// let value = Value::Tag(61, Box::from(Value::Null)); |
354 | /// |
355 | /// assert!(value.is_tag()); |
356 | /// ``` |
357 | pub fn is_tag(&self) -> bool { |
358 | self.as_tag().is_some() |
359 | } |
360 | |
361 | /// If the `Value` is a `Tag`, returns the associated tag value and a reference to the tag `Value`. |
362 | /// Returns None otherwise. |
363 | /// |
364 | /// ``` |
365 | /// # use ciborium::Value; |
366 | /// # |
367 | /// let value = Value::Tag(61, Box::from(Value::Bytes(vec![104, 101, 108, 108, 111]))); |
368 | /// |
369 | /// let (tag, data) = value.as_tag().unwrap(); |
370 | /// assert_eq!(tag, 61); |
371 | /// assert_eq!(data, &Value::Bytes(vec![104, 101, 108, 108, 111])); |
372 | /// ``` |
373 | pub fn as_tag(&self) -> Option<(u64, &Value)> { |
374 | match self { |
375 | Value::Tag(tag, data) => Some((*tag, data)), |
376 | _ => None, |
377 | } |
378 | } |
379 | |
380 | /// If the `Value` is a `Tag`, returns the associated tag value and a mutable reference |
381 | /// to the tag `Value`. Returns None otherwise. |
382 | /// |
383 | /// ``` |
384 | /// # use ciborium::Value; |
385 | /// # |
386 | /// let mut value = Value::Tag(61, Box::from(Value::Bytes(vec![104, 101, 108, 108, 111]))); |
387 | /// |
388 | /// let (tag, mut data) = value.as_tag_mut().unwrap(); |
389 | /// data.as_bytes_mut().unwrap().clear(); |
390 | /// assert_eq!(tag, &61); |
391 | /// assert_eq!(data, &Value::Bytes(vec![])); |
392 | /// ``` |
393 | pub fn as_tag_mut(&mut self) -> Option<(&mut u64, &mut Value)> { |
394 | match self { |
395 | Value::Tag(tag, data) => Some((tag, data.as_mut())), |
396 | _ => None, |
397 | } |
398 | } |
399 | |
400 | /// If the `Value` is a `Tag`, returns a the associated pair of `u64` and `Box<value>` data as `Ok`. |
401 | /// Returns `Err(Self)` otherwise. |
402 | /// |
403 | /// ``` |
404 | /// # use ciborium::Value; |
405 | /// # |
406 | /// let value = Value::Tag(7, Box::new(Value::Float(12.))); |
407 | /// assert_eq!(value.into_tag(), Ok((7, Box::new(Value::Float(12.))))); |
408 | /// |
409 | /// let value = Value::Bool(true); |
410 | /// assert_eq!(value.into_tag(), Err(Value::Bool(true))); |
411 | /// ``` |
412 | pub fn into_tag(self) -> Result<(u64, Box<Value>), Self> { |
413 | match self { |
414 | Value::Tag(tag, value) => Ok((tag, value)), |
415 | other => Err(other), |
416 | } |
417 | } |
418 | |
419 | /// Returns true if the `Value` is an Array. Returns false otherwise. |
420 | /// |
421 | /// ``` |
422 | /// # use ciborium::Value; |
423 | /// # |
424 | /// let value = Value::Array( |
425 | /// vec![ |
426 | /// Value::Text(String::from("foo" )), |
427 | /// Value::Text(String::from("bar" )) |
428 | /// ] |
429 | /// ); |
430 | /// |
431 | /// assert!(value.is_array()); |
432 | /// ``` |
433 | pub fn is_array(&self) -> bool { |
434 | self.as_array().is_some() |
435 | } |
436 | |
437 | /// If the `Value` is an Array, returns a reference to the associated vector. Returns None |
438 | /// otherwise. |
439 | /// |
440 | /// ``` |
441 | /// # use ciborium::Value; |
442 | /// # |
443 | /// let value = Value::Array( |
444 | /// vec![ |
445 | /// Value::Text(String::from("foo" )), |
446 | /// Value::Text(String::from("bar" )) |
447 | /// ] |
448 | /// ); |
449 | /// |
450 | /// // The length of `value` is 2 elements. |
451 | /// assert_eq!(value.as_array().unwrap().len(), 2); |
452 | /// ``` |
453 | pub fn as_array(&self) -> Option<&Vec<Value>> { |
454 | match *self { |
455 | Value::Array(ref array) => Some(array), |
456 | _ => None, |
457 | } |
458 | } |
459 | |
460 | /// If the `Value` is an Array, returns a mutable reference to the associated vector. |
461 | /// Returns None otherwise. |
462 | /// |
463 | /// ``` |
464 | /// # use ciborium::Value; |
465 | /// # |
466 | /// let mut value = Value::Array( |
467 | /// vec![ |
468 | /// Value::Text(String::from("foo" )), |
469 | /// Value::Text(String::from("bar" )) |
470 | /// ] |
471 | /// ); |
472 | /// |
473 | /// value.as_array_mut().unwrap().clear(); |
474 | /// assert_eq!(value, Value::Array(vec![])); |
475 | /// ``` |
476 | pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> { |
477 | match *self { |
478 | Value::Array(ref mut list) => Some(list), |
479 | _ => None, |
480 | } |
481 | } |
482 | |
483 | /// If the `Value` is a `Array`, returns a the associated `Vec<Value>` data as `Ok`. |
484 | /// Returns `Err(Self)` otherwise. |
485 | /// |
486 | /// ``` |
487 | /// # use ciborium::{Value, value::Integer}; |
488 | /// # |
489 | /// let mut value = Value::Array( |
490 | /// vec![ |
491 | /// Value::Integer(17.into()), |
492 | /// Value::Float(18.), |
493 | /// ] |
494 | /// ); |
495 | /// assert_eq!(value.into_array(), Ok(vec![Value::Integer(17.into()), Value::Float(18.)])); |
496 | /// |
497 | /// let value = Value::Bool(true); |
498 | /// assert_eq!(value.into_array(), Err(Value::Bool(true))); |
499 | /// ``` |
500 | pub fn into_array(self) -> Result<Vec<Value>, Self> { |
501 | match self { |
502 | Value::Array(vec) => Ok(vec), |
503 | other => Err(other), |
504 | } |
505 | } |
506 | |
507 | /// Returns true if the `Value` is a Map. Returns false otherwise. |
508 | /// |
509 | /// ``` |
510 | /// # use ciborium::Value; |
511 | /// # |
512 | /// let value = Value::Map( |
513 | /// vec![ |
514 | /// (Value::Text(String::from("foo" )), Value::Text(String::from("bar" ))) |
515 | /// ] |
516 | /// ); |
517 | /// |
518 | /// assert!(value.is_map()); |
519 | /// ``` |
520 | pub fn is_map(&self) -> bool { |
521 | self.as_map().is_some() |
522 | } |
523 | |
524 | /// If the `Value` is a Map, returns a reference to the associated Map data. Returns None |
525 | /// otherwise. |
526 | /// |
527 | /// ``` |
528 | /// # use ciborium::Value; |
529 | /// # |
530 | /// let value = Value::Map( |
531 | /// vec![ |
532 | /// (Value::Text(String::from("foo" )), Value::Text(String::from("bar" ))) |
533 | /// ] |
534 | /// ); |
535 | /// |
536 | /// // The length of data is 1 entry (1 key/value pair). |
537 | /// assert_eq!(value.as_map().unwrap().len(), 1); |
538 | /// |
539 | /// // The content of the first element is what we expect |
540 | /// assert_eq!( |
541 | /// value.as_map().unwrap().get(0).unwrap(), |
542 | /// &(Value::Text(String::from("foo" )), Value::Text(String::from("bar" ))) |
543 | /// ); |
544 | /// ``` |
545 | pub fn as_map(&self) -> Option<&Vec<(Value, Value)>> { |
546 | match *self { |
547 | Value::Map(ref map) => Some(map), |
548 | _ => None, |
549 | } |
550 | } |
551 | |
552 | /// If the `Value` is a Map, returns a mutable reference to the associated Map Data. |
553 | /// Returns None otherwise. |
554 | /// |
555 | /// ``` |
556 | /// # use ciborium::Value; |
557 | /// # |
558 | /// let mut value = Value::Map( |
559 | /// vec![ |
560 | /// (Value::Text(String::from("foo" )), Value::Text(String::from("bar" ))) |
561 | /// ] |
562 | /// ); |
563 | /// |
564 | /// value.as_map_mut().unwrap().clear(); |
565 | /// assert_eq!(value, Value::Map(vec![])); |
566 | /// assert_eq!(value.as_map().unwrap().len(), 0); |
567 | /// ``` |
568 | pub fn as_map_mut(&mut self) -> Option<&mut Vec<(Value, Value)>> { |
569 | match *self { |
570 | Value::Map(ref mut map) => Some(map), |
571 | _ => None, |
572 | } |
573 | } |
574 | |
575 | /// If the `Value` is a `Map`, returns a the associated `Vec<(Value, Value)>` data as `Ok`. |
576 | /// Returns `Err(Self)` otherwise. |
577 | /// |
578 | /// ``` |
579 | /// # use ciborium::Value; |
580 | /// # |
581 | /// let mut value = Value::Map( |
582 | /// vec![ |
583 | /// (Value::Text(String::from("key" )), Value::Float(18.)), |
584 | /// ] |
585 | /// ); |
586 | /// assert_eq!(value.into_map(), Ok(vec![(Value::Text(String::from("key" )), Value::Float(18.))])); |
587 | /// |
588 | /// let value = Value::Bool(true); |
589 | /// assert_eq!(value.into_map(), Err(Value::Bool(true))); |
590 | /// ``` |
591 | pub fn into_map(self) -> Result<Vec<(Value, Value)>, Self> { |
592 | match self { |
593 | Value::Map(map) => Ok(map), |
594 | other => Err(other), |
595 | } |
596 | } |
597 | } |
598 | |
599 | macro_rules! implfrom { |
600 | ($($v:ident($t:ty)),+ $(,)?) => { |
601 | $( |
602 | impl From<$t> for Value { |
603 | #[inline] |
604 | fn from(value: $t) -> Self { |
605 | Self::$v(value.into()) |
606 | } |
607 | } |
608 | )+ |
609 | }; |
610 | } |
611 | |
612 | implfrom! { |
613 | Integer(Integer), |
614 | Integer(u64), |
615 | Integer(i64), |
616 | Integer(u32), |
617 | Integer(i32), |
618 | Integer(u16), |
619 | Integer(i16), |
620 | Integer(u8), |
621 | Integer(i8), |
622 | |
623 | Bytes(Vec<u8>), |
624 | Bytes(&[u8]), |
625 | |
626 | Float(f64), |
627 | Float(f32), |
628 | |
629 | Text(String), |
630 | Text(&str), |
631 | |
632 | Bool(bool), |
633 | |
634 | Array(&[Value]), |
635 | Array(Vec<Value>), |
636 | |
637 | Map(&[(Value, Value)]), |
638 | Map(Vec<(Value, Value)>), |
639 | } |
640 | |
641 | impl From<u128> for Value { |
642 | #[inline ] |
643 | fn from(value: u128) -> Self { |
644 | if let Ok(x) = Integer::try_from(value) { |
645 | return Value::Integer(x); |
646 | } |
647 | |
648 | let mut bytes = &value.to_be_bytes()[..]; |
649 | while let Some(0) = bytes.first() { |
650 | bytes = &bytes[1..]; |
651 | } |
652 | |
653 | Value::Tag(ciborium_ll::tag::BIGPOS, Value::Bytes(bytes.into()).into()) |
654 | } |
655 | } |
656 | |
657 | impl From<i128> for Value { |
658 | #[inline ] |
659 | fn from(value: i128) -> Self { |
660 | if let Ok(x) = Integer::try_from(value) { |
661 | return Value::Integer(x); |
662 | } |
663 | |
664 | let (tag, raw) = match value.is_negative() { |
665 | true => (ciborium_ll::tag::BIGNEG, value as u128 ^ !0), |
666 | false => (ciborium_ll::tag::BIGPOS, value as u128), |
667 | }; |
668 | |
669 | let mut bytes = &raw.to_be_bytes()[..]; |
670 | while let Some(0) = bytes.first() { |
671 | bytes = &bytes[1..]; |
672 | } |
673 | |
674 | Value::Tag(tag, Value::Bytes(bytes.into()).into()) |
675 | } |
676 | } |
677 | |
678 | impl From<char> for Value { |
679 | #[inline ] |
680 | fn from(value: char) -> Self { |
681 | let mut v = String::with_capacity(1); |
682 | v.push(value); |
683 | Value::Text(v) |
684 | } |
685 | } |
686 | |