Skip to main content

object_rainbow/
extra_option.rs

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