der/asn1/
boolean.rs

1//! ASN.1 `BOOLEAN` support.
2
3use crate::{
4    asn1::AnyRef, ord::OrdIsValueOrd, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header,
5    Length, Reader, Result, Tag, Writer,
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    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
19        if header.length != Length::ONE {
20            return Err(reader.error(ErrorKind::Length { tag: Self::TAG }));
21        }
22
23        match reader.read_byte()? {
24            FALSE_OCTET => Ok(false),
25            TRUE_OCTET => Ok(true),
26            _ => Err(Self::TAG.non_canonical_error()),
27        }
28    }
29}
30
31impl EncodeValue for bool {
32    fn value_len(&self) -> Result<Length> {
33        Ok(Length::ONE)
34    }
35
36    fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
37        writer.write_byte(if *self { TRUE_OCTET } else { FALSE_OCTET })
38    }
39}
40
41impl FixedTag for bool {
42    const TAG: Tag = Tag::Boolean;
43}
44
45impl OrdIsValueOrd for bool {}
46
47impl TryFrom<AnyRef<'_>> for bool {
48    type Error = Error;
49
50    fn try_from(any: AnyRef<'_>) -> Result<bool> {
51        any.try_into()
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use crate::{Decode, Encode};
58
59    #[test]
60    fn decode() {
61        assert_eq!(true, bool::from_der(&[0x01, 0x01, 0xFF]).unwrap());
62        assert_eq!(false, bool::from_der(&[0x01, 0x01, 0x00]).unwrap());
63    }
64
65    #[test]
66    fn encode() {
67        let mut buffer = [0u8; 3];
68        assert_eq!(
69            &[0x01, 0x01, 0xFF],
70            true.encode_to_slice(&mut buffer).unwrap()
71        );
72        assert_eq!(
73            &[0x01, 0x01, 0x00],
74            false.encode_to_slice(&mut buffer).unwrap()
75        );
76    }
77
78    #[test]
79    fn reject_non_canonical() {
80        assert!(bool::from_der(&[0x01, 0x01, 0x01]).is_err());
81    }
82}