Skip to content

Commit

Permalink
Rename bitstream_status_list module into bitstring_status_list. (#…
Browse files Browse the repository at this point in the history
…573)

* Remove `BitstringStatusListType`.
* Remove `BitstringStatusListEntryType`.
* Make `BitstringStatusListEntry` fields public.
* Add constructor for `BitstringStatusListEntry`.
* Add constructors and accessors for `bitstring_status_list::StatusPurpose`.
* Impl `Display` for `bitstring_status_list::StatusPurpose`.
  • Loading branch information
timothee-haudebourg authored Jul 8, 2024
1 parent 72d6ce2 commit 90d11cb
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 92 deletions.
16 changes: 8 additions & 8 deletions crates/status/examples/status_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use ssi_data_integrity::{AnySuite, ProofOptions};
use ssi_dids::{VerificationMethodDIDResolver, DIDJWK};
use ssi_jwk::JWK;
use ssi_status::{
any::AnyStatusMap, bitstream_status_list, EncodedStatusMap, FromBytes, FromBytesOptions,
any::AnyStatusMap, bitstring_status_list, EncodedStatusMap, FromBytes, FromBytesOptions,
};
use ssi_verification_methods::{ReferenceOrOwned, SingleSecretSigner};
use std::{
Expand Down Expand Up @@ -139,34 +139,34 @@ impl Command {
Ok(())
}
Self::Create { id, list, key } => {
let data = create_bitstream_status_list(id.clone(), list, key).await?;
let data = create_bitstring_status_list(id.clone(), list, key).await?;
stdout().write_all(&data).unwrap();
Ok(())
}
}
}
}

