| // Copyright 2023 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| //! Definitions of traits for structures which supply |
| //! credentials for discovering advertisements/advertisement |
| //! sections for a _particular_ protocol version. |
| |
| use crate::credential::{ |
| DiscoveryCryptoMaterial, MatchableCredential, MatchedCredential, ProtocolVersion, |
| ReferencedMatchedCredential, |
| }; |
| use core::borrow::Borrow; |
| |
| /// Specialized version of the [`CredentialSource`] trait for |
| /// credential-sources which provide discovery credentials |
| /// for a specific protocol version. |
| /// |
| /// If you want ready-made structures which can provide |
| /// credentials for both V0 and V1 protocol versions, |
| /// see [`crate::credential::book::CredentialBook`] |
| /// and [`crate::credential::book::CredentialBookBuilder`] instead. |
| /// |
| /// It's preferred to use this kind of credential-source |
| /// in client code, if possible, and then lift to a |
| /// [`CredentialSource`] using [`AsCredentialSource`] |
| /// instead of implementing [`CredentialSource`] directly, |
| /// since it's better to trust this crate to handle |
| /// the details of what's in [`DiscoveryCryptoMaterial`]s |
| /// for specific protocol versions. |
| pub trait DiscoveryCredentialSource<'a, V: ProtocolVersion> |
| where |
| Self: 'a, |
| { |
| /// The kind of data yielded to the caller upon a successful |
| /// identity-match. |
| type Matched: MatchedCredential; |
| |
| /// The kind of crypto-material yielded from the wrapped |
| /// iterator, which allows borrowing a discovery credential. |
| type Crypto: DiscoveryCryptoMaterial<V> + Borrow<V::DiscoveryCredential>; |
| |
| /// The iterator type produced which emits credentials. |
| /// This is a lending iterator which may borrow things from `self`. |
| type Iterator: Iterator<Item = (Self::Crypto, Self::Matched)>; |
| |
| /// Iterate over the available credentials |
| fn iter(&'a self) -> Self::Iterator; |
| } |
| |
| /// A source of credentials for a particular protocol version, |
| /// utilizing any [`DiscoveryCryptoMaterial`] which is usable |
| /// for discovering advertisements in that protocol version. |
| /// |
| /// This trait is largely leveraged as a tool for building |
| /// new kinds of [`crate::credential::book::CredentialBook`]s |
| /// via the [`crate::credential::book::CredentialBookFromSources`] |
| /// wrapper. It differs from the [`DiscoveryCredentialSource`] |
| /// trait in that the crypto-materials do not have to be |
| /// discovery credentials, and can instead be some pre-calculated |
| /// crypto-materials. |
| /// |
| /// See [`crate::credential::book::CachedCredentialSource`] |
| /// for an example of this pattern. |
| pub trait CredentialSource<'a, V: ProtocolVersion> |
| where |
| Self: 'a, |
| { |
| /// The kind of data yielded to the caller upon a successful |
| /// identity-match. |
| type Matched: MatchedCredential; |
| |
| /// The kind of crypto-material yielded from the wrapped |
| /// iterator. |
| type Crypto: DiscoveryCryptoMaterial<V>; |
| |
| /// The iterator type produced which emits credentials. |
| /// This is a lending iterator which may borrow things from `self`. |
| type Iterator: Iterator<Item = (Self::Crypto, Self::Matched)>; |
| |
| /// Iterate over the available credentials |
| fn iter(&'a self) -> Self::Iterator; |
| } |
| |
| // Note: This is needed to get around coherence problems |
| // with the [`CredentialSource`] trait's relationship |
| // with [`DiscoveryCredentialSource`] if it were declared |
| // as a sub-trait (i.e: conflicting impls) |
| /// Wrapper which turns any [`DiscoveryCredentialSource`] |
| /// into a [`CredentialSource`]. |
| pub struct AsCredentialSource<S>(pub S); |
| |
| impl<'a, V: ProtocolVersion, S: DiscoveryCredentialSource<'a, V>> CredentialSource<'a, V> |
| for AsCredentialSource<S> |
| { |
| type Matched = <S as DiscoveryCredentialSource<'a, V>>::Matched; |
| type Crypto = <S as DiscoveryCredentialSource<'a, V>>::Crypto; |
| type Iterator = <S as DiscoveryCredentialSource<'a, V>>::Iterator; |
| |
| fn iter(&'a self) -> Self::Iterator { |
| self.0.iter() |
| } |
| } |
| |
| /// A simple [`DiscoveryCredentialSource`] which iterates over a provided slice of credentials |
| pub struct SliceCredentialSource<'c, V: ProtocolVersion, M: MatchedCredential> { |
| credentials: &'c [MatchableCredential<V, M>], |
| } |
| |
| impl<'c, V: ProtocolVersion, M: MatchedCredential> SliceCredentialSource<'c, V, M> { |
| /// Construct the credential supplier from the provided slice of credentials. |
| pub fn new(credentials: &'c [MatchableCredential<V, M>]) -> Self { |
| Self { credentials } |
| } |
| } |
| |
| impl<'a, 'b, V: ProtocolVersion, M: MatchedCredential> DiscoveryCredentialSource<'a, V> |
| for SliceCredentialSource<'b, V, M> |
| where |
| 'b: 'a, |
| Self: 'b, |
| &'a <V as ProtocolVersion>::DiscoveryCredential: DiscoveryCryptoMaterial<V>, |
| { |
| type Matched = ReferencedMatchedCredential<'a, M>; |
| type Crypto = &'a V::DiscoveryCredential; |
| type Iterator = core::iter::Map< |
| core::slice::Iter<'a, MatchableCredential<V, M>>, |
| fn( |
| &'a MatchableCredential<V, M>, |
| ) -> (&'a V::DiscoveryCredential, ReferencedMatchedCredential<M>), |
| >; |
| |
| fn iter(&'a self) -> Self::Iterator { |
| self.credentials.iter().map(MatchableCredential::<V, M>::as_pair) |
| } |
| } |