use std::fmt::{Debug, Write};
#[cfg(feature = "parse")]
use oxvg_parse::{error::Error, Parse, Parser};
#[cfg(feature = "serialize")]
use oxvg_serialize::{error::PrinterError, Printer, ToValue};
#[derive(Debug, PartialEq)]
pub enum Inheritable<T: Debug + PartialEq> {
Defined(T),
Inherited,
}
impl<T: Clone + Debug + PartialEq> Clone for Inheritable<T> {
fn clone(&self) -> Self {
match self {
Self::Defined(t) => Self::Defined(t.clone()),
Self::Inherited => Self::Inherited,
}
}
}
impl<T: Debug + PartialEq> Inheritable<T> {
pub fn map<'a, U: Debug + PartialEq, F>(&'a self, f: F) -> Inheritable<U>
where
F: FnOnce(&'a T) -> U,
{
match self {
Self::Defined(x) => Inheritable::Defined(f(x)),
Self::Inherited => Inheritable::Inherited,
}
}
pub fn map_mut<'a, U: Debug + PartialEq, F>(&'a mut self, f: F) -> Inheritable<U>
where
F: FnOnce(&'a mut T) -> U,
{
match self {
Self::Defined(x) => Inheritable::Defined(f(x)),
Self::Inherited => Inheritable::Inherited,
}
}
pub fn option(self) -> Option<T> {
match self {
Self::Defined(x) => Some(x),
Self::Inherited => None,
}
}
pub fn option_ref(&self) -> Option<&T> {
match self {
Self::Defined(x) => Some(x),
Self::Inherited => None,
}
}
pub fn option_mut(&mut self) -> Option<&mut T> {
match self {
Self::Defined(x) => Some(x),
Self::Inherited => None,
}
}
}
#[cfg(feature = "parse")]
impl<'input, T: Parse<'input> + Debug + PartialEq> Parse<'input> for Inheritable<T> {
fn parse<'t>(input: &mut Parser<'input>) -> Result<Self, Error<'input>> {
input
.try_parse(|input| {
input
.expect_ident_matching("inherit")
.map(|()| Self::Inherited)
})
.or_else(|_| T::parse(input).map(Self::Defined))
}
}
#[cfg(feature = "serialize")]
impl<T: ToValue + Debug + PartialEq> Inheritable<Box<T>> {
pub fn write_value<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
where
W: Write,
{
match self {
Self::Inherited => dest.write_str("inherit"),
Self::Defined(inner) => inner.write_value(dest),
}
}
}
#[cfg(feature = "serialize")]
impl<T: ToValue + Debug + PartialEq> ToValue for Inheritable<T> {
fn write_value<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
where
W: Write,
{
match self {
Self::Inherited => dest.write_str("inherit"),
Self::Defined(inner) => inner.write_value(dest),
}
}
}
pub fn map_ref_mut<T: Debug + PartialEq>(
inheritable: std::cell::RefMut<Inheritable<T>>,
) -> Option<std::cell::RefMut<T>> {
std::cell::RefMut::filter_map(inheritable, Inheritable::option_mut).ok()
}
#[test]
fn inheritable() {
assert_eq!(
Inheritable::<f64>::parse_string("10"),
Ok(Inheritable::Defined(10.0))
);
assert_eq!(
Inheritable::<f64>::parse_string("inherit"),
Ok(Inheritable::Inherited)
);
assert_eq!(
Inheritable::<f64>::parse_string(" inherit "),
Ok(Inheritable::Inherited)
);
assert_eq!(
Inheritable::<f64>::parse_string("junk"),
Err(Error::InvalidNumber)
);
}