1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 use crate::util::kw;
6 use proc_macro2::TokenStream;
7 use quote::{quote, ToTokens};
8 use syn::{
9 bracketed, parenthesized,
10 parse::{Nothing, Parse, ParseStream},
11 token::{Bracket, Paren},
12 Lit,
13 };
14
15 /// Default value
16 #[derive(Clone)]
17 pub enum DefaultValue {
18 Literal(Lit),
19 None(kw::None),
20 Some {
21 some: kw::Some,
22 paren: Paren,
23 inner: Box<DefaultValue>,
24 },
25 EmptySeq(Bracket),
26 }
27
28 impl ToTokens for DefaultValue {
to_tokens(&self, tokens: &mut TokenStream)29 fn to_tokens(&self, tokens: &mut TokenStream) {
30 match self {
31 DefaultValue::Literal(lit) => lit.to_tokens(tokens),
32 DefaultValue::None(kw) => kw.to_tokens(tokens),
33 DefaultValue::Some { inner, .. } => tokens.extend(quote! { Some(#inner) }),
34 DefaultValue::EmptySeq(_) => tokens.extend(quote! { [] }),
35 }
36 }
37 }
38
39 impl Parse for DefaultValue {
parse(input: ParseStream<'_>) -> syn::Result<Self>40 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
41 let lookahead = input.lookahead1();
42 if lookahead.peek(kw::None) {
43 let none_kw: kw::None = input.parse()?;
44 Ok(Self::None(none_kw))
45 } else if lookahead.peek(kw::Some) {
46 let some: kw::Some = input.parse()?;
47 let content;
48 let paren = parenthesized!(content in input);
49 Ok(Self::Some {
50 some,
51 paren,
52 inner: content.parse()?,
53 })
54 } else if lookahead.peek(Bracket) {
55 let content;
56 let bracket = bracketed!(content in input);
57 content.parse::<Nothing>()?;
58 Ok(Self::EmptySeq(bracket))
59 } else {
60 Ok(Self::Literal(input.parse()?))
61 }
62 }
63 }
64
65 impl DefaultValue {
metadata_calls(&self) -> syn::Result<TokenStream>66 fn metadata_calls(&self) -> syn::Result<TokenStream> {
67 match self {
68 DefaultValue::Literal(Lit::Int(i)) if !i.suffix().is_empty() => Err(
69 syn::Error::new_spanned(i, "integer literals with suffix not supported here"),
70 ),
71 DefaultValue::Literal(Lit::Float(f)) if !f.suffix().is_empty() => Err(
72 syn::Error::new_spanned(f, "float literals with suffix not supported here"),
73 ),
74
75 DefaultValue::Literal(Lit::Str(s)) => Ok(quote! {
76 .concat_value(::uniffi::metadata::codes::LIT_STR)
77 .concat_str(#s)
78 }),
79 DefaultValue::Literal(Lit::Int(i)) => {
80 let digits = i.base10_digits();
81 Ok(quote! {
82 .concat_value(::uniffi::metadata::codes::LIT_INT)
83 .concat_str(#digits)
84 })
85 }
86 DefaultValue::Literal(Lit::Float(f)) => {
87 let digits = f.base10_digits();
88 Ok(quote! {
89 .concat_value(::uniffi::metadata::codes::LIT_FLOAT)
90 .concat_str(#digits)
91 })
92 }
93 DefaultValue::Literal(Lit::Bool(b)) => Ok(quote! {
94 .concat_value(::uniffi::metadata::codes::LIT_BOOL)
95 .concat_bool(#b)
96 }),
97
98 DefaultValue::Literal(_) => Err(syn::Error::new_spanned(
99 self,
100 "this type of literal is not currently supported as a default",
101 )),
102
103 DefaultValue::EmptySeq(_) => Ok(quote! {
104 .concat_value(::uniffi::metadata::codes::LIT_EMPTY_SEQ)
105 }),
106
107 DefaultValue::None(_) => Ok(quote! {
108 .concat_value(::uniffi::metadata::codes::LIT_NONE)
109 }),
110
111 DefaultValue::Some { inner, .. } => {
112 let inner_calls = inner.metadata_calls()?;
113 Ok(quote! {
114 .concat_value(::uniffi::metadata::codes::LIT_SOME)
115 #inner_calls
116 })
117 }
118 }
119 }
120 }
121
default_value_metadata_calls(default: &Option<DefaultValue>) -> syn::Result<TokenStream>122 pub fn default_value_metadata_calls(default: &Option<DefaultValue>) -> syn::Result<TokenStream> {
123 Ok(match default {
124 Some(default) => {
125 let metadata_calls = default.metadata_calls()?;
126 quote! {
127 .concat_bool(true)
128 #metadata_calls
129 }
130 }
131 None => quote! { .concat_bool(false) },
132 })
133 }
134