ssi_status/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
use std::time::Duration;
mod r#impl;
use iref::Uri;
pub use r#impl::*;
pub mod client;
/// Encoded [`StatusMap`].
pub trait EncodedStatusMap {
type Decoded: StatusMap;
type DecodeError: std::error::Error;
fn decode(self) -> Result<Self::Decoded, Self::DecodeError>;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct FromBytesOptions {
/// Allow unsecured claims.
pub allow_unsecured: bool,
}
impl FromBytesOptions {
pub const ALLOW_UNSECURED: Self = Self {
allow_unsecured: true,
};
}
pub trait FromBytes<V>: Sized {
type Error: std::error::Error;
#[allow(async_fn_in_trait)]
async fn from_bytes_with(
bytes: &[u8],
media_type: &str,
verification_params: &V,
options: FromBytesOptions,
) -> Result<Self, Self::Error>;
#[allow(async_fn_in_trait)]
async fn from_bytes(bytes: &[u8], media_type: &str, verifier: &V) -> Result<Self, Self::Error> {
Self::from_bytes_with(bytes, media_type, verifier, FromBytesOptions::default()).await
}
}
#[derive(Debug, thiserror::Error)]
pub enum StatusSizeError {
#[error("missing status size")]
Missing,
#[error("invalid status size")]
Invalid,
}
/// Status map.
///
/// A status map is a map from [`StatusMapEntry`] to [`StatusMap::Status`].
/// The [`StatusMapEntry`] is generally found in the credential or claims you
/// need to verify.
pub trait StatusMap: Clone {
/// Key indexing each status in the map.
type Key;
/// Status bit size type.
type StatusSize;
/// Status type.
type Status;
/// Maximum duration an implementer is allowed to cache a
/// status list.
fn time_to_live(&self) -> Option<Duration> {
None
}
/// Returns a status using the given status size and key.
///
/// If `status_size` is `None`, it is assumed that the map itself knows the
/// status size. If it does not, a [`StatusSizeError::Missing`] error is
/// returned.
fn get_by_key(
&self,
status_size: Option<Self::StatusSize>,
key: Self::Key,
) -> Result<Option<Self::Status>, StatusSizeError>;
/// Returns the status associated to the given entry.
fn get_entry<E: StatusMapEntry<Key = Self::Key, StatusSize = Self::StatusSize>>(
&self,
entry: &E,
) -> Result<Option<Self::Status>, StatusSizeError> {
self.get_by_key(entry.status_size(), entry.key())
}
}
pub trait StatusMapEntrySet {
type Entry<'a>: StatusMapEntry
where
Self: 'a;
fn get_entry(&self, purpose: StatusPurpose<&str>) -> Option<Self::Entry<'_>>;
}
/// Status map entry.
///
/// A status map entry is a reference to a particular status in a status map.
/// It links to a status map, providing a key in this map.
pub trait StatusMapEntry {
/// Key indexing each status in the referenced status list.
type Key;
/// Status map status size type.
type StatusSize;
/// URL to the status map.
fn status_list_url(&self) -> &Uri;
/// Size of each status in the status map, if it is known by the entry.
///
/// For some [`StatusMap`] implementations such as
/// [`crate::token_status_list::StatusList`] the status size is stored in
/// the map, while for some other implementations such as
/// [`crate::bitstring_status_list::StatusList`] the status size is stored
/// in the entry
/// ([`crate::bitstring_status_list::BitstringStatusListEntry`]).
///
/// If this function returns `None`, it is assumed that the status size
/// will be provided by the status map.
fn status_size(&self) -> Option<Self::StatusSize>;
/// Entry key.
fn key(&self) -> Self::Key;
}
impl<'a, E: StatusMapEntry> StatusMapEntry for &'a E {
type Key = E::Key;
type StatusSize = E::StatusSize;
fn status_list_url(&self) -> &Uri {
E::status_list_url(*self)
}
fn status_size(&self) -> Option<Self::StatusSize> {
E::status_size(*self)
}
fn key(&self) -> Self::Key {
E::key(*self)
}
}
pub enum StatusPurpose<T = String> {
/// Cancel the validity of a verifiable credential.
///
/// This status is not reversible.
Revocation,
/// Temporarily prevent the acceptance of a verifiable credential.
///
/// This status is reversible.
Suspension,
/// Other purpose whose semantics is not supported by `ssi-status`.
Other(T),
}