use std::fmt;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Terminator(pub er7::Terminator);
impl From<er7::Terminator> for Terminator {
fn from(inner: er7::Terminator) -> Terminator {
Terminator(inner)
}
}
impl From<Terminator> for er7::Terminator {
fn from(outer: Terminator) -> er7::Terminator {
outer.0
}
}
impl Serialize for Terminator {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let name = match self.0 {
er7::Terminator::Cr => "Cr",
er7::Terminator::Lf => "Lf",
er7::Terminator::CrLf => "CrLf",
};
serializer.serialize_str(name)
}
}
struct TerminatorVisitor;
impl Visitor<'_> for TerminatorVisitor {
type Value = Terminator;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(r#""Cr", "Lf", or "CrLf""#)
}
fn visit_str<E>(self, value: &str) -> Result<Terminator, E>
where
E: de::Error,
{
match value {
"Cr" => Ok(Terminator(er7::Terminator::Cr)),
"Lf" => Ok(Terminator(er7::Terminator::Lf)),
"CrLf" => Ok(Terminator(er7::Terminator::CrLf)),
other => Err(de::Error::unknown_variant(other, &["Cr", "Lf", "CrLf"])),
}
}
}
impl<'de> Deserialize<'de> for Terminator {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(TerminatorVisitor)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trips_every_variant() {
for terminator in [
er7::Terminator::Cr,
er7::Terminator::Lf,
er7::Terminator::CrLf,
] {
let wrapped = Terminator(terminator);
let json = serde_json::to_string(&wrapped).unwrap();
let back: Terminator = serde_json::from_str(&json).unwrap();
assert_eq!(back.0, terminator);
}
}
#[test]
fn rejects_an_unknown_variant() {
assert!(serde_json::from_str::<Terminator>(r#""Sixteen""#).is_err());
}
}