yubihsm/object/
filter.rs

1//! Filters for selecting objects in the list object command
2
3use crate::{algorithm::Algorithm, capability::Capability, client, domain::Domain, object};
4use std::io::Write;
5
6#[cfg(feature = "mockhsm")]
7use {
8    crate::{client::ErrorKind::ProtocolError, object::LABEL_SIZE},
9    std::io::Read,
10};
11
12/// Filters to apply when listing objects
13pub enum Filter {
14    /// Filter objects by algorithm
15    Algorithm(Algorithm),
16
17    /// Filter objects by capability
18    Capabilities(Capability),
19
20    /// Filter objects by domain
21    Domains(Domain),
22
23    /// Filter objects by label
24    Label(object::Label),
25
26    /// Filter by object ID
27    Id(object::Id),
28
29    /// Filter by object type
30    Type(object::Type),
31}
32
33#[cfg(feature = "mockhsm")]
34macro_rules! read_byte {
35    ($reader:expr) => {{
36        let mut byte = [0u8];
37        $reader.read_exact(&mut byte)?;
38        byte[0]
39    }};
40}
41
42#[cfg(feature = "mockhsm")]
43macro_rules! read_be_bytes {
44    ($reader:expr, $type:path) => {{
45        let mut bytes = [0u8; std::mem::size_of::<$type>()];
46        $reader.read_exact(&mut bytes)?;
47        <$type>::from_be_bytes(bytes)
48    }};
49}
50
51impl Filter {
52    /// Tag value for TLV serialization for this filter
53    pub fn tag(&self) -> u8 {
54        match *self {
55            Filter::Id(_) => 0x01,
56            Filter::Type(_) => 0x02,
57            Filter::Domains(_) => 0x03,
58            Filter::Capabilities(_) => 0x04,
59            Filter::Algorithm(_) => 0x05,
60            Filter::Label(_) => 0x06,
61        }
62    }
63
64    // TODO: replace this with serde
65    pub(crate) fn serialize<W: Write>(&self, mut writer: W) -> Result<W, client::Error> {
66        writer.write_all(&[self.tag()])?;
67
68        match *self {
69            Filter::Algorithm(alg) => writer.write_all(&[alg.to_u8()])?,
70            Filter::Capabilities(caps) => writer.write_all(&caps.bits().to_be_bytes())?,
71            Filter::Domains(doms) => writer.write_all(&doms.bits().to_be_bytes())?,
72            Filter::Label(ref label) => {
73                writer.write_all(label.as_ref())?;
74            }
75            Filter::Id(id) => writer.write_all(&id.to_be_bytes())?,
76            Filter::Type(ty) => writer.write_all(&[ty.to_u8()])?,
77        }
78
79        Ok(writer)
80    }
81
82    // TODO: replace this with serde
83    #[cfg(feature = "mockhsm")]
84    pub(crate) fn deserialize<R: Read>(mut reader: R) -> Result<Self, client::Error> {
85        let tag = read_byte!(reader);
86
87        Ok(match tag {
88            0x01 => Filter::Id(read_be_bytes!(reader, u16)),
89            0x02 => Filter::Type(
90                object::Type::from_u8(read_byte!(reader))
91                    .map_err(|e| format_err!(ProtocolError, e))?,
92            ),
93            0x03 => Filter::Domains(
94                Domain::from_bits(read_be_bytes!(reader, u16))
95                    .ok_or_else(|| format_err!(ProtocolError, "invalid domain bitflags"))?,
96            ),
97            0x04 => Filter::Capabilities(
98                Capability::from_bits(read_be_bytes!(reader, u64))
99                    .ok_or_else(|| format_err!(ProtocolError, "invalid capability bitflags"))?,
100            ),
101            0x05 => Filter::Algorithm(
102                Algorithm::from_u8(read_byte!(reader))
103                    .map_err(|e| format_err!(ProtocolError, e))?,
104            ),
105            0x06 => {
106                let mut label_bytes = [0u8; LABEL_SIZE];
107                reader.read_exact(&mut label_bytes)?;
108                Filter::Label(object::Label(label_bytes))
109            }
110            _ => fail!(ProtocolError, "invalid filter tag: 0x{:2x}", tag),
111        })
112    }
113}