Skip to main content

cbor_core/
simple_value.rs

1use crate::{DataType, Error, Result};
2
3/// A CBOR simple value (major type 7, values 0-23 and 32-255).
4///
5/// In CBOR, booleans and null are not separate types but specific simple
6/// values: `false` is 20, `true` is 21, `null` is 22. The constants
7/// [`FALSE`](Self::FALSE), [`TRUE`](Self::TRUE), and [`NULL`](Self::NULL)
8/// are provided for these. Values 24-31 are reserved by the CBOR
9/// specification and cannot be constructed. Note that CBOR also defines
10/// `undefined` (simple value 23), but CBOR::Core does not give it any
11/// special treatment.
12#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[repr(transparent)]
14pub struct SimpleValue(pub(crate) u8);
15
16impl SimpleValue {
17    /// CBOR `false` (simple value 20).
18    pub const FALSE: Self = SimpleValue(20);
19    /// CBOR `true` (simple value 21).
20    pub const TRUE: Self = SimpleValue(21);
21    /// CBOR `null` (simple value 22).
22    pub const NULL: Self = SimpleValue(22);
23
24    /// Create a simple value from any type that implements `TryInto<SimpleValue>`.
25    ///
26    /// This is a convenience wrapper around `TryInto` that unwraps the result.
27    ///
28    /// # Panics
29    ///
30    /// Panics if `value` is in the reserved range 24-31. Use [`from_u8`](Self::from_u8)
31    /// for a fallible alternative.
32    pub fn new(value: impl TryInto<Self, Error = Error>) -> Self {
33        value.try_into().unwrap()
34    }
35
36    /// Create a simple value from a raw number.
37    ///
38    /// # Errors
39    ///
40    /// Returns [`Error::InvalidSimpleValue`] for values in the reserved
41    /// range 24-31.
42    pub const fn from_u8(value: u8) -> Result<Self> {
43        let valid_range = value <= 23 || value >= 32;
44        if valid_range {
45            Ok(Self(value))
46        } else {
47            Err(Error::InvalidSimpleValue)
48        }
49    }
50
51    #[inline]
52    #[must_use]
53    /// Create from a boolean.
54    pub const fn from_bool(value: bool) -> Self {
55        if value { Self::TRUE } else { Self::FALSE }
56    }
57
58    #[inline]
59    #[must_use]
60    /// Return the [`DataType`] of this simple value.
61    pub const fn data_type(&self) -> DataType {
62        match self.0 {
63            20 | 21 => DataType::Bool,
64            22 => DataType::Null,
65            _ => DataType::Simple,
66        }
67    }
68
69    /// Convert to `bool`.
70    ///
71    /// # Errors
72    ///
73    /// Returns [`Error::InvalidSimpleValue`] for non-boolean simple
74    /// values (anything other than [`Self::FALSE`] or [`Self::TRUE`]).
75    pub const fn to_bool(&self) -> Result<bool> {
76        match *self {
77            Self::FALSE => Ok(false),
78            Self::TRUE => Ok(true),
79            _ => Err(Error::InvalidSimpleValue),
80        }
81    }
82
83    /// Return the raw simple value number.
84    #[must_use]
85    pub const fn to_u8(&self) -> u8 {
86        self.0
87    }
88}
89
90impl TryFrom<u8> for SimpleValue {
91    type Error = Error;
92
93    #[inline]
94    fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
95        Self::from_u8(value)
96    }
97}
98
99impl From<SimpleValue> for u8 {
100    #[inline]
101    fn from(value: SimpleValue) -> Self {
102        value.to_u8()
103    }
104}
105
106impl From<bool> for SimpleValue {
107    #[inline]
108    fn from(value: bool) -> Self {
109        Self::from_bool(value)
110    }
111}
112
113impl TryFrom<SimpleValue> for bool {
114    type Error = Error;
115
116    fn try_from(value: SimpleValue) -> std::result::Result<Self, Self::Error> {
117        value.to_bool()
118    }
119}
120
121impl From<()> for SimpleValue {
122    #[inline]
123    fn from(_: ()) -> Self {
124        Self::NULL
125    }
126}