blob: 709bbd654f55d1e6a16546d8176faa5aa68976ef [file] [log] [blame]
// 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)
}
}