From 47efc1c6466b690636d93f5a4a2c5bc71b5f8736 Mon Sep 17 00:00:00 2001 From: "Aode (lion)" Date: Wed, 17 Nov 2021 19:20:56 -0600 Subject: [PATCH] Add as_slice(), rename unwrap_to_vec() to into_vec() --- Cargo.toml | 2 +- src/base.rs | 12 ++-- src/primitives/any_string.rs | 2 +- src/primitives/one_or_many.rs | 116 ++++++++++++++++++++++++++++------ 4 files changed, 105 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1a24ddb..31355a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "activitystreams" description = "A set of core types and traits for activitystreams data" -version = "0.7.0-alpha.11" +version = "0.7.0-alpha.12" license = "GPL-3.0" authors = ["asonix "] repository = "https://git.asonix.dog/Aardwolf/activitystreams" diff --git a/src/base.rs b/src/base.rs index d2243a8..c19189e 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1754,7 +1754,7 @@ impl OneOrMany { /// # } /// ``` pub fn from_xsd_any_uri(id: Url) -> Self { - OneOrMany(Either::Left(AnyBase::from_xsd_any_uri(id))) + OneOrMany(Either::Left([AnyBase::from_xsd_any_uri(id)])) } /// Create a `OneOrMany` from a String @@ -1765,7 +1765,7 @@ impl OneOrMany { /// let one = OneOrMany::::from_xsd_string("hi".into()); /// ``` pub fn from_xsd_string(xsd_string: String) -> Self { - OneOrMany(Either::Left(AnyBase::from_xsd_string(xsd_string))) + OneOrMany(Either::Left([AnyBase::from_xsd_string(xsd_string)])) } /// Create a `OneOrMany` from a `Base` @@ -1779,7 +1779,7 @@ impl OneOrMany { /// let one = OneOrMany::from_base(base); /// ``` pub fn from_base(base: Base) -> Self { - OneOrMany(Either::Left(AnyBase::from_base(base))) + OneOrMany(Either::Left([AnyBase::from_base(base)])) } /// Overwrite the current object with a Url @@ -1795,7 +1795,7 @@ impl OneOrMany { /// assert!(one.as_single_xsd_any_uri().is_some()); /// ``` pub fn set_single_xsd_any_uri(&mut self, id: Url) -> &mut Self { - self.0 = Either::Left(AnyBase::from_xsd_any_uri(id)); + self.0 = Either::Left([AnyBase::from_xsd_any_uri(id)]); self } @@ -1812,7 +1812,7 @@ impl OneOrMany { /// assert!(one.as_single_xsd_string().is_some()); /// ``` pub fn set_single_xsd_string(&mut self, xsd_string: String) -> &mut Self { - self.0 = Either::Left(AnyBase::from_xsd_string(xsd_string)); + self.0 = Either::Left([AnyBase::from_xsd_string(xsd_string)]); self } @@ -1829,7 +1829,7 @@ impl OneOrMany { /// assert!(one.as_single_base().is_some()); /// ``` pub fn set_single_base(&mut self, base: Base) -> &mut Self { - self.0 = Either::Left(AnyBase::from_base(base)); + self.0 = Either::Left([AnyBase::from_base(base)]); self } diff --git a/src/primitives/any_string.rs b/src/primitives/any_string.rs index 5ec9f53..1435e48 100644 --- a/src/primitives/any_string.rs +++ b/src/primitives/any_string.rs @@ -358,7 +358,7 @@ impl OneOrMany<&AnyString> { /// ``` pub fn to_owned(self) -> OneOrMany { match self.0 { - Either::Left(one_ref) => OneOrMany(Either::Left(one_ref.to_owned())), + Either::Left([one_ref]) => OneOrMany(Either::Left([one_ref.to_owned()])), Either::Right(many_ref) => { OneOrMany(Either::Right(many_ref.into_iter().cloned().collect())) } diff --git a/src/primitives/one_or_many.rs b/src/primitives/one_or_many.rs index 2e50b2a..01b7c77 100644 --- a/src/primitives/one_or_many.rs +++ b/src/primitives/one_or_many.rs @@ -18,9 +18,8 @@ use crate::either::Either; /// "key": [value, ...] /// } /// ``` -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] -#[serde(transparent)] -pub struct OneOrMany(pub(crate) Either>); +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct OneOrMany(pub(crate) Either<[T; 1], Vec>); /// An iterator over a OneOrMany's borrowed contents #[derive(Clone, Debug)] @@ -48,7 +47,7 @@ impl OneOrMany { /// ``` pub fn iter(&self) -> Iter<'_, T> { match self.0 { - Either::Left(ref t) => Iter(Either::Left(Some(t))), + Either::Left([ref t]) => Iter(Either::Left(Some(t))), Either::Right(ref v) => Iter(Either::Right(v.iter())), } } @@ -66,7 +65,7 @@ impl OneOrMany { /// ``` pub fn iter_mut(&mut self) -> IterMut<'_, T> { match self.0 { - Either::Left(ref mut t) => IterMut(Either::Left(Some(t))), + Either::Left([ref mut t]) => IterMut(Either::Left(Some(t))), Either::Right(ref mut v) => IterMut(Either::Right(v.iter_mut())), } } @@ -82,7 +81,7 @@ impl OneOrMany { /// assert_eq!(value_ref.one(), Some(&String::from("hi"))); /// ``` pub fn as_ref(&self) -> OneOrMany<&T> { - OneOrMany(self.0.as_ref().map(|l| l, |r| r.iter().collect())) + OneOrMany(self.0.as_ref().map(|[l]| [l], |r| r.iter().collect())) } /// Map the value inside the OneOrMany from T to U @@ -99,7 +98,7 @@ impl OneOrMany { where F: Fn(T) -> U + Copy, { - OneOrMany(self.0.map(f, |v| v.into_iter().map(f).collect())) + OneOrMany(self.0.map(|[l]| [f(l)], |v| v.into_iter().map(f).collect())) } /// Create a OneOrMany mutably referencing the existing one @@ -111,7 +110,7 @@ impl OneOrMany { /// let value_mut = value.as_mut(); /// ``` pub fn as_mut(&mut self) -> OneOrMany<&mut T> { - OneOrMany(self.0.as_mut().map(|l| l, |r| r.iter_mut().collect())) + OneOrMany(self.0.as_mut().map(|[l]| [l], |r| r.iter_mut().collect())) } /// Get a reference to a single value @@ -124,7 +123,7 @@ impl OneOrMany { /// } /// ``` pub fn as_one(&self) -> Option<&T> { - self.0.as_ref().left() + self.0.as_ref().left().map(|[t]| t) } /// Borrow one as mutable @@ -141,7 +140,7 @@ impl OneOrMany { /// assert_eq!(value.one(), Some(2)); /// ``` pub fn one_mut(&mut self) -> Option<&mut T> { - self.0.as_mut().left() + self.0.as_mut().left().map(|[t]| t) } /// Take a single value @@ -154,7 +153,7 @@ impl OneOrMany { /// } /// ``` pub fn one(self) -> Option { - self.0.left() + self.0.left().map(|[t]| t) } /// Get a slice of values @@ -211,17 +210,33 @@ impl OneOrMany { /// ```rust /// # use activitystreams::primitives::OneOrMany; /// # let value = OneOrMany::from_many(vec![1, 2, 3]); - /// for item in value.unwrap_to_vec() { + /// for item in value.into_vec() { /// println!("{:?}", item); /// } /// ``` - pub fn unwrap_to_vec(self) -> Vec { + pub fn into_vec(self) -> Vec { match self.0 { - Either::Left(t) => vec![t], + Either::Left(t) => t.into(), Either::Right(v) => v, } } + /// Return a slice of values contained by the OneOrMany + /// + /// ```rust + /// # use activitystreams::primitives::OneOrMany; + /// # let value = OneOrMany::from_many(vec![1, 2, 3]); + /// for item in value.as_slice() { + /// println!("{:?}", item) + /// } + /// ``` + pub fn as_slice(&self) -> &[T] { + match self.0 { + Either::Left(ref t) => t, + Either::Right(ref v) => v, + } + } + /// Produce a new object from one value /// /// ``` @@ -229,7 +244,7 @@ impl OneOrMany { /// let v = OneOrMany::from_one(1234); /// ``` pub fn from_one(t: T) -> Self { - OneOrMany(Either::Left(t)) + OneOrMany(Either::Left([t])) } /// Produce a new object from a vec of values @@ -255,7 +270,7 @@ impl OneOrMany { where U: Into, { - self.0 = Either::Left(u.into()); + self.0 = Either::Left([u.into()]); self } @@ -293,7 +308,7 @@ impl OneOrMany { U: Into, { let mut v = match std::mem::replace(&mut self.0, Either::Right(vec![])) { - Either::Left(one) => vec![one], + Either::Left(one) => one.into(), Either::Right(v) => v, }; v.push(u.into()); @@ -318,7 +333,7 @@ impl OneOrMany { U: Into, { let mut v = match std::mem::replace(&mut self.0, Either::Right(vec![])) { - Either::Left(one) => vec![one], + Either::Left(one) => one.into(), Either::Right(v) => v, }; v.extend(items.into_iter().map(Into::into)); @@ -341,7 +356,7 @@ impl IntoIterator for OneOrMany { /// ``` fn into_iter(self) -> Self::IntoIter { match self.0 { - Either::Left(t) => IntoIter(Either::Left(Some(t))), + Either::Left([t]) => IntoIter(Either::Left(Some(t))), Either::Right(v) => IntoIter(Either::Right(v.into_iter())), } } @@ -557,10 +572,73 @@ impl From> for OneOrMany { } } +impl<'de, T> serde::de::Deserialize<'de> for OneOrMany +where + T: serde::de::Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(serde::Deserialize)] + struct OneOrManyInner(Either>); + + OneOrManyInner::deserialize(deserializer).map(|inner| match inner.0 { + Either::Left(one) => OneOrMany(Either::Left([one])), + Either::Right(vec) => OneOrMany(Either::Right(vec)), + }) + } +} + +impl serde::Serialize for OneOrMany +where + T: serde::ser::Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + #[derive(serde::Serialize)] + struct OneOrManyInner<'a, T>(Either<&'a T, &'a [T]>); + let to_ser = match self.0 { + Either::Left([ref one]) => OneOrManyInner(Either::Left(one)), + Either::Right(ref v) => OneOrManyInner(Either::Right(v)), + }; + + to_ser.serialize(serializer) + } +} + #[cfg(test)] mod tests { use super::OneOrMany; + #[test] + fn ser_de() { + #[derive(Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)] + struct Hi { + inner: OneOrMany, + } + + let h1 = Hi { + inner: OneOrMany::from_one(String::from("hello")), + }; + let s = serde_json::to_string(&h1).unwrap(); + assert_eq!(s, r#"{"inner":"hello"}"#); + + let h2: Hi = serde_json::from_str(&s).unwrap(); + assert_eq!(h2, h1); + + let h1 = Hi { + inner: OneOrMany::from_many(vec![String::from("hello"), String::from("hi")]), + }; + let s = serde_json::to_string(&h1).unwrap(); + assert_eq!(s, r#"{"inner":["hello","hi"]}"#); + + let h2: Hi = serde_json::from_str(&s).unwrap(); + assert_eq!(h2, h1); + } + #[test] fn iter_works() { let single = OneOrMany::from_one(1);