from_attr/
convert_parsed.rs

1use from_attr_core::Array;
2use proc_macro2::{Group, Literal, Punct, TokenTree};
3use syn::{
4    parse_quote,
5    token::{
6        Abstract, And, AndAnd, AndEq, As, Async, At, Auto, Await, Become, Break, Caret, CaretEq,
7        Colon, Comma, Const, Continue, Crate, Do, Dollar, Dot, DotDot, DotDotDot, DotDotEq, Dyn,
8        Else, Enum, Eq, EqEq, Extern, FatArrow, Final, Fn, For, Ge, Gt, If, Impl, In, LArrow, Le,
9        Let, Loop, Lt, Match, Minus, MinusEq, Mod, Move, Mut, Ne, Not, Or, OrEq, OrOr, Override,
10        PathSep, Percent, PercentEq, Plus, PlusEq, Pound, Priv, Pub, Question, RArrow, Ref, Return,
11        SelfType, SelfValue, Semi, Shl, ShlEq, Shr, ShrEq, Slash, SlashEq, Star, StarEq, Static,
12        Struct, Super, Tilde, Trait, Try, Typeof, Underscore, Union, Unsafe, Unsized, Use, Virtual,
13        Where, While, Yield,
14    },
15    Abi, AngleBracketedGenericArguments, BareFnArg, BinOp, BoundLifetimes, ConstParam, Constraint,
16    DeriveInput, Expr, ExprArray, ExprAssign, ExprAsync, ExprBinary, ExprBlock, ExprBreak,
17    ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprIf, ExprIndex,
18    ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath,
19    ExprRange, ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple,
20    ExprUnary, ExprUnsafe, ExprWhile, ExprYield, FieldValue, FieldsNamed, FieldsUnnamed,
21    GenericArgument, GenericParam, Generics, Ident, Index, Lifetime, Lit, LitBool, LitByteStr,
22    LitChar, LitFloat, LitInt, LitStr, Member, Meta, MetaList, MetaNameValue,
23    ParenthesizedGenericArguments, Path, PathSegment, ReturnType, TraitBound, TraitBoundModifier,
24    Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer, TypeMacro, TypeNever,
25    TypeParam, TypeParamBound, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice,
26    TypeTraitObject, TypeTuple, UnOp, Variant, Visibility, WhereClause, WherePredicate,
27};
28
29use crate::PathValue;
30
31/// Helper trait to convert syn types implementing [`Parse`](syn::parse::Parse) like
32/// [`LitStr`](struct@syn::LitStr) to rust types like [`String`]
33///
34/// You probably don't need to implement this trait, as most syn types like
35/// [`LitStr`](struct@syn::LitStr) and [`Type`] or that have a direct equivalent in
36/// those like [`String`], [`char`] or [`f32`] are already implemented. A
37/// special treatment have [`Vec`] which are parsed with the syntax `[a, b, c]`.
38pub trait ConvertParsed: Sized {
39    /// The type this can be converted from
40    type Type;
41
42    /// Convert the [`PathValue<Self::Type>`](crate::PathValue) to self.
43    fn convert(path_value: PathValue<Self::Type>) -> syn::Result<Self>;
44
45    /// Returns the value when this type is not specified.
46    fn default() -> Option<Self> {
47        None
48    }
49
50    /// Returns the value when this type is specified as flag.
51    fn flag() -> Option<Self::Type> {
52        None
53    }
54}
55
56impl<T> ConvertParsed for Option<T>
57where
58    T: ConvertParsed,
59{
60    type Type = T::Type;
61
62    fn convert(path_value: PathValue<Self::Type>) -> syn::Result<Self> {
63        Ok(Some(T::convert(path_value)?))
64    }
65
66    fn default() -> Option<Self> {
67        Some(None)
68    }
69
70    fn flag() -> Option<Self::Type> {
71        T::flag()
72    }
73}
74
75impl<T> ConvertParsed for Vec<T>
76where
77    T: ConvertParsed,
78{
79    type Type = Array<T::Type>;
80
81    fn convert(path_value: PathValue<Self::Type>) -> syn::Result<Self> {
82        let PathValue { path, value } = path_value;
83
84        let mut elems = Vec::new();
85        let mut errors = Vec::new();
86
87        value
88            .elems
89            .into_iter()
90            .for_each(|value| match T::convert(PathValue { path, value }) {
91                Ok(o) => elems.push(o),
92                Err(e) => errors.push(e),
93            });
94
95        match errors.into_iter().reduce(|mut a, b| {
96            a.combine(b);
97            a
98        }) {
99            Some(e) => Err(e),
100            None => Ok(elems),
101        }
102    }
103
104    fn default() -> Option<Self> {
105        Some(Vec::new())
106    }
107}
108
109impl ConvertParsed for bool {
110    type Type = LitBool;
111
112    fn convert(path_value: PathValue<Self::Type>) -> syn::Result<Self> {
113        Ok(path_value.value.value)
114    }
115
116    fn default() -> Option<Self> {
117        Some(false)
118    }
119
120    fn flag() -> Option<Self::Type> {
121        Some(parse_quote!(true))
122    }
123}
124
125macro_rules! get_value {
126    ($from:path => $to:path > $get:path) => {
127        impl ConvertParsed for $to {
128            type Type = $from;
129
130            fn convert(path_value: PathValue<$from>) -> syn::Result<$to> {
131                Ok($get(&path_value.value))
132            }
133        }
134    };
135}
136
137get_value!(LitStr => String > LitStr::value);
138get_value!(LitChar => char > LitChar::value);
139
140macro_rules! parse_value {
141    ($from:path => $($to:path),+ > $parse:path) => {
142        $(
143            impl ConvertParsed for $to {
144                type Type = $from;
145
146                fn convert(path_value: PathValue<$from>) -> syn::Result<$to> {
147                    $parse(&path_value.value)
148                }
149            }
150        )*
151    };
152}
153
154parse_value!(LitInt => u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize > LitInt::base10_parse);
155parse_value!(LitFloat => f32, f64 > LitFloat::base10_parse);
156
157macro_rules! convert_parsed {
158    ($($type:ty),* $(,)?) => {
159        $(
160            impl ConvertParsed for $type {
161                type Type = $type;
162
163                fn convert(path_value: PathValue<Self>) -> syn::Result<Self> {
164                    Ok(path_value.value)
165                }
166            }
167        )*
168    };
169}
170
171convert_parsed![
172    Abi,
173    Abstract,
174    And,
175    AndAnd,
176    AndEq,
177    AngleBracketedGenericArguments,
178    As,
179    Async,
180    At,
181    Auto,
182    Await,
183    BareFnArg,
184    Become,
185    BinOp,
186    BoundLifetimes,
187    Break,
188    Caret,
189    CaretEq,
190    Colon,
191    Comma,
192    Const,
193    ConstParam,
194    Constraint,
195    Continue,
196    Crate,
197    DeriveInput,
198    Do,
199    Dollar,
200    Dot,
201    DotDot,
202    DotDotDot,
203    DotDotEq,
204    Dyn,
205    Else,
206    Enum,
207    Eq,
208    EqEq,
209    Expr,
210    ExprArray,
211    ExprAssign,
212    ExprAsync,
213    ExprBinary,
214    ExprBlock,
215    ExprBreak,
216    ExprCall,
217    ExprCast,
218    ExprClosure,
219    ExprContinue,
220    ExprField,
221    ExprForLoop,
222    ExprIf,
223    ExprIndex,
224    ExprLet,
225    ExprLit,
226    ExprLoop,
227    ExprMacro,
228    ExprMatch,
229    ExprMethodCall,
230    ExprParen,
231    ExprPath,
232    ExprRange,
233    ExprReference,
234    ExprRepeat,
235    ExprReturn,
236    ExprStruct,
237    ExprTry,
238    ExprTryBlock,
239    ExprTuple,
240    ExprUnary,
241    ExprUnsafe,
242    ExprWhile,
243    ExprYield,
244    Extern,
245    FatArrow,
246    FieldValue,
247    FieldsNamed,
248    FieldsUnnamed,
249    Final,
250    Fn,
251    For,
252    Ge,
253    GenericArgument,
254    GenericParam,
255    Generics,
256    Group,
257    Gt,
258    Ident,
259    If,
260    Impl,
261    In,
262    Index,
263    LArrow,
264    Le,
265    Let,
266    Lifetime,
267    Lit,
268    LitBool,
269    LitByteStr,
270    LitChar,
271    LitFloat,
272    LitInt,
273    LitStr,
274    Literal,
275    Loop,
276    Lt,
277    Match,
278    Member,
279    Meta,
280    MetaList,
281    MetaNameValue,
282    Minus,
283    MinusEq,
284    Mod,
285    Move,
286    Mut,
287    Ne,
288    Not,
289    Or,
290    OrEq,
291    OrOr,
292    Override,
293    ParenthesizedGenericArguments,
294    Path,
295    PathSegment,
296    PathSep,
297    Percent,
298    PercentEq,
299    Plus,
300    PlusEq,
301    Pound,
302    Priv,
303    Pub,
304    Punct,
305    Question,
306    RArrow,
307    Ref,
308    Return,
309    ReturnType,
310    SelfType,
311    SelfValue,
312    Semi,
313    Shl,
314    ShlEq,
315    Shr,
316    ShrEq,
317    Slash,
318    SlashEq,
319    Star,
320    StarEq,
321    Static,
322    Struct,
323    Super,
324    Tilde,
325    TokenTree,
326    Trait,
327    TraitBound,
328    TraitBoundModifier,
329    Try,
330    TypeArray,
331    TypeBareFn,
332    TypeGroup,
333    TypeImplTrait,
334    TypeInfer,
335    TypeMacro,
336    TypeNever,
337    TypeParam,
338    TypeParamBound,
339    TypeParen,
340    TypePath,
341    TypePtr,
342    TypeReference,
343    TypeSlice,
344    TypeTraitObject,
345    TypeTuple,
346    Typeof,
347    UnOp,
348    Underscore,
349    Union,
350    Unsafe,
351    Unsized,
352    Use,
353    Variant,
354    Virtual,
355    Visibility,
356    Where,
357    WhereClause,
358    WherePredicate,
359    While,
360    Yield,
361    syn::Macro,
362    syn::token::Box,
363    syn::token::Default,
364    syn::token::Macro,
365    syn::token::Type,
366    Type,
367];
368
369#[cfg_attr(docsrs, doc(cfg(feature = "syn-full")))]
370#[cfg(feature = "syn-full")]
371mod syn_full {
372    use syn::{
373        Arm, Block, File, FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic,
374        ForeignItemType, ImplItem, ImplItemConst, ImplItemMacro, ImplItemType, Item, ItemConst,
375        ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod,
376        ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Label,
377        Pat, RangeLimits, Receiver, Signature, Stmt, TraitItem, TraitItemConst, TraitItemMacro,
378        TraitItemType, UseTree,
379    };
380
381    use super::*;
382
383    convert_parsed![
384        Block,
385        File,
386        FnArg,
387        ForeignItem,
388        ForeignItemFn,
389        ForeignItemMacro,
390        ForeignItemStatic,
391        ForeignItemType,
392        ImplItem,
393        ImplItemConst,
394        ImplItemMacro,
395        ImplItemType,
396        Item,
397        ItemConst,
398        ItemEnum,
399        ItemExternCrate,
400        ItemFn,
401        ItemForeignMod,
402        ItemImpl,
403        ItemMacro,
404        ItemMod,
405        ItemStatic,
406        ItemStruct,
407        ItemTrait,
408        ItemTraitAlias,
409        ItemType,
410        ItemUnion,
411        ItemUse,
412        Label,
413        Pat,
414        RangeLimits,
415        Receiver,
416        Signature,
417        Stmt,
418        TraitItem,
419        TraitItemConst,
420        TraitItemMacro,
421        TraitItemType,
422        UseTree,
423        Arm,
424    ];
425}