Skip to main content

der/asn1/
boolean.rs

1//! ASN.1 `BOOLEAN` support.
2
3use crate::{
4    DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag,
5    Writer, asn1::AnyRef, ord::OrdIsValueOrd,
6};
7
8/// Byte used to encode `true` in ASN.1 DER. From X.690 Section 11.1:
9///
10/// > If the encoding represents the boolean value TRUE, its single contents
11/// > octet shall have all eight bits set to one.
12const TRUE_OCTET: u8 = 0b11111111;
13
14/// Byte used to encode `false` in ASN.1 DER.
15const FALSE_OCTET: u8 = 0b00000000;
16
17impl<'a> DecodeValue<'a> for bool {
18    type Error = Error;
19
20    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
21        if header.length() != Length::ONE {
22            return Err(reader.error(ErrorKind::Length { tag: Self::TAG }));
23        }
24
25        match reader.read_byte()? {
26            FALSE_OCTET => Ok(false),
27            TRUE_OCTET => Ok(true),
28            _ => Err(reader.error(Self::TAG.non_canonical_error())),
29        }
30    }
31}
32
33impl EncodeValue for bool {
34    fn value_len(&self) -> Result<Length> {
35        Ok(Length::ONE)
36    }
37
38    fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
39        writer.write_byte(if *self { TRUE_OCTET } else { FALSE_OCTET })
40    }
41}
42
43impl FixedTag for bool {
44    const TAG: Tag = Tag::Boolean;
45}
46
47impl OrdIsValueOrd for bool {}
48
49impl TryFrom<AnyRef<'_>> for bool {
50    type Error = Error;
51
52    fn try_from(any: AnyRef<'_>) -> Result<bool> {
53        any.try_into()
54    }
55}
56
57#[cfg(test)]
58#[allow(clippy::unwrap_used, clippy::bool_assert_comparison)]
59mod tests {
60    use crate::{Decode, Encode};
61
62    #[test]
63    fn decode() {
64        assert_eq!(true, bool::from_der(&[0x01, 0x01, 0xFF]).unwrap());
65        assert_eq!(false, bool::from_der(&[0x01, 0x01, 0x00]).unwrap());
66    }
67
68    #[test]
69    fn encode() {
70        let mut buffer = [0u8; 3];
71        assert_eq!(
72            &[0x01, 0x01, 0xFF],
73            true.encode_to_slice(&mut buffer).unwrap()
74        );
75        assert_eq!(
76            &[0x01, 0x01, 0x00],
77            false.encode_to_slice(&mut buffer).unwrap()
78        );
79    }
80
81    #[test]
82    fn reject_non_canonical() {
83        assert!(bool::from_der(&[0x01, 0x01, 0x01]).is_err());
84    }
85}