use super::{
AttributesIntoIteratorV03, AttributesIntoIteratorV10, AttributesV03, AttributesV10,
ExtensionValue, SpecVersion, UriReference,
};
use chrono::{DateTime, Utc};
use serde::Serializer;
use std::fmt;
use url::Url;
#[derive(Debug, PartialEq, Eq)]
pub enum AttributeValue<'a> {
SpecVersion(SpecVersion),
String(&'a str),
URI(&'a Url),
URIRef(&'a UriReference),
Boolean(&'a bool),
Integer(&'a i64),
Time(&'a DateTime<Utc>),
}
impl<'a> From<&'a ExtensionValue> for AttributeValue<'a> {
fn from(ev: &'a ExtensionValue) -> Self {
match ev {
ExtensionValue::String(s) => AttributeValue::String(s),
ExtensionValue::Boolean(b) => AttributeValue::Boolean(b),
ExtensionValue::Integer(i) => AttributeValue::Integer(i),
}
}
}
impl fmt::Display for AttributeValue<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AttributeValue::SpecVersion(s) => s.fmt(f),
AttributeValue::String(s) => f.write_str(s),
AttributeValue::URI(s) => f.write_str(s.as_str()),
AttributeValue::URIRef(s) => f.write_str(s.as_str()),
AttributeValue::Time(s) => f.write_str(&s.to_rfc3339()),
AttributeValue::Boolean(b) => f.serialize_bool(**b),
AttributeValue::Integer(i) => f.serialize_i64(**i),
}
}
}
pub trait AttributesReader {
fn id(&self) -> &str;
fn source(&self) -> &UriReference;
fn specversion(&self) -> SpecVersion;
fn ty(&self) -> &str;
fn datacontenttype(&self) -> Option<&str>;
fn dataschema(&self) -> Option<&Url>;
fn subject(&self) -> Option<&str>;
fn time(&self) -> Option<&DateTime<Utc>>;
}
pub trait AttributesWriter {
fn set_id(&mut self, id: impl Into<String>) -> String;
fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference;
fn set_type(&mut self, ty: impl Into<String>) -> String;
fn set_subject(&mut self, subject: Option<impl Into<String>>) -> Option<String>;
fn set_time(&mut self, time: Option<impl Into<DateTime<Utc>>>) -> Option<DateTime<Utc>>;
fn set_datacontenttype(&mut self, datacontenttype: Option<impl Into<String>>)
-> Option<String>;
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url>;
}
pub(crate) trait AttributesConverter {
fn into_v03(self) -> AttributesV03;
fn into_v10(self) -> AttributesV10;
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub(crate) enum AttributesIter<'a> {
IterV03(AttributesIntoIteratorV03<'a>),
IterV10(AttributesIntoIteratorV10<'a>),
}
impl<'a> Iterator for AttributesIter<'a> {
type Item = (&'a str, AttributeValue<'a>);
fn next(&mut self) -> Option<Self::Item> {
match self {
AttributesIter::IterV03(a) => a.next(),
AttributesIter::IterV10(a) => a.next(),
}
}
}
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Attributes {
V03(AttributesV03),
V10(AttributesV10),
}
impl AttributesReader for Attributes {
fn id(&self) -> &str {
match self {
Attributes::V03(a) => a.id(),
Attributes::V10(a) => a.id(),
}
}
fn source(&self) -> &UriReference {
match self {
Attributes::V03(a) => a.source(),
Attributes::V10(a) => a.source(),
}
}
fn specversion(&self) -> SpecVersion {
match self {
Attributes::V03(a) => a.specversion(),
Attributes::V10(a) => a.specversion(),
}
}
fn ty(&self) -> &str {
match self {
Attributes::V03(a) => a.ty(),
Attributes::V10(a) => a.ty(),
}
}
fn datacontenttype(&self) -> Option<&str> {
match self {
Attributes::V03(a) => a.datacontenttype(),
Attributes::V10(a) => a.datacontenttype(),
}
}
fn dataschema(&self) -> Option<&Url> {
match self {
Attributes::V03(a) => a.dataschema(),
Attributes::V10(a) => a.dataschema(),
}
}
fn subject(&self) -> Option<&str> {
match self {
Attributes::V03(a) => a.subject(),
Attributes::V10(a) => a.subject(),
}
}
fn time(&self) -> Option<&DateTime<Utc>> {
match self {
Attributes::V03(a) => a.time(),
Attributes::V10(a) => a.time(),
}
}
}
impl AttributesWriter for Attributes {
fn set_id(&mut self, id: impl Into<String>) -> String {
match self {
Attributes::V03(a) => a.set_id(id),
Attributes::V10(a) => a.set_id(id),
}
}
fn set_source(&mut self, source: impl Into<UriReference>) -> UriReference {
match self {
Attributes::V03(a) => a.set_source(source),
Attributes::V10(a) => a.set_source(source),
}
}
fn set_type(&mut self, ty: impl Into<String>) -> String {
match self {
Attributes::V03(a) => a.set_type(ty),
Attributes::V10(a) => a.set_type(ty),
}
}
fn set_subject(&mut self, subject: Option<impl Into<String>>) -> Option<String> {
match self {
Attributes::V03(a) => a.set_subject(subject),
Attributes::V10(a) => a.set_subject(subject),
}
}
fn set_time(&mut self, time: Option<impl Into<DateTime<Utc>>>) -> Option<DateTime<Utc>> {
match self {
Attributes::V03(a) => a.set_time(time),
Attributes::V10(a) => a.set_time(time),
}
}
fn set_datacontenttype(
&mut self,
datacontenttype: Option<impl Into<String>>,
) -> Option<String> {
match self {
Attributes::V03(a) => a.set_datacontenttype(datacontenttype),
Attributes::V10(a) => a.set_datacontenttype(datacontenttype),
}
}
fn set_dataschema(&mut self, dataschema: Option<impl Into<Url>>) -> Option<Url> {
match self {
Attributes::V03(a) => a.set_dataschema(dataschema),
Attributes::V10(a) => a.set_dataschema(dataschema),
}
}
}
impl Attributes {
pub(crate) fn into_v10(self) -> Self {
match self {
Attributes::V03(v03) => Attributes::V10(v03.into_v10()),
_ => self,
}
}
pub(crate) fn into_v03(self) -> Self {
match self {
Attributes::V10(v10) => Attributes::V03(v10.into_v03()),
_ => self,
}
}
pub(crate) fn iter(&self) -> impl Iterator<Item = (&str, AttributeValue)> {
match self {
Attributes::V03(a) => AttributesIter::IterV03(a.into_iter()),
Attributes::V10(a) => AttributesIter::IterV10(a.into_iter()),
}
}
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn default_hostname() -> Url {
Url::parse(
format!(
"http://{}",
hostname::get()
.ok()
.and_then(|s| s.into_string().ok())
.unwrap_or_else(|| "localhost".to_string())
)
.as_ref(),
)
.unwrap()
}
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub(crate) fn default_hostname() -> Url {
use std::str::FromStr;
Url::from_str(
web_sys::window()
.map(|w| w.location().host().ok())
.flatten()
.unwrap_or(String::from("http://localhost"))
.as_str(),
)
.unwrap()
}
#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
pub(crate) fn default_hostname() -> Url {
use std::str::FromStr;
Url::from_str("http://localhost").unwrap()
}