attr_parser_fn/meta/
utils.rs

1use std::fmt::Write;
2
3use syn::{meta::ParseNestedMeta, Result};
4
5use crate::{Marker, ParseArgs};
6
7use super::{list, List, ParseMeta, ParseMetaUnnamed};
8
9pub trait ParseMetaExt: ParseMeta + Sized {
10    fn optional(self) -> Optional<Self> {
11        Optional(self)
12    }
13
14    fn map<F, R>(self, map: F) -> Map<Self, F>
15    where
16        F: FnOnce(Self::Output) -> R,
17    {
18        Map { parser: self, map }
19    }
20
21    fn value<U>(self, value: U) -> impl ParseMeta<Output = U> {
22        self.map(move |_| value)
23    }
24}
25
26impl<T> ParseMetaExt for T where T: ParseMeta + Sized {}
27
28pub struct Optional<T>(T);
29
30impl<T> ParseMeta for Optional<T>
31where
32    T: ParseMeta,
33{
34    type Output = Option<T::Output>;
35
36    fn conflict_alternative_arm(&self, f: &mut dyn Write) -> std::fmt::Result {
37        self.0.conflict_alternative_arm(f)
38    }
39
40    fn parse(&mut self, nested: &ParseNestedMeta) -> Result<bool> {
41        self.0.parse(nested)
42    }
43
44    fn finish(self) -> Result<Self::Output> {
45        let opt = if self.0.ok_to_finish() {
46            Some(self.0.finish()?)
47        } else {
48            None
49        };
50
51        Ok(opt)
52    }
53
54    fn ok_to_finish(&self) -> bool {
55        true
56    }
57}
58
59pub struct Map<T, F> {
60    parser: T,
61    map: F,
62}
63
64impl<T, F, R> ParseMeta for Map<T, F>
65where
66    T: ParseMeta,
67    F: FnOnce(T::Output) -> R,
68{
69    type Output = R;
70
71    fn parse(&mut self, nested: &ParseNestedMeta) -> Result<bool> {
72        self.parser.parse(nested)
73    }
74
75    fn conflict_alternative_arm(&self, f: &mut dyn Write) -> std::fmt::Result {
76        self.parser.conflict_alternative_arm(f)
77    }
78
79    fn finish(self) -> Result<Self::Output> {
80        self.parser.finish().map(self.map)
81    }
82
83    fn ok_to_finish(&self) -> bool {
84        self.parser.ok_to_finish()
85    }
86}
87
88pub fn meta_list<P>(p: P) -> MetaList<P>
89where
90    P: ParseMeta,
91{
92    MetaList(list(ParseArgs::new().meta(p)))
93}
94
95pub struct MetaList<P>(List<ParseArgs<Marker<()>, Marker<()>, Marker<()>, P>>)
96where
97    P: ParseMeta;
98
99impl<P> ParseMetaUnnamed for MetaList<P>
100where
101    P: ParseMeta,
102{
103    type Output = P::Output;
104
105    fn parse(&mut self, nested: &ParseNestedMeta) -> Result<bool> {
106        self.0.parse(nested)
107    }
108
109    fn ok_to_finish(&self) -> bool {
110        self.0.ok_to_finish()
111    }
112
113    fn finish(self) -> Option<Self::Output> {
114        self.0.finish().map(|x| x.meta)
115    }
116}