bc_envelope/base/
leaf.rs

1//! Provides methods for working with envelope leaf nodes,
2//! which are dCBOR values of any kind.
3
4use dcbor::prelude::*;
5
6#[cfg(feature = "known_value")]
7use super::envelope::EnvelopeCase;
8use crate::{Envelope, Result};
9#[cfg(feature = "known_value")]
10use crate::{Error, extension::KnownValue};
11
12impl Envelope {
13    pub fn r#false() -> Self { Self::new_leaf(false) }
14
15    pub fn r#true() -> Self { Self::new_leaf(true) }
16
17    pub fn is_false(&self) -> bool {
18        self.extract_subject().ok() == Some(false)
19    }
20
21    pub fn is_true(&self) -> bool { self.extract_subject().ok() == Some(true) }
22
23    pub fn is_bool(&self) -> bool {
24        matches!(
25            self.extract_subject(),
26            Ok(dcbor::Simple::True | dcbor::Simple::False)
27        )
28    }
29}
30
31impl Envelope {
32    /// `true` if the envelope is a leaf node that contains a number, `false`
33    pub fn is_number(&self) -> bool {
34        self.as_leaf().map(|c| c.is_number()).unwrap_or(false)
35    }
36
37    /// `true` if the subject of the envelope is a number, `false`
38    /// otherwise.
39    pub fn is_subject_number(&self) -> bool { self.subject().is_number() }
40
41    /// `true` if the envelope is a leaf node that contains the NaN value,
42    /// `false` otherwise.
43    pub fn is_nan(&self) -> bool {
44        self.as_leaf().map(|c| c.is_nan()).unwrap_or(false)
45    }
46
47    /// `true` if the subject of the envelope is the NaN value, `false`
48    /// otherwise.
49    pub fn is_subject_nan(&self) -> bool { self.subject().is_nan() }
50}
51
52impl Envelope {
53    pub fn null() -> Self { Self::new_leaf(dcbor::Simple::Null) }
54
55    pub fn is_null(&self) -> bool {
56        self.extract_subject().ok() == Some(dcbor::Simple::Null)
57    }
58}
59
60impl Envelope {
61    /// The envelope's leaf CBOR object as a CBOR byte string, or an error if
62    /// the envelope is not a leaf, or the leaf is not a byte string.
63    pub fn try_byte_string(&self) -> Result<Vec<u8>> {
64        Ok(self.try_leaf()?.try_into_byte_string()?)
65    }
66
67    pub fn as_byte_string(&self) -> Option<Vec<u8>> {
68        self.as_leaf().and_then(|c| c.into_byte_string())
69    }
70}
71
72impl Envelope {
73    pub fn as_array(&self) -> Option<Vec<CBOR>> {
74        self.as_leaf().and_then(|c| c.into_array())
75    }
76
77    pub fn as_map(&self) -> Option<dcbor::Map> {
78        self.as_leaf().and_then(|c| c.into_map())
79    }
80
81    pub fn as_text(&self) -> Option<String> {
82        self.as_leaf().and_then(|c| c.into_text())
83    }
84}
85
86#[cfg(feature = "known_value")]
87impl Envelope {
88    /// The envelope's `KnownValue`, or `None` if the envelope is not case
89    /// `::KnownValue`.
90    pub fn as_known_value(&self) -> Option<&KnownValue> {
91        match self.case() {
92            EnvelopeCase::KnownValue { value, .. } => Some(value),
93            _ => None,
94        }
95    }
96
97    /// The envelope's `KnownValue`, or an error if the envelope is not case
98    /// `::KnownValue`.
99    pub fn try_known_value(&self) -> Result<&KnownValue> {
100        self.as_known_value().ok_or(Error::NotKnownValue)
101    }
102
103    /// `true` if the envelope is case `::KnownValue`, `false` otherwise.
104    pub fn is_known_value(&self) -> bool {
105        matches!(self.case(), EnvelopeCase::KnownValue { .. })
106    }
107
108    /// Constructs a unit envelope.
109    ///
110    /// Unit envelopes have the known value `''`. They represent a position
111    /// where no meaningful data *can* exist. In this sense they make a
112    /// semantically stronger assertion than `null`, which represent a
113    /// position where no meaningful data currently exists, but could exist in
114    /// the future.
115    pub fn unit() -> Self { Self::new_leaf(known_values::UNIT) }
116
117    /// `true` if the subject of the envelope is the unit value, `false`
118    /// otherwise.
119    pub fn is_subject_unit(&self) -> bool {
120        self.extract_subject().ok() == Some(known_values::UNIT)
121    }
122
123    /// Checks that the subject of the envelope is the unit value.
124    ///
125    /// Returns `Ok(&self)` if so, or an error otherwise.
126    pub fn check_subject_unit(&self) -> Result<&Self> {
127        if self.is_subject_unit() {
128            Ok(self)
129        } else {
130            Err(Error::SubjectNotUnit)
131        }
132    }
133}