//! 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::::from_one(1234); //! //! let cm = Unit::centimeters(); //! ``` use crate::either::Either; pub use activitystreams::primitives::{ MimeMediaType, MimeMediaTypeError, RdfLangString, XsdAnyUri, XsdAnyUriError, XsdDateTime, XsdDateTimeError, XsdDuration, XsdDurationError, XsdFloat, XsdFloatError, XsdNonNegativeInteger, }; use activitystreams::primitives::Length; /// 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); /// 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); /// 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(pub(crate) Either>); impl AnyString { /// Borrow the AnyString as an &str /// /// ```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<&str> { self.0.as_ref().left().map(|l| l.as_str()) } /// 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 a String /// /// ```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 { 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 { self.0.right() } /// Create a new AnyString from an `Into` /// /// ```rust /// use activitystreams_new::primitives::AnyString; /// /// let any_string = AnyString::from_xsd_string("hi"); /// ``` pub fn from_xsd_string(string: T) -> Self where T: Into, { 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(string: T) -> Self where T: Into, { AnyString(Either::Right(string.into())) } /// Replace the contents of self with a String /// /// ```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(&mut self, string: T) where T: Into, { 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(&mut self, string: T) where T: Into, { self.0 = Either::Right(string.into()); } } impl OneOrMany { /// Try to borrow a single String from the current object /// /// ```rust /// # fn main() -> Result<(), anyhow::Error> { /// # use activitystreams_new::primitives::{OneOrMany, AnyString}; /// # let string = OneOrMany::::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<&str> { 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 String from the current object /// /// ```rust /// # fn main() -> Result<(), anyhow::Error> { /// # use activitystreams_new::primitives::{OneOrMany, AnyString}; /// # let string = OneOrMany::::from_xsd_string("Hey"); /// string /// .single_xsd_string() /// .ok_or(anyhow::Error::msg("Wrong string type"))?; /// # Ok(()) /// # } /// ``` pub fn single_xsd_string(self) -> Option { 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 { self.one() .and_then(|any_string| any_string.rdf_lang_string()) } /// Create the object from a single String /// /// ```rust /// use activitystreams_new::primitives::{OneOrMany, AnyString}; /// /// let string = OneOrMany::::from_xsd_string("hi"); /// ``` pub fn from_xsd_string(string: T) -> Self where T: Into, { 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(string: T) -> Self where T: Into, { Self::from_one(AnyString::from_rdf_lang_string(string)) } /// Add a String to the object, appending to whatever is currently included /// /// ```rust /// use activitystreams_new::primitives::{OneOrMany, AnyString}; /// /// let mut string = OneOrMany::::from_xsd_string("Hello"); /// /// string /// .add_xsd_string("Hey") /// .add_xsd_string("hi"); /// ``` pub fn add_xsd_string(&mut self, string: T) -> &mut Self where T: Into, { 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::::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(&mut self, string: T) -> &mut Self where T: Into, { self.add(string.into()) } } impl OneOrMany { /// 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 { 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> { 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 { match self.0 { Either::Left(t) => vec![t], Either::Right(v) => v, } } /// 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) -> 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(&mut self, u: U) -> &mut Self where U: Into, { self.0 = Either::Left(u.into()); 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(&mut self, items: impl IntoIterator) -> &mut Self where U: Into, { self.0 = Either::Right(items.into_iter().map(Into::into).collect()); 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(&mut self, u: U) -> &mut Self where U: Into, { let mut v = match std::mem::replace(&mut self.0, Either::Right(vec![])) { Either::Left(one) => vec![one], Either::Right(v) => v, }; v.push(u.into()); self.0 = Either::Right(v); 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(&mut self, items: impl IntoIterator) -> &mut Self where U: Into, { let mut v = match std::mem::replace(&mut self.0, Either::Right(vec![])) { Either::Left(one) => vec![one], Either::Right(v) => v, }; v.extend(items.into_iter().map(Into::into)); self.0 = Either::Right(v); self } } impl Unit { /// Create a new unit measuring Centimeters /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// Unit::centimeters(); /// ``` pub fn centimeters() -> Self { Unit(Either::Left(Length::Centimeters)) } /// Check if the unit is Centimeters /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// assert!(Unit::centimeters().is_centimeters()); /// ``` pub fn is_centimeters(&self) -> bool { self.0 .as_ref() .left() .map(|l| l.is_centimeters()) .unwrap_or(false) } /// Create a new unit measuring Meters /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// Unit::meters(); /// ``` pub fn meters() -> Self { Unit(Either::Left(Length::Meters)) } /// Check if the unit is Meters /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// assert!(Unit::meters().is_meters()); /// ``` pub fn is_meters(&self) -> bool { self.0 .as_ref() .left() .map(|l| l.is_meters()) .unwrap_or(false) } /// Create a new unit measuring Kilometers /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// Unit::kilometers(); /// ``` pub fn kilometers() -> Self { Unit(Either::Left(Length::Kilometers)) } /// Check if the unit is Kilometers /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// assert!(Unit::kilometers().is_kilometers()); /// ``` pub fn is_kilometers(&self) -> bool { self.0 .as_ref() .left() .map(|l| l.is_kilometers()) .unwrap_or(false) } /// Create a new unit measuring Feet /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// Unit::feet(); /// ``` pub fn feet() -> Self { Unit(Either::Left(Length::Feet)) } /// Check if the unit is Feet /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// assert!(Unit::feet().is_feet()); /// ``` pub fn is_feet(&self) -> bool { self.0.as_ref().left().map(|l| l.is_feet()).unwrap_or(false) } /// Create a new unit measuring Inches /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// Unit::inches(); /// ``` pub fn inches() -> Self { Unit(Either::Left(Length::Inches)) } /// Check if the unit is Inches /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// assert!(Unit::inches().is_inches()); /// ``` pub fn is_inches(&self) -> bool { self.0 .as_ref() .left() .map(|l| l.is_inches()) .unwrap_or(false) } /// Create a new custom unit /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// Unit::custom("Yards"); /// ``` pub fn custom(string: T) -> Self where T: Into, { Unit(Either::Right(string.into())) } /// Check if a unit is custom /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// assert!(Unit::custom("Yards").is_custom()); /// ``` pub fn is_custom(&self) -> bool { self.as_custom().is_some() } /// Fetch a custom unit /// /// ```rust /// use activitystreams_new::primitives::Unit; /// /// assert!(Unit::custom("Yards").as_custom() == Some("Yards")); /// ``` pub fn as_custom(&self) -> Option<&str> { self.0.as_ref().right().map(|r| r.as_str()) } } impl Default for Unit { fn default() -> Self { Self::meters() } } impl std::str::FromStr for Unit { type Err = std::convert::Infallible; fn from_str(s: &str) -> Result { let unit = match s { "cm" => Self::centimeters(), "m" => Self::meters(), "km" => Self::kilometers(), "inches" => Self::inches(), "feet" => Self::feet(), other => Self::custom(other), }; Ok(unit) } } impl From for Unit { fn from(s: String) -> Self { match s.parse() { Ok(u) => u, Err(e) => match e {}, } } } impl From<&str> for Unit { fn from(s: &str) -> Self { match s.parse() { Ok(u) => u, Err(e) => match e {}, } } } impl From for OneOrMany { fn from(t: T) -> Self { OneOrMany::from_one(t) } } impl From> for OneOrMany { fn from(t: Vec) -> Self { OneOrMany::from_many(t) } } impl From<&str> for AnyString { fn from(s: &str) -> Self { AnyString::from_xsd_string(s.to_owned()) } } impl From for AnyString { fn from(s: String) -> Self { AnyString::from_xsd_string(s) } } impl From for AnyString { fn from(s: RdfLangString) -> Self { AnyString::from_rdf_lang_string(s) } } impl From<&str> for OneOrMany { fn from(s: &str) -> Self { OneOrMany::::from_xsd_string(s.to_owned()) } } impl From for OneOrMany { fn from(s: String) -> Self { OneOrMany::::from_xsd_string(s) } } impl From for OneOrMany { fn from(s: RdfLangString) -> Self { OneOrMany::::from_rdf_lang_string(s) } }