attr_parser_fn/meta/
utils.rs1use 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}