1use alloc::borrow::Cow;
4use alloc::boxed::Box;
5use alloc::collections::BTreeMap;
6use alloc::format;
7use alloc::string::{String, ToString};
8use alloc::vec::Vec;
9#[cfg(feature = "std")]
10use std::collections::HashMap;
11
12mod canonical;
13mod de;
14mod integer;
15mod ser;
16
17pub use canonical::KeyOrder;
18pub use integer::Integer;
19
20#[derive(Clone, Debug)]
22pub enum Error {
23 Custom(String),
25}
26
27impl core::fmt::Display for Error {
28 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
29 match self {
30 Error::Custom(msg) => write!(f, "{msg}"),
31 }
32 }
33}
34
35impl serde::ser::StdError for Error {}
38
39impl serde::de::Error for Error {
40 #[inline]
41 fn custom<T: core::fmt::Display>(msg: T) -> Self {
42 Self::Custom(msg.to_string())
43 }
44}
45
46impl serde::ser::Error for Error {
47 #[inline]
48 fn custom<T: core::fmt::Display>(msg: T) -> Self {
49 Self::Custom(msg.to_string())
50 }
51}
52
53#[non_exhaustive]
67#[derive(Clone, PartialEq, PartialOrd)]
68pub enum Value {
69 Integer(Integer),
71
72 Bytes(Vec<u8>),
74
75 Float(f64),
77
78 Text(String),
80
81 Bool(bool),
83
84 Null,
86
87 Tag(u64, Box<Value>),
89
90 Array(Vec<Value>),
92
93 Map(Vec<(Value, Value)>),
95}
96
97impl core::fmt::Debug for Value {
114 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
115 let mut out = String::new();
116 crate::diag::write_value_pretty(&mut out, self, 0);
117 f.write_str(&out)
118 }
119}
120
121macro_rules! accessors {
122 ($(#[doc = $doc:literal] $is:ident $as:ident $into:ident($variant:ident) -> $t:ty;)+) => {
123 $(
124 #[doc = concat!("Returns true if the value is ", $doc, ".")]
125 #[inline]
126 pub fn $is(&self) -> bool {
127 matches!(self, Value::$variant(..))
128 }
129
130 #[doc = concat!("If the value is ", $doc, ", returns a reference to it. Returns `None` otherwise.")]
131 #[inline]
132 pub fn $as(&self) -> Option<&$t> {
133 match self {
134 Value::$variant(x) => Some(x),
135 _ => None,
136 }
137 }
138
139 #[doc = concat!("If the value is ", $doc, ", returns it as `Ok`. Returns `Err(self)` otherwise.")]
140 #[inline]
141 pub fn $into(self) -> Result<$t, Self> {
142 match self {
143 Value::$variant(x) => Ok(x),
144 other => Err(other),
145 }
146 }
147 )+
148 };
149}
150
151impl Value {
152 accessors! {
153 #[doc = "a byte string"]
154 is_bytes as_bytes into_bytes(Bytes) -> Vec<u8>;
155
156 #[doc = "an array"]
157 is_array as_array into_array(Array) -> Vec<Value>;
158
159 #[doc = "a map"]
160 is_map as_map into_map(Map) -> Vec<(Value, Value)>;
161 }
162
163 #[inline]
165 pub fn is_integer(&self) -> bool {
166 matches!(self, Value::Integer(..))
167 }
168
169 #[inline]
171 pub fn as_integer(&self) -> Option<Integer> {
172 match self {
173 Value::Integer(x) => Some(*x),
174 _ => None,
175 }
176 }
177
178 #[inline]
181 pub fn into_integer(self) -> Result<Integer, Self> {
182 match self {
183 Value::Integer(x) => Ok(x),
184 other => Err(other),
185 }
186 }
187
188 #[inline]
190 pub fn is_float(&self) -> bool {
191 matches!(self, Value::Float(..))
192 }
193
194 #[inline]
196 pub fn as_float(&self) -> Option<f64> {
197 match self {
198 Value::Float(x) => Some(*x),
199 _ => None,
200 }
201 }
202
203 #[inline]
206 pub fn into_float(self) -> Result<f64, Self> {
207 match self {
208 Value::Float(x) => Ok(x),
209 other => Err(other),
210 }
211 }
212
213 #[inline]
215 pub fn is_text(&self) -> bool {
216 matches!(self, Value::Text(..))
217 }
218
219 #[inline]
222 pub fn as_text(&self) -> Option<&str> {
223 match self {
224 Value::Text(x) => Some(x),
225 _ => None,
226 }
227 }
228
229 #[inline]
232 pub fn into_text(self) -> Result<String, Self> {
233 match self {
234 Value::Text(x) => Ok(x),
235 other => Err(other),
236 }
237 }
238
239 #[inline]
241 pub fn is_bool(&self) -> bool {
242 matches!(self, Value::Bool(..))
243 }
244
245 #[inline]
247 pub fn as_bool(&self) -> Option<bool> {
248 match self {
249 Value::Bool(x) => Some(*x),
250 _ => None,
251 }
252 }
253
254 #[inline]
257 pub fn into_bool(self) -> Result<bool, Self> {
258 match self {
259 Value::Bool(x) => Ok(x),
260 other => Err(other),
261 }
262 }
263
264 #[inline]
266 pub fn is_null(&self) -> bool {
267 matches!(self, Value::Null)
268 }
269
270 #[inline]
272 pub fn is_tag(&self) -> bool {
273 matches!(self, Value::Tag(..))
274 }
275
276 #[inline]
279 pub fn as_tag(&self) -> Option<(u64, &Value)> {
280 match self {
281 Value::Tag(tag, data) => Some((*tag, data)),
282 _ => None,
283 }
284 }
285
286 #[inline]
289 pub fn into_tag(self) -> Result<(u64, Box<Value>), Self> {
290 match self {
291 Value::Tag(tag, data) => Ok((tag, data)),
292 other => Err(other),
293 }
294 }
295
296 #[inline]
299 pub fn as_bytes_mut(&mut self) -> Option<&mut Vec<u8>> {
300 match self {
301 Value::Bytes(x) => Some(x),
302 _ => None,
303 }
304 }
305
306 #[inline]
309 pub fn as_text_mut(&mut self) -> Option<&mut String> {
310 match self {
311 Value::Text(x) => Some(x),
312 _ => None,
313 }
314 }
315
316 #[inline]
319 pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
320 match self {
321 Value::Array(x) => Some(x),
322 _ => None,
323 }
324 }
325
326 #[inline]
329 pub fn as_map_mut(&mut self) -> Option<&mut Vec<(Value, Value)>> {
330 match self {
331 Value::Map(x) => Some(x),
332 _ => None,
333 }
334 }
335
336 #[inline]
339 pub fn as_tag_mut(&mut self) -> Option<(&mut u64, &mut Value)> {
340 match self {
341 Value::Tag(tag, data) => Some((tag, data.as_mut())),
342 _ => None,
343 }
344 }
345}
346
347impl core::fmt::Display for Value {
360 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
361 let mut out = String::new();
362 crate::diag::write_value(&mut out, self);
363 f.write_str(&out)
364 }
365}
366
367macro_rules! implfrom {
368 ($($variant:ident($t:ty)),+ $(,)?) => {
369 $(
370 impl From<$t> for Value {
371 #[inline]
372 fn from(value: $t) -> Self {
373 Self::$variant(value.into())
374 }
375 }
376 )+
377 };
378}
379
380implfrom! {
381 Integer(Integer),
382 Integer(u64),
383 Integer(i64),
384 Integer(u32),
385 Integer(i32),
386 Integer(u16),
387 Integer(i16),
388 Integer(u8),
389 Integer(i8),
390
391 Bytes(Vec<u8>),
392 Bytes(&[u8]),
393
394 Float(f64),
395 Float(f32),
396
397 Text(String),
398 Text(&str),
399
400 Bool(bool),
401
402 Array(&[Value]),
403 Array(Vec<Value>),
404
405 Map(&[(Value, Value)]),
406 Map(Vec<(Value, Value)>),
407}
408
409impl From<u128> for Value {
410 #[inline]
411 fn from(value: u128) -> Self {
412 if let Ok(x) = Integer::try_from(value) {
413 return Value::Integer(x);
414 }
415
416 let mut bytes = &value.to_be_bytes()[..];
417 while let Some(0) = bytes.first() {
418 bytes = &bytes[1..];
419 }
420
421 Value::Tag(crate::core::tag::BIGPOS, Value::Bytes(bytes.into()).into())
422 }
423}
424
425impl From<i128> for Value {
426 #[inline]
427 fn from(value: i128) -> Self {
428 if let Ok(x) = Integer::try_from(value) {
429 return Value::Integer(x);
430 }
431
432 let (tag, raw) = match value.is_negative() {
433 true => (crate::core::tag::BIGNEG, value as u128 ^ !0),
434 false => (crate::core::tag::BIGPOS, value as u128),
435 };
436
437 let mut bytes = &raw.to_be_bytes()[..];
438 while let Some(0) = bytes.first() {
439 bytes = &bytes[1..];
440 }
441
442 Value::Tag(tag, Value::Bytes(bytes.into()).into())
443 }
444}
445
446impl From<char> for Value {
447 #[inline]
448 fn from(value: char) -> Self {
449 let mut v = String::with_capacity(value.len_utf8());
450 v.push(value);
451 Value::Text(v)
452 }
453}
454
455impl From<Cow<'_, str>> for Value {
456 #[inline]
457 fn from(value: Cow<'_, str>) -> Self {
458 Value::Text(value.into_owned())
459 }
460}
461
462impl<const N: usize> From<[u8; N]> for Value {
463 #[inline]
464 fn from(value: [u8; N]) -> Self {
465 Value::Bytes(value.into())
466 }
467}
468
469impl<const N: usize> From<&[u8; N]> for Value {
470 #[inline]
471 fn from(value: &[u8; N]) -> Self {
472 Value::Bytes(value.into())
473 }
474}
475
476#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
477impl From<usize> for Value {
478 #[inline]
479 fn from(value: usize) -> Self {
480 Value::Integer(value.into())
481 }
482}
483
484#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
485impl From<isize> for Value {
486 #[inline]
487 fn from(value: isize) -> Self {
488 Value::Integer(value.into())
489 }
490}
491
492impl<T: Into<Value>> From<Option<T>> for Value {
494 #[inline]
495 fn from(value: Option<T>) -> Self {
496 match value {
497 Some(value) => value.into(),
498 None => Value::Null,
499 }
500 }
501}
502
503#[cfg(feature = "std")]
516impl<K: Into<Value>, V: Into<Value>> From<HashMap<K, V>> for Value {
517 fn from(value: HashMap<K, V>) -> Self {
518 Value::Map(
519 value
520 .into_iter()
521 .map(|(k, v)| (k.into(), v.into()))
522 .collect(),
523 )
524 }
525}
526
527impl<K: Into<Value>, V: Into<Value>> From<BTreeMap<K, V>> for Value {
529 fn from(value: BTreeMap<K, V>) -> Self {
530 Value::Map(
531 value
532 .into_iter()
533 .map(|(k, v)| (k.into(), v.into()))
534 .collect(),
535 )
536 }
537}
538
539impl<T: Into<Value>> FromIterator<T> for Value {
548 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
549 Value::Array(iter.into_iter().map(Into::into).collect())
550 }
551}
552
553fn invalid_type(value: &Value, expected: &'static str) -> Error {
555 serde::de::Error::invalid_type(value.into(), &expected)
556}
557
558macro_rules! tryfrom_value {
559 ($($t:ty: $variant:ident => $expected:literal,)+) => {$(
560 #[doc = concat!("Converts from [`Value::", stringify!($variant), "`]; any other variant is an `\"invalid type\"` error.")]
561 impl TryFrom<Value> for $t {
566 type Error = Error;
567
568 #[inline]
569 fn try_from(value: Value) -> Result<Self, Error> {
570 match value {
571 Value::$variant(x) => Ok(x),
572 other => Err(invalid_type(&other, $expected)),
573 }
574 }
575 }
576 )+};
577}
578
579tryfrom_value! {
580 Integer: Integer => "integer",
581 Vec<u8>: Bytes => "bytes",
582 f64: Float => "float",
583 String: Text => "text",
584 bool: Bool => "bool",
585 Vec<Value>: Array => "array",
586 Vec<(Value, Value)>: Map => "map",
587}
588
589impl TryFrom<Value> for char {
591 type Error = Error;
592
593 fn try_from(value: Value) -> Result<Self, Error> {
594 if let Value::Text(text) = &value {
595 let mut chars = text.chars();
596 if let (Some(c), None) = (chars.next(), chars.next()) {
597 return Ok(c);
598 }
599 }
600
601 Err(invalid_type(&value, "a single-character text"))
602 }
603}
604
605macro_rules! tryfrom_int {
606 ($($(#[$($attr:meta)+])? $t:ident)+) => {$(
607 $(#[$($attr)+])?
608 #[doc = concat!("Converts from a [`Value::Integer`] in `", stringify!($t), "` range.")]
609 impl TryFrom<Value> for $t {
610 type Error = Error;
611
612 #[inline]
613 fn try_from(value: Value) -> Result<Self, Error> {
614 match value {
615 Value::Integer(x) => $t::try_from(x).map_err(|_| {
616 Error::Custom(format!(
617 concat!(
618 "invalid value: integer `{}`, expected ",
619 stringify!($t),
620 ),
621 i128::from(x),
622 ))
623 }),
624 other => Err(invalid_type(&other, "integer")),
625 }
626 }
627 }
628 )+};
629}
630
631tryfrom_int! {
632 u8 u16 u32 u64
633 i8 i16 i32 i64
634
635 #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
636 usize
637
638 #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
639 isize
640}
641
642impl TryFrom<Value> for u128 {
646 type Error = Error;
647
648 #[inline]
649 fn try_from(value: Value) -> Result<Self, Error> {
650 value.deserialized()
651 }
652}
653
654impl TryFrom<Value> for i128 {
658 type Error = Error;
659
660 #[inline]
661 fn try_from(value: Value) -> Result<Self, Error> {
662 value.deserialized()
663 }
664}
665
666fn map_entries<K, V, M>(pairs: Vec<(Value, Value)>) -> Result<M, Error>
668where
669 K: TryFrom<Value>,
670 K::Error: core::fmt::Display,
671 V: TryFrom<Value>,
672 V::Error: core::fmt::Display,
673 M: FromIterator<(K, V)>,
674{
675 pairs
676 .into_iter()
677 .map(|(k, v)| {
678 Ok((
679 K::try_from(k).map_err(|err| Error::Custom(format!("invalid map key: {err}")))?,
680 V::try_from(v).map_err(|err| Error::Custom(format!("invalid map value: {err}")))?,
681 ))
682 })
683 .collect()
684}
685
686#[cfg(feature = "std")]
700impl<K, V> TryFrom<Value> for HashMap<K, V>
701where
702 K: TryFrom<Value> + Eq + core::hash::Hash,
703 K::Error: core::fmt::Display,
704 V: TryFrom<Value>,
705 V::Error: core::fmt::Display,
706{
707 type Error = Error;
708
709 fn try_from(value: Value) -> Result<Self, Error> {
710 match value {
711 Value::Map(pairs) => map_entries(pairs),
712 other => Err(invalid_type(&other, "map")),
713 }
714 }
715}
716
717impl<K, V> TryFrom<Value> for BTreeMap<K, V>
720where
721 K: TryFrom<Value> + Ord,
722 K::Error: core::fmt::Display,
723 V: TryFrom<Value>,
724 V::Error: core::fmt::Display,
725{
726 type Error = Error;
727
728 fn try_from(value: Value) -> Result<Self, Error> {
729 match value {
730 Value::Map(pairs) => map_entries(pairs),
731 other => Err(invalid_type(&other, "map")),
732 }
733 }
734}