Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions crates/claims/crates/vc-jose-cose/src/cose/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ssi_cose::{CosePayload, CoseSign1Bytes, CoseSigner, DecodedCoseSign1, Valida
use ssi_json_ld::{iref::Uri, syntax::Context};
use ssi_vc::{
enveloped::EnvelopedVerifiableCredential,
v2::{Credential, CredentialTypes, JsonCredential},
v2::{AnyInternationalString, Credential, CredentialTypes, JsonCredential},
MaybeIdentified,
};
use std::borrow::Cow;
Expand Down Expand Up @@ -90,7 +90,6 @@ impl<T: MaybeIdentified> MaybeIdentified for CoseVc<T> {
}

impl<T: Credential> Credential for CoseVc<T> {
type Description = T::Description;
type Subject = T::Subject;
type Issuer = T::Issuer;
type Status = T::Status;
Expand All @@ -112,11 +111,11 @@ impl<T: Credential> Credential for CoseVc<T> {
self.0.types()
}

fn name(&self) -> Option<&str> {
fn name(&self) -> Option<impl AnyInternationalString> {
self.0.name()
}

fn description(&self) -> Option<&Self::Description> {
fn description(&self) -> Option<impl AnyInternationalString> {
self.0.description()
}

Expand Down
7 changes: 3 additions & 4 deletions crates/claims/crates/vc-jose-cose/src/jose/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ssi_json_ld::{iref::Uri, syntax::Context};
use ssi_jws::{DecodedJws, JwsPayload, JwsSigner, JwsSlice, ValidateJwsHeader};
use ssi_vc::{
enveloped::EnvelopedVerifiableCredential,
v2::{Credential, CredentialTypes, JsonCredential},
v2::{AnyInternationalString, Credential, CredentialTypes, JsonCredential},
MaybeIdentified,
};
use std::borrow::Cow;
Expand Down Expand Up @@ -74,7 +74,6 @@ impl<T: MaybeIdentified> MaybeIdentified for JoseVc<T> {
}

impl<T: Credential> Credential for JoseVc<T> {
type Description = T::Description;
type Subject = T::Subject;
type Issuer = T::Issuer;
type Status = T::Status;
Expand All @@ -96,11 +95,11 @@ impl<T: Credential> Credential for JoseVc<T> {
self.0.types()
}

fn name(&self) -> Option<&str> {
fn name(&self) -> Option<impl AnyInternationalString> {
self.0.name()
}

fn description(&self) -> Option<&Self::Description> {
fn description(&self) -> Option<impl AnyInternationalString> {
self.0.description()
}

Expand Down
7 changes: 3 additions & 4 deletions crates/claims/crates/vc-jose-cose/src/sd_jwt/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use ssi_jwt::{ClaimSet, InfallibleClaimSet, JWTClaims};
use ssi_sd_jwt::{JsonPointer, RevealError, RevealedSdJwt, SdAlg, SdJwt, SdJwtBuf};
use ssi_vc::{
enveloped::EnvelopedVerifiableCredential,
v2::{Credential, CredentialTypes, JsonCredential},
v2::{AnyInternationalString, Credential, CredentialTypes, JsonCredential},
MaybeIdentified,
};
use xsd_types::DateTimeStamp;
Expand Down Expand Up @@ -139,7 +139,6 @@ impl<T: MaybeIdentified> MaybeIdentified for SdJwtVc<T> {
}

impl<T: Credential> Credential for SdJwtVc<T> {
type Description = T::Description;
type Subject = T::Subject;
type Issuer = T::Issuer;
type Status = T::Status;
Expand All @@ -161,11 +160,11 @@ impl<T: Credential> Credential for SdJwtVc<T> {
self.0.types()
}

fn name(&self) -> Option<&str> {
fn name(&self) -> Option<impl AnyInternationalString> {
self.0.name()
}

fn description(&self) -> Option<&Self::Description> {
fn description(&self) -> Option<impl AnyInternationalString> {
self.0.description()
}

Expand Down
9 changes: 0 additions & 9 deletions crates/claims/crates/vc/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,3 @@ impl Identified for IdentifiedTypedObject {
&self.id
}
}

impl Identified for IdOr<IdentifiedObject> {
fn id(&self) -> &Uri {
match self {
Self::Id(id) => id,
Self::NotId(o) => &o.id,
}
}
}
6 changes: 6 additions & 0 deletions crates/claims/crates/vc/src/syntax/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ impl<T: Identified> IdOr<T> {
}
}

impl<T: Identified> Identified for IdOr<T> {
fn id(&self) -> &Uri {
self.id()
}
}

impl<T> From<UriBuf> for IdOr<T> {
fn from(value: UriBuf) -> Self {
Self::Id(value)
Expand Down
13 changes: 5 additions & 8 deletions crates/claims/crates/vc/src/v2/data_model/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ use iref::Uri;
use ssi_claims_core::{ClaimsValidity, DateTimeProvider, InvalidClaims};
use xsd_types::DateTimeStamp;

use super::{InternationalString, RelatedResource};
use super::{AnyInternationalString, RelatedResource};

pub use crate::v1::CredentialTypes;
use crate::{Identified, MaybeIdentified, Typed};

/// Verifiable Credential.
pub trait Credential: MaybeIdentified {
/// Description type.
type Description: InternationalString;

/// Credential subject type.
type Subject;

Expand Down Expand Up @@ -72,8 +69,8 @@ pub trait Credential: MaybeIdentified {
/// other credentials that they might hold.
///
/// See: <https://www.w3.org/TR/vc-data-model-2.0/#names-and-descriptions>
fn name(&self) -> Option<&str> {
None
fn name(&self) -> Option<impl AnyInternationalString> {
Option::<String>::None
}

/// Details about the credential.
Expand All @@ -84,8 +81,8 @@ pub trait Credential: MaybeIdentified {
/// entirety of the claims.
///
/// See: <https://www.w3.org/TR/vc-data-model-2.0/#names-and-descriptions>
fn description(&self) -> Option<&Self::Description> {
None
fn description(&self) -> Option<impl AnyInternationalString> {
Option::<String>::None
}

/// Credential subject.
Expand Down
46 changes: 38 additions & 8 deletions crates/claims/crates/vc/src/v2/data_model/language.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,57 @@
use ssi_json_ld::{syntax::LangTag, Direction, LangString, LenientLangTag};

pub struct LanguageValue<'a> {
pub struct LanguageValueRef<'a> {
pub value: &'a str,
pub language: Option<&'a LangTag>,
pub direction: Option<Direction>,
}

impl<'a> From<&'a LangString> for LanguageValue<'a> {
impl<'a> From<&'a LangString> for LanguageValueRef<'a> {
fn from(value: &'a LangString) -> Self {
LanguageValue {
LanguageValueRef {
value: value.as_str(),
language: value.language().and_then(LenientLangTag::as_well_formed),
direction: value.direction(),
}
}
}

pub trait InternationalString {
fn default_value(&self) -> Option<LanguageValue>;
pub trait AnyInternationalString {
fn default_value(&self) -> Option<LanguageValueRef>;

fn get_language(&self, _lang: &LangTag) -> Option<LanguageValueRef> {
None
}

fn get_language_or_default(&self, lang: &LangTag) -> Option<LanguageValueRef> {
self.get_language(lang).or_else(|| self.default_value())
}
}

impl<T: ?Sized + AnyInternationalString> AnyInternationalString for &T {
fn default_value(&self) -> Option<LanguageValueRef> {
T::default_value(*self)
}
}

impl AnyInternationalString for str {
fn default_value(&self) -> Option<LanguageValueRef> {
Some(LanguageValueRef {
value: self,
language: None,
direction: None,
})
}
}

impl AnyInternationalString for String {
fn default_value(&self) -> Option<LanguageValueRef> {
self.as_str().default_value()
}
}

impl InternationalString for std::convert::Infallible {
fn default_value(&self) -> Option<LanguageValue> {
unreachable!()
impl AnyInternationalString for LangString {
fn default_value(&self) -> Option<LanguageValueRef> {
Some(LanguageValueRef::from(self))
}
}
18 changes: 17 additions & 1 deletion crates/claims/crates/vc/src/v2/syntax/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
IdentifiedTypedObject, MaybeIdentifiedTypedObject, NonEmptyObject, NonEmptyVec,
RequiredContextList, RequiredTypeSet, TypedObject,
},
v2::data_model,
Identified, MaybeIdentified, Typed,
};
use iref::{Uri, UriBuf};
Expand Down Expand Up @@ -60,6 +61,12 @@ pub struct SpecializedJsonCredential<
)]
pub id: Option<UriBuf>,

/// Name.
pub name: Option<InternationalString>,

/// Credential description.
pub description: Option<InternationalString>,

/// Credential type.
#[serde(rename = "type")]
pub types: JsonCredentialTypes<RequiredType>,
Expand Down Expand Up @@ -167,6 +174,8 @@ where
context: Context::default(),
id,
types: JsonCredentialTypes::default(),
name: None,
description: None,
issuer,
credential_subjects,
valid_from: None,
Expand Down Expand Up @@ -331,7 +340,6 @@ impl<
>
{
type Subject = Subject;
type Description = InternationalString;
type Issuer = Issuer;
type Status = Status;
type RefreshService = RefreshService;
Expand All @@ -344,6 +352,14 @@ impl<
self.types.additional_types()
}

fn name(&self) -> Option<impl data_model::AnyInternationalString> {
self.name.as_ref()
}

fn description(&self) -> Option<impl data_model::AnyInternationalString> {
self.description.as_ref()
}

fn credential_subjects(&self) -> &[Self::Subject] {
&self.credential_subjects
}
Expand Down
57 changes: 48 additions & 9 deletions crates/claims/crates/vc/src/v2/syntax/language.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,62 @@
use crate::v2::LanguageValue;
use serde::{Deserialize, Serialize};
use ssi_json_ld::LangString;

use crate::v2::data_model;

/// International string.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(untagged)]
pub enum InternationalString {
String(String),
LanguageValue(LangString),
LanguageMap(Vec<LangString>),
}

impl crate::v2::InternationalString for InternationalString {
fn default_value(&self) -> Option<LanguageValue> {
impl data_model::AnyInternationalString for InternationalString {
fn default_value(&self) -> Option<data_model::LanguageValueRef> {
match self {
Self::String(s) => Some(LanguageValue {
value: s,
language: None,
direction: None,
}),
Self::LanguageValue(l) => Some(l.into()),
Self::String(s) => s.default_value(),
Self::LanguageValue(v) => v.default_value(),
Self::LanguageMap(_) => None,
}
}

fn get_language(
&self,
lang: &ssi_json_ld::syntax::LangTag,
) -> Option<data_model::LanguageValueRef> {
match self {
Self::String(_) => None,
Self::LanguageValue(v) => {
if let Some(tag) = v.language() {
if tag.as_str() == lang.as_str() {
return Some(v.into());
}
}

None
}
Self::LanguageMap(values) => values.iter().find_map(|v| {
if let Some(tag) = v.language() {
if tag.as_str() == lang.as_str() {
return Some(v.into());
}
}

None
}),
}
}
}

impl From<String> for InternationalString {
fn from(value: String) -> Self {
Self::String(value)
}
}

impl From<LangString> for InternationalString {
fn from(value: LangString) -> Self {
Self::LanguageValue(value)
}
}