Skip to main content

object_rainbow/
extra_option.rs

1use crate::{extras::Extras, *};
2
3#[derive(
4    Enum, Debug, Clone, PartialEq, ListHashes, Topological, Tagged, CanonicalExtra, ToCanonicalExtra,
5)]
6#[rainbow(untagged)]
7pub enum ExtraOption<T, E = ()> {
8    Some(T),
9    None(Extras<E>),
10}
11
12impl<T, E> ExtraOption<T, E> {
13    pub fn as_ref(&self) -> Option<&T> {
14        match self {
15            Self::Some(value) => Some(value),
16            Self::None(_) => None,
17        }
18    }
19
20    fn new(extra: Extras<E>, value: Option<T>) -> Self {
21        match value {
22            Some(value) => Self::Some(value),
23            None => Self::None(extra),
24        }
25    }
26
27    pub fn from_tuple((extra, value): (Extras<E>, Option<T>)) -> Self {
28        Self::new(extra, value)
29    }
30
31    pub fn none(extra: E) -> Self {
32        Self::None(Extras(extra))
33    }
34}
35
36pub trait ExtraNoneOutput<E>: Sized {
37    fn extra_some_output(&self, output: &mut (impl ?Sized + Output));
38    fn extra_none_output(extra: &E, output: &mut (impl ?Sized + Output));
39    fn extra_option_output(option: &ExtraOption<Self, E>, output: &mut (impl ?Sized + Output)) {
40        match option {
41            ExtraOption::Some(value) => value.extra_some_output(output),
42            ExtraOption::None(extra) => Self::extra_none_output(extra, output),
43        }
44    }
45}
46
47impl<T: OptionOutput, E> ExtraNoneOutput<E> for T {
48    fn extra_some_output(&self, output: &mut (impl ?Sized + Output)) {
49        T::to_option_output(Some(self), output);
50    }
51
52    fn extra_none_output(_: &E, output: &mut (impl ?Sized + Output)) {
53        T::to_option_output(None, output);
54    }
55
56    fn extra_option_output(option: &ExtraOption<Self, E>, output: &mut (impl ?Sized + Output)) {
57        T::to_option_output(option.as_ref(), output);
58    }
59}
60
61impl<T: ExtraNoneOutput<E>, E> ToOutput for ExtraOption<T, E> {
62    fn to_output(&self, output: &mut (impl ?Sized + Output)) {
63        T::extra_option_output(self, output);
64    }
65}
66
67impl<T: OptionOutput + InlineOutput, E> InlineOutput for ExtraOption<T, E> {}
68
69impl<T: OptionParse<I>, I: PointInput> Parse<I> for ExtraOption<T, I::Extra> {
70    fn parse(input: I) -> crate::Result<Self> {
71        input.parse().map(Self::from_tuple)
72    }
73}
74
75impl<T: OptionParseInline<I>, I: PointInput> ParseInline<I> for ExtraOption<T, I::Extra> {
76    fn parse_inline(input: &mut I) -> crate::Result<Self> {
77        input.parse_inline().map(Self::from_tuple)
78    }
79}