From 5117509437da49b07d6908522df80f940b60b0d1 Mon Sep 17 00:00:00 2001 From: "Charles E. Lehner" <charles.lehner@spruceid.com> Date: Mon, 21 Sep 2020 13:44:24 -0400 Subject: [PATCH] Move OneOrMany into own file --- src/lib.rs | 1 + src/one_or_many.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++ src/vc.rs | 63 +----------------------------------- 3 files changed, 81 insertions(+), 62 deletions(-) create mode 100644 src/one_or_many.rs diff --git a/src/lib.rs b/src/lib.rs index f7fd982f6..c2995fe88 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ pub mod der; pub mod did; pub mod error; pub mod jwk; +pub(crate) mod one_or_many; pub mod vc; extern crate pest; diff --git a/src/one_or_many.rs b/src/one_or_many.rs new file mode 100644 index 000000000..347bb00c1 --- /dev/null +++ b/src/one_or_many.rs @@ -0,0 +1,79 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(untagged)] +pub enum OneOrMany<T> { + One(T), + Many(Vec<T>), +} + +impl<T> OneOrMany<T> { + pub fn len(&self) -> usize { + match self { + Self::One(_) => 1, + Self::Many(values) => values.len(), + } + } + + pub fn contains(&self, x: &T) -> bool + where + T: PartialEq<T>, + { + match self { + Self::One(value) => x == value, + Self::Many(values) => values.contains(x), + } + } + + pub fn first(&self) -> Option<&T> { + match self { + Self::One(value) => Some(&value), + Self::Many(values) => { + if values.len() > 0 { + Some(&values[0]) + } else { + None + } + } + } + } + + pub fn to_single(&self) -> Option<&T> { + match self { + Self::One(value) => Some(&value), + Self::Many(values) => { + if values.len() == 1 { + Some(&values[0]) + } else { + None + } + } + } + } +} + +// consuming iterator +impl<T> IntoIterator for OneOrMany<T> { + type Item = T; + type IntoIter = std::vec::IntoIter<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + match self { + Self::One(value) => vec![value].into_iter(), + Self::Many(values) => values.into_iter(), + } + } +} + +// non-consuming iterator +impl<'a, T> IntoIterator for &'a OneOrMany<T> { + type Item = &'a T; + type IntoIter = std::vec::IntoIter<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + match self { + OneOrMany::One(value) => vec![value].into_iter(), + OneOrMany::Many(values) => values.into_iter().collect::<Vec<Self::Item>>().into_iter(), + } + } +} diff --git a/src/vc.rs b/src/vc.rs index 7a6f81516..d574fa86b 100644 --- a/src/vc.rs +++ b/src/vc.rs @@ -3,6 +3,7 @@ use std::convert::TryFrom; use crate::error::Error; use crate::jwk::{JWTKeys, Params}; +use crate::one_or_many::OneOrMany; use chrono::prelude::*; use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation}; @@ -63,13 +64,6 @@ pub struct Credential { pub refresh_service: Option<OneOrMany<RefreshService>>, } -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(untagged)] -pub enum OneOrMany<T> { - One(T), - Many(Vec<T>), -} - #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(untagged)] #[serde(try_from = "OneOrMany<Context>")] @@ -231,61 +225,6 @@ pub struct JWTClaims { pub verifiable_presentation: Option<Presentation>, } -impl<T> OneOrMany<T> { - pub fn any<F>(&self, f: F) -> bool - where - F: Fn(&T) -> bool, - { - match self { - Self::One(value) => f(value), - Self::Many(values) => values.iter().any(f), - } - } - - pub fn len(&self) -> usize { - match self { - Self::One(_) => 1, - Self::Many(values) => values.len(), - } - } - - pub fn contains(&self, x: &T) -> bool - where - T: PartialEq<T>, - { - match self { - Self::One(value) => x == value, - Self::Many(values) => values.contains(x), - } - } - - pub fn first(&self) -> Option<&T> { - match self { - Self::One(value) => Some(&value), - Self::Many(values) => { - if values.len() > 0 { - Some(&values[0]) - } else { - None - } - } - } - } - - pub fn to_single(&self) -> Option<&T> { - match self { - Self::One(value) => Some(&value), - Self::Many(values) => { - if values.len() == 1 { - Some(&values[0]) - } else { - None - } - } - } - } -} - impl TryFrom<OneOrMany<Context>> for Contexts { type Error = Error; fn try_from(context: OneOrMany<Context>) -> Result<Self, Self::Error> {