1use crate::{
4 DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag,
5 Writer, asn1::AnyRef, ord::OrdIsValueOrd,
6};
7
8const TRUE_OCTET: u8 = 0b11111111;
13
14const 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}