Test primitives

This commit is contained in:
asonix 2020-05-16 15:34:35 -05:00
parent 9095ba4077
commit 4e22ce7923
1 changed files with 350 additions and 0 deletions

View File

@ -1,3 +1,17 @@
//! Types creating the base for most ActivityStreams fields.
//!
//! These types are not themselves defined by ActivityStreams, but are referenced by the
//! specification.
//!
//! ```rust
//! use activitystreams_new::primitives::{AnyString, OneOrMany, Unit};
//!
//! let any_string = AnyString::from_xsd_string("hey");
//!
//! let one_or_many = OneOrMany::<i32>::from_one(1234);
//!
//! let cm = Unit::centimeters();
//! ```
use crate::either::Either;
pub use activitystreams::primitives::{
@ -5,37 +19,133 @@ pub use activitystreams::primitives::{
XsdNonNegativeInteger, XsdString,
};
/// A type representing any kind of string
///
/// In the ActivityStreams specification, string types are often defined as either an xsd:String or
/// and rdf:langString. The AnyString type represents this union.
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
pub struct AnyString(Either<XsdString, RdfLangString>);
/// A type representing units of length
///
/// It can be any of the following
/// - Centimeters
/// - Meters
/// - Kilometers
/// - Inches
/// - Feet
/// - A custom value
#[derive(
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
)]
#[serde(transparent)]
pub struct Unit(Either<Length, XsdString>);
/// A type representing at least one value
///
/// When translated to JSON, it can represent the following structures:
/// ```json
/// {
/// "key": value
/// }
/// ```
/// ```json
/// {
/// "key": [],
/// }
/// ```
/// ```json
/// {
/// "key": [value, ...]
/// }
/// ```
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
pub struct OneOrMany<T>(pub Either<T, Vec<T>>);
impl AnyString {
/// Borrow the AnyString as an XsdString
///
/// ```rust
/// # fn main() -> Result<(), anyhow::Error> {
/// # use activitystreams_new::primitives::AnyString;
/// # let any_string = AnyString::from_xsd_string("hi");
/// #
/// let s_borrow = any_string
/// .as_xsd_string()
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
/// # Ok(())
/// # }
/// ```
pub fn as_xsd_string(&self) -> Option<&XsdString> {
self.0.as_ref().left()
}
/// Borrow the AnyString as an RdfLangString
///
/// ```rust
/// # fn main() -> Result<(), anyhow::Error> {
/// # use activitystreams_new::primitives::{AnyString, RdfLangString};
/// # let any_string = AnyString::from_rdf_lang_string(RdfLangString {
/// # value: "hi".into(),
/// # language: "en".into(),
/// # });
/// #
/// let s_borrow = any_string
/// .as_rdf_lang_string()
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
/// # Ok(())
/// # }
/// ```
pub fn as_rdf_lang_string(&self) -> Option<&RdfLangString> {
self.0.as_ref().right()
}
/// Take the AnyString as an XsdString
///
/// ```rust
/// # fn main() -> Result<(), anyhow::Error> {
/// # use activitystreams_new::primitives::AnyString;
/// # let any_string = AnyString::from_xsd_string("hi");
/// #
/// let xsd_string = any_string
/// .xsd_string()
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
/// # Ok(())
/// # }
/// ```
pub fn xsd_string(self) -> Option<XsdString> {
self.0.left()
}
/// Take the AnyString as an RdfLangString
///
/// ```rust
/// # fn main() -> Result<(), anyhow::Error> {
/// # use activitystreams_new::primitives::{AnyString, RdfLangString};
/// # let any_string = AnyString::from_rdf_lang_string(RdfLangString {
/// # value: "hi".into(),
/// # language: "en".into(),
/// # });
/// #
/// let rdf_lang_string = any_string
/// .rdf_lang_string()
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
/// # Ok(())
/// # }
/// ```
pub fn rdf_lang_string(self) -> Option<RdfLangString> {
self.0.right()
}
/// Create a new AnyString from an `Into<XsdString>`
///
/// ```rust
/// use activitystreams_new::primitives::AnyString;
///
/// let any_string = AnyString::from_xsd_string("hi");
/// ```
pub fn from_xsd_string<T>(string: T) -> Self
where
T: Into<XsdString>,
@ -43,6 +153,16 @@ impl AnyString {
AnyString(Either::Left(string.into()))
}
/// Create a new AnyString from an RdfLangString
///
/// ```rust
/// use activitystreams_new::primitives::{AnyString, RdfLangString};
///
/// let any_string = AnyString::from_rdf_lang_string(RdfLangString {
/// value: "hi".into(),
/// language: "en".into(),
/// });
/// ```
pub fn from_rdf_lang_string<T>(string: T) -> Self
where
T: Into<RdfLangString>,
@ -50,6 +170,20 @@ impl AnyString {
AnyString(Either::Right(string.into()))
}
/// Replace the contents of self with an XsdString
///
/// ```rust
/// use activitystreams_new::primitives::{AnyString, RdfLangString};
///
/// let mut any_string = AnyString::from_rdf_lang_string(RdfLangString {
/// value: "hi".into(),
/// language: "en".into(),
/// });
///
/// any_string.set_xsd_string("hi");
///
/// assert!(any_string.as_xsd_string().is_some());
/// ```
pub fn set_xsd_string<T>(&mut self, string: T)
where
T: Into<XsdString>,
@ -57,6 +191,20 @@ impl AnyString {
self.0 = Either::Left(string.into());
}
/// Replace the contents of self with an RdfLangString
///
/// ```rust
/// use activitystreams_new::primitives::{AnyString, RdfLangString};
///
/// let mut any_string = AnyString::from_xsd_string("hi");
///
/// any_string.set_rdf_lang_string(RdfLangString {
/// value: "hi".into(),
/// language: "en".into(),
/// });
///
/// assert!(any_string.as_rdf_lang_string().is_some());
/// ```
pub fn set_rdf_lang_string<T>(&mut self, string: T)
where
T: Into<RdfLangString>,
@ -66,25 +214,86 @@ impl AnyString {
}
impl OneOrMany<AnyString> {
/// Try to borrow a single XsdString from the current object
///
/// ```rust
/// # fn main() -> Result<(), anyhow::Error> {
/// # use activitystreams_new::primitives::{OneOrMany, AnyString};
/// # let string = OneOrMany::<AnyString>::from_xsd_string("Hey");
/// string
/// .as_single_xsd_string()
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
/// # Ok(())
/// # }
/// ```
pub fn as_single_xsd_string(&self) -> Option<&XsdString> {
self.as_one()
.and_then(|any_string| any_string.as_xsd_string())
}
/// Try to borrow a single RdfLangString from the current object
///
/// ```rust
/// # fn main() -> Result<(), anyhow::Error> {
/// # use activitystreams_new::primitives::{OneOrMany, RdfLangString};
/// # let string = OneOrMany::from_rdf_lang_string(RdfLangString {
/// # value: "hi".into(),
/// # language: "en".into(),
/// # });
/// string
/// .as_single_rdf_lang_string()
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
/// # Ok(())
/// # }
/// ```
pub fn as_single_rdf_lang_string(&self) -> Option<&RdfLangString> {
self.as_one()
.and_then(|any_string| any_string.as_rdf_lang_string())
}
/// Try to take a single XsdString from the current object
///
/// ```rust
/// # fn main() -> Result<(), anyhow::Error> {
/// # use activitystreams_new::primitives::{OneOrMany, AnyString};
/// # let string = OneOrMany::<AnyString>::from_xsd_string("Hey");
/// string
/// .single_xsd_string()
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
/// # Ok(())
/// # }
/// ```
pub fn single_xsd_string(self) -> Option<XsdString> {
self.one().and_then(|any_string| any_string.xsd_string())
}
/// Try to take a single RdfLangString from the current object
///
/// ```rust
/// # fn main() -> Result<(), anyhow::Error> {
/// # use activitystreams_new::primitives::{OneOrMany, RdfLangString};
/// # let string = OneOrMany::from_rdf_lang_string(RdfLangString {
/// # value: "hi".into(),
/// # language: "en".into(),
/// # });
/// string
/// .single_rdf_lang_string()
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
/// # Ok(())
/// # }
/// ```
pub fn single_rdf_lang_string(self) -> Option<RdfLangString> {
self.one()
.and_then(|any_string| any_string.rdf_lang_string())
}
/// Create the object from a single XsdString
///
/// ```rust
/// use activitystreams_new::primitives::{OneOrMany, AnyString};
///
/// let string = OneOrMany::<AnyString>::from_xsd_string("hi");
/// ```
pub fn from_xsd_string<T>(string: T) -> Self
where
T: Into<XsdString>,
@ -92,6 +301,16 @@ impl OneOrMany<AnyString> {
Self::from_one(AnyString::from_xsd_string(string))
}
/// Create the object from a single RdfLangString
///
/// ```rust
/// use activitystreams_new::primitives::{OneOrMany, RdfLangString};
///
/// let string = OneOrMany::from_rdf_lang_string(RdfLangString {
/// value: "hi".into(),
/// language: "en".into(),
/// });
/// ```
pub fn from_rdf_lang_string<T>(string: T) -> Self
where
T: Into<RdfLangString>,
@ -99,6 +318,17 @@ impl OneOrMany<AnyString> {
Self::from_one(AnyString::from_rdf_lang_string(string))
}
/// Add an XsdString to the object, appending to whatever is currently included
///
/// ```rust
/// use activitystreams_new::primitives::{OneOrMany, AnyString};
///
/// let mut string = OneOrMany::<AnyString>::from_xsd_string("Hello");
///
/// string
/// .add_xsd_string("Hey")
/// .add_xsd_string("hi");
/// ```
pub fn add_xsd_string<T>(&mut self, string: T) -> &mut Self
where
T: Into<XsdString>,
@ -106,6 +336,23 @@ impl OneOrMany<AnyString> {
self.add(string.into())
}
/// Add an RdfLangString to the object, appending to whatever is currently included
///
/// ```rust
/// use activitystreams_new::primitives::{AnyString, OneOrMany, RdfLangString};
///
/// let mut string = OneOrMany::<AnyString>::from_xsd_string("Hello");
///
/// string
/// .add_rdf_lang_string(RdfLangString {
/// value: "Hey".into(),
/// language: "en".into(),
/// })
/// .add_rdf_lang_string(RdfLangString {
/// value: "hi".into(),
/// language: "en".into(),
/// });
/// ```
pub fn add_rdf_lang_string<T>(&mut self, string: T) -> &mut Self
where
T: Into<RdfLangString>,
@ -115,22 +362,71 @@ impl OneOrMany<AnyString> {
}
impl<T> OneOrMany<T> {
/// Get a reference to a single value
///
/// ```rust
/// # use activitystreams_new::primitives::OneOrMany;
/// # let value = OneOrMany::from_one(1);
/// if let Some(v) = value.as_one() {
/// println!("{:?}", v);
/// }
/// ```
pub fn as_one(&self) -> Option<&T> {
self.0.as_ref().left()
}
/// Take a single value
///
/// ```rust
/// # use activitystreams_new::primitives::OneOrMany;
/// # let value = OneOrMany::from_one(1);
/// if let Some(v) = value.one() {
/// println!("{:?}", v);
/// }
/// ```
pub fn one(self) -> Option<T> {
self.0.left()
}
/// Get a slice of values
///
/// ```rust
/// # use activitystreams_new::primitives::OneOrMany;
/// # let value = OneOrMany::from_many(vec![1, 2, 3]);
/// if let Some(v) = value.as_many() {
/// for item in v.iter() {
/// println!("{:?}", item);
/// }
/// }
/// ```
pub fn as_many(&self) -> Option<&[T]> {
self.0.as_ref().right().map(|v| v.as_ref())
}
/// Take a Vec of values
///
/// ```rust
/// # use activitystreams_new::primitives::OneOrMany;
/// # let value = OneOrMany::from_many(vec![1, 2, 3]);
/// if let Some(v) = value.many() {
/// for item in v.into_iter() {
/// println!("{:?}", item);
/// }
/// }
/// ```
pub fn many(self) -> Option<Vec<T>> {
self.0.right()
}
/// Consume the type, returning a vec
///
/// ```rust
/// # use activitystreams_new::primitives::OneOrMany;
/// # let value = OneOrMany::from_many(vec![1, 2, 3]);
/// for item in value.unwrap_to_vec() {
/// println!("{:?}", item);
/// }
/// ```
pub fn unwrap_to_vec(self) -> Vec<T> {
match self.0 {
Either::Left(t) => vec![t],
@ -138,14 +434,35 @@ impl<T> OneOrMany<T> {
}
}
/// Produce a new object from one value
///
/// ```
/// use activitystreams_new::primitives::OneOrMany;
/// let v = OneOrMany::from_one(1234);
/// ```
pub fn from_one(t: T) -> Self {
OneOrMany(Either::Left(t))
}
/// Produce a new object from a vec of values
///
/// ```
/// use activitystreams_new::primitives::OneOrMany;
/// let v = OneOrMany::from_many(vec![1, 2, 3, 4]);
/// ```
pub fn from_many(items: Vec<T>) -> Self {
OneOrMany(Either::Right(items))
}
/// Overwrite the contents with a single value
///
/// ```
/// # use activitystreams_new::primitives::OneOrMany;
/// # let mut value = OneOrMany::from_many(vec![1, 2, 3]);
/// value.set_one(3);
///
/// assert!(value.as_one().is_some());
/// ```
pub fn set_one<U>(&mut self, u: U) -> &mut Self
where
U: Into<T>,
@ -154,6 +471,15 @@ impl<T> OneOrMany<T> {
self
}
/// Overwrite the contents with vec of values
///
/// ```
/// # use activitystreams_new::primitives::OneOrMany;
/// # let mut value = OneOrMany::from_one(1234);
/// value.set_many(vec![1, 2, 3, 4]);
///
/// assert!(value.as_many().is_some());
/// ```
pub fn set_many<U>(&mut self, items: impl IntoIterator<Item = U>) -> &mut Self
where
U: Into<T>,
@ -162,6 +488,18 @@ impl<T> OneOrMany<T> {
self
}
/// Add a value to the object
///
/// This appends the value to the existing vec, or converts the single value into a vec, and
/// then appends the new value
///
/// ```
/// use activitystreams_new::primitives::OneOrMany;
/// let mut value = OneOrMany::from_one(1234);
/// value.add(4321);
///
/// assert!(value.as_many().is_some());
/// ```
pub fn add<U>(&mut self, u: U) -> &mut Self
where
U: Into<T>,
@ -175,6 +513,18 @@ impl<T> OneOrMany<T> {
self
}
/// Add many values to the object
///
/// This appends the values to the existing vec, or converts the single value into a vec, and
/// then appends the new values
///
/// ```
/// use activitystreams_new::primitives::OneOrMany;
/// let mut value = OneOrMany::from_one(1234);
/// value.add_many(vec![4321, 2345]);
///
/// assert!(value.as_many().is_some());
/// ```
pub fn add_many<U>(&mut self, items: impl IntoIterator<Item = U>) -> &mut Self
where
U: Into<T>,