use super::{id::Id, DateTime};
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::ops::Deref;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct References(Vec<Reference>);
impl References {
pub fn new(references: Vec<Reference>) -> Self {
Self(references)
}
pub fn into_inner(self) -> Vec<Reference> {
self.0
}
pub fn as_slice(&self) -> &[Reference] {
self.0.as_slice()
}
#[must_use]
pub fn iter(&self) -> std::slice::Iter<Reference> {
self.0.iter()
}
}
impl Deref for References {
type Target = [Reference];
fn deref(&self) -> &Self::Target {
self.0.as_slice()
}
}
impl From<Vec<Reference>> for References {
fn from(v: Vec<Reference>) -> Self {
Self(v)
}
}
impl From<References> for Vec<Reference> {
fn from(r: References) -> Self {
r.0
}
}
impl FromIterator<Reference> for References {
fn from_iter<T: IntoIterator<Item = Reference>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
impl<'a> IntoIterator for &'a References {
type Item = &'a Reference;
type IntoIter = std::slice::Iter<'a, Reference>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for References {
type Item = Reference;
type IntoIter = std::vec::IntoIter<Reference>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Reference {
pub sender: Id,
pub identifier: Id,
pub sent: DateTime,
}
impl std::fmt::Display for Reference {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{},{},{}", self.sender, self.identifier, self.sent)
}
}
#[derive(thiserror::Error, Debug)]
pub enum ReferenceError {
#[error("invalid format: {0:?}")]
Format(String),
#[error("invalid sender: {0}")]
Sender(crate::id::InvalidIdError),
#[error("invalid identifier: {0}")]
Identifier(crate::id::InvalidIdError),
#[error("invalid sent timestamp: {0}")]
Sent(chrono::ParseError),
}
impl std::str::FromStr for Reference {
type Err = ReferenceError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match {
let mut i = s.split(',');
(
i.next().map(|v| Id::new(v).map_err(ReferenceError::Sender)),
i.next()
.map(|v| Id::new(v).map_err(ReferenceError::Identifier)),
i.next().map(|v| v.parse().map_err(ReferenceError::Sent)),
i.next(),
)
} {
(Some(sender), Some(identifier), Some(sent), None) => Ok(Reference {
sender: sender?,
identifier: identifier?,
sent: sent?,
}),
_ => Err(ReferenceError::Format(s.into())),
}
}
}
impl std::str::FromStr for References {
type Err = ReferenceError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.split_whitespace()
.map(|reference| reference.parse())
.collect::<Result<Vec<_>, _>>()
.map(Self)
}
}
impl std::fmt::Display for References {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
for (i, reference) in self.0.iter().enumerate() {
let space = if i == 0 { "" } else { " " };
write!(f, "{}{}", space, reference)?;
}
Ok(())
}
}
impl Serialize for References {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for References {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let str = <std::borrow::Cow<str>>::deserialize(deserializer)?;
str.parse().map_err(D::Error::custom)
}
}