async fn create_bitstream_status_list(
async fn create_bitstring_status_list(
id: UriBuf,
list: Vec<StatusValue>,
key: Option<PathBuf>,
) -> Result<Vec<u8>, Error> {
let mut status_list = bitstream_status_list::StatusList::new(
bitstream_status_list::StatusSize::default(),
bitstream_status_list::TimeToLive::default(),
let mut status_list = bitstring_status_list::StatusList::new(
bitstring_status_list::StatusSize::default(),
bitstring_status_list::TimeToLive::default(),
// list.into_iter().map(|v| v.0).collect(),
);

for v in list {
status_list.push(v.0).unwrap();
}

let credential = bitstream_status_list::BitstringStatusListCredential::new(
let credential = bitstring_status_list::BitstringStatusListCredential::new(
Some(id),
status_list.to_credential_subject(
None,
bitstream_status_list::StatusPurpose::Revocation,
bitstring_status_list::StatusPurpose::Revocation,
Vec::new(),
),
);
Expand Down
14 changes: 7 additions & 7 deletions crates/status/src/impl/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ssi_jwk::JWKResolver;
use ssi_verification_methods::{AnyMethod, VerificationMethodResolver};

use crate::{
bitstream_status_list::{
bitstring_status_list::{
self, BitstringStatusListCredential, BitstringStatusListEntry,
BitstringStatusListEntrySetCredential,
},
Expand Down Expand Up @@ -34,7 +34,7 @@ pub enum FromBytesError {
UnexpectedMediaType(String),

#[error(transparent)]
BitstringStatusList(bitstream_status_list::FromBytesError),
BitstringStatusList(bitstring_status_list::FromBytesError),

#[error(transparent)]
TokenStatusList(token_status_list::FromBytesError),
Expand Down Expand Up @@ -77,7 +77,7 @@ where
#[derive(Debug, thiserror::Error)]
pub enum DecodeError {
#[error(transparent)]
BitstringStatusList(#[from] bitstream_status_list::DecodeError),
BitstringStatusList(#[from] bitstring_status_list::DecodeError),

#[error(transparent)]
TokenStatusList(#[from] token_status_list::DecodeError),
Expand All @@ -103,7 +103,7 @@ impl EncodedStatusMap for AnyStatusMap {

#[derive(Clone)]
pub enum AnyDecodedStatusMap {
BitstringStatusList(bitstream_status_list::StatusList),
BitstringStatusList(bitstring_status_list::StatusList),
TokenStatusList(token_status_list::StatusList),
}

Expand Down Expand Up @@ -145,7 +145,7 @@ impl<'a> IntoIterator for &'a AnyDecodedStatusMap {
}

pub enum AnyDecodedStatusMapIter<'a> {
BitstringStatusList(bitstream_status_list::BitStringIter<'a>),
BitstringStatusList(bitstring_status_list::BitStringIter<'a>),
TokenStatusList(token_status_list::BitStringIter<'a>),
}

Expand All @@ -166,7 +166,7 @@ pub enum EntrySetFromBytesError {
TokenStatusList(#[from] token_status_list::EntrySetFromBytesError),

#[error(transparent)]
BitstringStatusList(#[from] bitstream_status_list::FromBytesError),
BitstringStatusList(#[from] bitstring_status_list::FromBytesError),

#[error("unexpected media type `{0}`")]
UnexpectedMediaType(String),
Expand Down Expand Up @@ -203,7 +203,7 @@ where
| "application/vc+ld+json+sd-jwt"
| "application/vc+ld+json+cose"
| "application/vc+ld+json" => {
bitstream_status_list::BitstringStatusListEntrySetCredential::from_bytes_with(
bitstring_status_list::BitstringStatusListEntrySetCredential::from_bytes_with(
bytes, media_type, params, options,
)
.await
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
//! Credentials through use of bitstrings.
//!
//! See: <https://www.w3.org/TR/vc-bitstring-status-list/>
use core::fmt;
use iref::UriBuf;
use serde::{Deserialize, Serialize};
use std::{hash::Hash, time::Duration};
use std::{hash::Hash, str::FromStr, time::Duration};

use crate::{Overflow, StatusMap};

Expand Down Expand Up @@ -127,7 +128,7 @@ impl From<TimeToLive> for Duration {
}
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum StatusPurpose {
/// Cancel the validity of a verifiable credential.
Expand All @@ -142,9 +143,54 @@ pub enum StatusPurpose {

/// Convey an arbitrary message related to the status of the verifiable
/// credential.
///
/// The actual message is stored in the status list credential, in
/// [`BitstringStatusList::status_message`].
Message,
}

impl StatusPurpose {
/// Creates a new status purpose from its name.
pub fn from_name(name: &str) -> Option<Self> {
match name {
"revocation" => Some(Self::Revocation),
"suspension" => Some(Self::Suspension),
"message" => Some(Self::Message),
_ => None,
}
}

/// Returns the name of this status purpose.
pub fn name(&self) -> &'static str {
match self {
Self::Revocation => "revocation",
Self::Suspension => "suspension",
Self::Message => "message",
}
}

/// Returns the string representation of this status purpose.
///
/// Same as [`Self::name`].
pub fn as_str(&self) -> &'static str {
self.name()
}

/// Turns this status purpose into its name.
///
/// Same as [`Self::name`].
pub fn into_name(self) -> &'static str {
self.name()
}

/// Turns this status purpose into its string representation.
///
/// Same as [`Self::name`].
pub fn into_str(self) -> &'static str {
self.name()
}
}

impl<'a> From<&'a StatusPurpose> for crate::StatusPurpose<&'a str> {
fn from(value: &'a StatusPurpose) -> Self {
match value {
Expand All @@ -166,6 +212,25 @@ impl<'a> PartialEq<crate::StatusPurpose<&'a str>> for StatusPurpose {
}
}

impl fmt::Display for StatusPurpose {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.name().fmt(f)
}
}

/// Error raised when converting a string into a [`StatusPurpose`] fails.
#[derive(Debug, Clone, thiserror::Error)]
#[error("invalid status purpose: {0}")]
pub struct InvalidStatusPurpose(pub String);

impl FromStr for StatusPurpose {
type Err = InvalidStatusPurpose;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from_name(s).ok_or_else(|| InvalidStatusPurpose(s.to_owned()))
}
}

/// Bit-string as defined by the W3C Bitstring Status List specification.
///
/// Bits are indexed from most significant to least significant.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use ssi_vc::v2::{syntax::JsonCredentialTypes, Context};
use ssi_verification_methods::{ssi_core::OneOrMany, AnyMethod, VerificationMethodResolver};

use crate::{
bitstream_status_list::FromBytesError, FromBytes, FromBytesOptions, StatusMapEntrySet,
bitstring_status_list::FromBytesError, FromBytes, FromBytesOptions, StatusMapEntrySet,
};

use super::BitstringStatusListEntry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
mod credential;
pub use credential::*;

use crate::{bitstream_status_list::StatusPurpose, StatusMapEntry};
use crate::{bitstring_status_list::StatusPurpose, StatusMapEntry};

pub const BITSTRING_STATUS_LIST_ENTRY_TYPE: &str = "BitstringStatusListEntry";

Expand All @@ -16,28 +16,41 @@ pub const BITSTRING_STATUS_LIST_ENTRY_TYPE: &str = "BitstringStatusListEntry";
///
/// See: <https://www.w3.org/TR/vc-bitstring-status-list/#bitstringstatuslistentry>
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "type", rename_all = "camelCase")]
pub struct BitstringStatusListEntry {
/// Optional identifier for the status list entry.
///
/// Identifies the status information associated with the verifiable
/// credential. Must *not* be the URL of the status list.
id: Option<UriBuf>,

/// `BitstringStatusListEntry` type.
#[serde(rename = "type")]
type_: BitstringStatusListEntryType,
pub id: Option<UriBuf>,

/// Purpose of the status entry.
status_purpose: StatusPurpose,
pub status_purpose: StatusPurpose,

/// URL to a `BitstringStatusListCredential` verifiable credential.
status_list_credential: UriBuf,
pub status_list_credential: UriBuf,

/// Arbitrary size integer greater than or equal to 0, encoded as a string
/// in base 10.
#[serde(with = "base10_nat_string")]
status_list_index: usize,
pub status_list_index: usize,
}

impl BitstringStatusListEntry {
/// Creates a new bit-string status list entry.
pub fn new(
id: Option<UriBuf>,
status_purpose: StatusPurpose,
status_list_credential: UriBuf,
status_list_index: usize,
) -> Self {
Self {
id,
status_purpose,
status_list_credential,
status_list_index,
}
}
}

impl StatusMapEntry for BitstringStatusListEntry {
Expand All @@ -52,34 +65,6 @@ impl StatusMapEntry for BitstringStatusListEntry {
}
}

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BitstringStatusListEntryType;

impl Serialize for BitstringStatusListEntryType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
BITSTRING_STATUS_LIST_ENTRY_TYPE.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for BitstringStatusListEntryType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let type_ = String::deserialize(deserializer)?;
if type_ == BITSTRING_STATUS_LIST_ENTRY_TYPE {
Ok(Self)
} else {
Err(serde::de::Error::custom(
"expected `BitstringStatusListEntry` type",
))
}
}
}

mod base10_nat_string {
use serde::{Deserialize, Deserializer, Serialize, Serializer};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,18 @@ use serde::{Deserialize, Serialize};
mod credential;
pub use credential::*;

use crate::bitstream_status_list::{
use crate::bitstring_status_list::{
EncodedList, StatusList, StatusMessage, StatusPurpose, StatusSize, TimeToLive,
};

pub const BITSTRING_STATUS_LIST_TYPE: &str = "BitstringStatusList";

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "type", rename_all = "camelCase")]
pub struct BitstringStatusList {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub id: Option<UriBuf>,

/// `BitstringStatusList` type.
#[serde(rename = "type")]
pub type_: BitstringStatusListType,

/// Status purpose.
pub status_purpose: StatusPurpose,

Expand Down Expand Up @@ -52,7 +48,6 @@ impl BitstringStatusList {
) -> Self {
Self {
id,
type_: BitstringStatusListType,
status_purpose,
status_size,
encoded_list,
Expand All @@ -67,31 +62,3 @@ impl BitstringStatusList {
Ok(StatusList::from_bytes(self.status_size, bytes, self.ttl))
}
}

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BitstringStatusListType;

impl Serialize for BitstringStatusListType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
BITSTRING_STATUS_LIST_TYPE.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for BitstringStatusListType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let type_ = String::deserialize(deserializer)?;
if type_ == BITSTRING_STATUS_LIST_TYPE {
Ok(Self)
} else {
Err(serde::de::Error::custom(
"expected `BitstringStatusList` type",
))
}
}
}
2 changes: 1 addition & 1 deletion crates/status/src/impl/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod any;
pub mod bitstream_status_list;
pub mod bitstring_status_list;
pub mod token_status_list;

pub use flate2::Compression;
Expand Down

0 comments on commit 90d11cb

Please sign in to comment.