webauthn_rs_device_catalog/
lib.rs1pub mod aaguid;
2pub mod certificate_authority;
3pub mod device;
4pub mod image;
5pub mod manufacturer;
6pub mod quirks;
7
8pub mod query;
9
10pub mod data;
11
12use std::fmt;
13
14use crate::device::*;
15use crate::query::Query;
16use std::rc::Rc;
17
18use webauthn_attestation_ca::AttestationCaList;
19
20pub mod prelude {
21 pub use crate::aaguid::Aaguid;
22 pub use crate::certificate_authority::Authority;
23 pub use crate::device::{Device, Sku};
24 pub use crate::manufacturer::Manufacturer;
25 pub use crate::query::Query;
26 pub use crate::{Data, DataBuilder};
27
28 pub(crate) use openssl::error::ErrorStack as OpenSSLErrorStack;
29 pub(crate) use openssl::x509;
30 pub(crate) use std::collections::BTreeSet;
31 pub(crate) use std::rc::Rc;
32}
33
34#[derive(Default)]
35pub struct DataBuilder {
36 devices: Vec<Rc<Device>>,
37}
38
39impl DataBuilder {
40 pub fn build(self) -> Data {
41 Data {
42 devices: self.devices,
43 }
44 }
45}
46
47pub struct Data {
48 devices: Vec<Rc<Device>>,
49}
50
51impl Default for Data {
52 fn default() -> Self {
53 Self::strict()
54 }
55}
56
57impl fmt::Display for Data {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 write!(f, "Data")
60 }
61}
62
63impl Data {
64 pub fn strict() -> Self {
68 DataBuilder::default().add_yubico().build()
69 }
70
71 pub fn all_known_devices() -> Self {
72 DataBuilder::default().add_yubico().build()
73 }
74
75 pub fn query(&self, query: &Query) -> Option<Data> {
76 tracing::debug!(?query);
77
78 let devices: Vec<_> = self
79 .devices
80 .iter()
81 .filter(|dev| dev.query_match(query))
82 .cloned()
84 .collect();
85
86 if devices.is_empty() {
87 None
88 } else {
89 Some(Data { devices })
90 }
91 }
92
93 pub fn iter(&self) -> impl Iterator<Item = &Device> {
94 self.devices.iter().map(|d| d.as_ref())
95 }
96}
97
98#[allow(clippy::from_over_into)]
100impl TryInto<AttestationCaList> for &Data {
101 type Error = crate::prelude::OpenSSLErrorStack;
102
103 fn try_into(self) -> Result<AttestationCaList, Self::Error> {
104 AttestationCaList::from_iter(self.devices.iter().flat_map(|dev| {
105 dev.aaguid
106 .ca
107 .iter()
108 .map(|ca| (ca.ca.clone(), dev.aaguid.id))
109 }))
110 }
111}
112
113#[cfg(test)]
114mod test {
115 use super::*;
116
117 #[test]
118 fn test_init_data() {
119 let data = Data::default();
120
121 println!("{data}");
122 for i in data.iter() {
123 println!("{0:?}", i);
124 }
125 }
126}