Skip to main content

tinyklv_impl/
lib.rs

1// --------------------------------------------------
2// mods
3// --------------------------------------------------
4#[macro_use]
5mod err;
6mod ast;
7mod ctxt;
8mod expand;
9
10// --------------------------------------------------
11// external
12// --------------------------------------------------
13use syn::{parse_macro_input, DeriveInput};
14use thiserror::Error;
15
16// --------------------------------------------------
17// re-exports
18// --------------------------------------------------
19use crate::ast::symbol;
20use crate::ctxt::Ctxt;
21
22// --------------------------------------------------
23// constants
24// --------------------------------------------------
25const CRATE_NAME: &str = "tinyklv";
26const DERIVE_NAME: &str = "Klv";
27const ATTR_NAME: &str = "klv";
28
29#[proc_macro_derive(Klv, attributes(klv))]
30/// [`tinyklv`](crate) proc-macro
31pub fn klv_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
32    let input = parse_macro_input!(input as DeriveInput);
33    expand::derive(&input)
34        .unwrap_or_else(syn::Error::into_compile_error)
35        .into()
36}
37
38#[derive(Debug, Error)]
39/// [`tinyklv`](crate) proc-macro errors
40enum Error {
41    // --------------------------------------------------
42    // container parsing
43    // --------------------------------------------------
44    #[error("\
45        {c} does not support #[derive({d})] for {0}s.",
46        c = CRATE_NAME,
47        d = DERIVE_NAME,
48    )]
49    UnsupportedContainer(String),
50
51    #[error("\
52        {c} does not support #[derive({d})] for structs with unnamed fields (tuple-structs).",
53        c = CRATE_NAME,
54        d = DERIVE_NAME,
55    )]
56    UnsupportedUnnamedStructs,
57
58    #[error("\
59        {c} does not support #[derive({d})] for unit-structs.",
60        c = CRATE_NAME,
61        d = DERIVE_NAME,
62    )]
63    UnsupportedUnitStructs,
64
65    // --------------------------------------------------
66    // container attributes
67    // --------------------------------------------------
68    #[error("\
69        Unknown attribute: `{0}`.
70Expected {s}.",
71        s = symbol::CONT_SYMBOLS,
72    )]
73    UnknownContainerAttribute(String),
74
75    #[error("\
76        Unknown list attribute: `{0}(..)`.
77Options include {s}.",
78        s = symbol::CONT_LIST_SYMBOLS,
79    )]
80    UnknownContainerListAttribute(String),
81
82    #[error("\
83        Unknown name-value attribute: `{0} = <value>`.
84Options include {s}.",
85        s = symbol::CONT_NV_SYMBOLS,
86    )]
87    UnknownContainerNameValueAttribute(String),
88
89    #[error("\
90        Expected `{0}` to be a list attribute: `#[{k}({0}(..),)]`.",
91        k = symbol::KLV_ATTR,
92    )]
93    ExpectedAsList(String),
94
95    #[error("\
96        Expected `{0}` to be a name-value attribute: `#[{k}({0} = <..>,)]`.",
97        k = symbol::KLV_ATTR,
98    )]
99    ExpectedAsNameValue(String),
100
101    #[error("\
102        Expected `{0}` to be a path attribute: `#[{k}({0},)]`.",
103        k = symbol::KLV_ATTR,
104    )]
105    ExpectedAsPath(String),
106
107    // --------------------------------------------------
108    // stream
109    // --------------------------------------------------
110    #[error("\
111        Duplicate `{s}` attribute. Only one stream-type per struct is supported.",
112        s = symbol::STREAM,
113    )]
114    DuplicateStream,
115
116    // --------------------------------------------------
117    // sentinel
118    // --------------------------------------------------
119    #[error("\
120        Duplicate `{s}` attribute. Currently, only one sentinel is supported per struct.",
121        s = symbol::SENTINEL,
122    )]
123    DuplicateSentinel,
124
125    // --------------------------------------------------
126    // key / len
127    // --------------------------------------------------
128    #[error("\
129        Missing required `{s}` field to describe how to encode/decode key values.",
130        s = symbol::KEY,
131    )]
132    MissingKey,
133
134    #[error("\
135        Missing required `{s}` field to describe how to encode/decode length values.",
136        s = symbol::LENGTH,
137    )]
138    MissingLength,
139
140    #[error("\
141        Duplicate `{s}` attribute. Only one method of encoding and decoding keys is allowed.",
142        s = symbol::KEY,
143    )]
144    DuplicateKey,
145
146    #[error("\
147        Duplicate `{s}` attribute. Only one method of encoding and decoding lengths is allowed.",
148        s = symbol::LENGTH,
149    )]
150    DuplicateLength,
151
152    #[error("\
153        Unknown field `{0}` in {k}/{l}.
154Expected `{e} = <..>` or `{d} = <..>`.",
155        k = symbol::KEY,
156        l = symbol::LENGTH,
157        e = symbol::ENCODER,
158        d = symbol::DECODER,
159    )]
160    UnknownKeyLenField(String),
161
162    #[error("\
163        Duplicate `{e}` field. Only one method of encoding {k}/{l} is allowed.",
164        e = symbol::ENCODER,
165        k = symbol::KEY,
166        l = symbol::LENGTH,
167    )]
168    DuplicateEncoderInKeyLen,
169
170    #[error("\
171        Duplicate `{d}` field. Only one method of decoding {k}/{l} is allowed.",
172        d = symbol::DECODER,
173        k = symbol::KEY,
174        l = symbol::LENGTH,
175    )]
176    DuplicateDecoderInKeyLen,
177
178    #[error("\
179        Missing required `{e}` field for `{0}`.
180If no encoding is required, use `#[{a}({aue})]`.",
181        e = symbol::ENCODER,
182        a = symbol::KLV_ATTR,
183        aue = symbol::ALLOW_UNIMPLEMENTED_ENCODE,
184    )]
185    MissingEncInKeyLen(String),
186
187    #[error("\
188        Missing required `{d}` field for `{0}`.
189If no decoding is required, use `#[{a}({aud})]`.",
190        d = symbol::DECODER,
191        a = symbol::KLV_ATTR,
192        aud = symbol::ALLOW_UNIMPLEMENTED_DECODE,
193    )]
194    MissingDecInKeyLen(String),
195
196    // --------------------------------------------------
197    // default
198    // --------------------------------------------------
199    #[error("\
200        Unknown default field: `{0}`.
201Expected {s}.",
202        s = symbol::CONT_DEFAULT_LIST_SYMBOLS,
203    )]
204    UnknownDefaultField(String),
205
206    #[error("\
207        Missing required `{s}` field for `{d}`.",
208        s = symbol::TYPE,
209        d = symbol::DEFAULT,
210    )]
211    MissingTypeInDefault,
212
213    #[error("\
214        Both `{e}` and `{d}` fields are missing: at least one is required.",
215        e = symbol::ENCODER,
216        d = symbol::DECODER,
217    )]
218    MissingEncDecInDefault,
219
220    #[error("\
221        Duplicate `{s}` field.
222To add multiple default encoder/decoders for types, add another `{d}` attribute.",
223        s = symbol::TYPE,
224        d = symbol::DEFAULT,
225    )]
226    DuplicateTypeInDefault,
227
228    #[error("\
229        Duplicate `{s}` field. Only one default encoder is allowed for {0} type.
230To add ways to encode said type, they must be done on a field-by-field basis and not using the `{d}` attribute.",
231        s = symbol::ENCODER,
232        d = symbol::DEFAULT,
233    )]
234    DuplicateEncoderInDefault(String),
235
236    #[error("\
237        Duplicate `{s}` field. Only one default decoder is allowed for {0} type.
238To add ways to decode said type, they must be done on a field-by-field basis and not using the `{d}` attribute.",
239        s = symbol::DECODER,
240        d = symbol::DEFAULT,
241    )]
242    DuplicateDecoderInDefault(String),
243
244    #[error("\
245        Duplicate `{s}` field. Only required once, defaults to `false`.",
246        s = symbol::VARIABLE_LENGTH,
247    )]
248    DuplicateVariableLengthInDefault,
249
250    #[error("\
251        Duplicate '{1}' found for `{d}({t} = {0})`. Only one default {1} is allowed per type.",
252        d = symbol::DEFAULT,
253        t = symbol::TYPE,
254    )]
255    DuplicateDefault(String, String),
256
257    // --------------------------------------------------
258    // field
259    // --------------------------------------------------
260    #[error("\
261        Malformed `{s}` field. Expecting list: `{s}(..)`
262Options include {fs}.",
263        s = symbol::KLV_ATTR,
264        fs = symbol::FIELD_SYMBOLS,
265    )]
266    MalformedField,
267
268    #[error("\
269        Unknown field: `{0}`.
270Expected {s}.",
271        s = symbol::FIELD_SYMBOLS
272    )]
273    UnknownFieldField(String),
274
275    #[error("\
276        Duplicate `{s}` field.
277Currently only one key per field is supported.",
278        s = symbol::KEY,
279    )]
280    DuplicateKeyInField,
281
282    #[error("\
283        Duplicate `{s}` field.",
284        s = symbol::ENCODER,
285    )]
286    DuplicateEncoderInField,
287
288    #[error("\
289        Duplicate `{s}` field.",
290        s = symbol::DECODER,
291    )]
292    DuplicateDecoderInField,
293
294    #[error("\
295        Duplicate `{s}` field. Only required once, will default to `false`.",
296        s = symbol::VARIABLE_LENGTH,
297    )]
298    DuplicateVariableLengthInField,
299
300    #[error("\
301        Duplicate `{s}` field.",
302        s = symbol::LATEBIND,
303    )]
304    DuplicateLatebindInField,
305
306    #[error("\
307        Duplicate `{s}` field.",
308        s = symbol::DEFAULT_VALUE,
309    )]
310    DuplicateDefaultInField,
311
312    #[error("\
313        Missing required `{s}` field.",
314        s = symbol::KEY,
315    )]
316    MissingKeyInField,
317
318    #[error("\
319No encoder is found for field `{0}: {1}`.
320
321If encoding is not required, use `#[{k}({aue})]` on the struct.
322
323Otherwise, you can:
324    a. add a default encoder for all `{1}` types using `#[{k}({df}({t} = {1}, {e} = <..>)))]` on the struct
325    b. add an encoder to `{0}` using `#[{k}({e} = <..>)]`
326    c. set `#[{k}({fi})]` on the struct to fall back to try and use `tinyklv::EncodeValue` trait implementation",
327        k = symbol::KLV_ATTR,
328        df = symbol::DEFAULT,
329        t = symbol::TYPE,
330        e = symbol::ENCODER,
331        aue = symbol::ALLOW_UNIMPLEMENTED_ENCODE,
332        fi = symbol::TRAIT_FALLBACK,
333    )]
334    UnimplementedEncode(String, String),
335
336    #[error("\
337No decoder is found for field `{0}: {1}`.
338
339If decoding is not required, use `#[{k}({aud})]` on the struct.
340
341Otherwise, you can:
342    a. add a default decoder for all `{1}` types using `#[{k}({df}({t} = {1}, {d} = <..>)))]` on the struct
343    b. add a decoder to `{0}` using `#[{k}({d} = <..>)]`
344    c. set `#[{k}({fi})]` on the struct to fall back to try and use `tinyklv::DecodeValue` trait implementation",
345        k = symbol::KLV_ATTR,
346        df = symbol::DEFAULT,
347        t = symbol::TYPE,
348        d = symbol::DECODER,
349        aud = symbol::ALLOW_UNIMPLEMENTED_DECODE,
350        fi = symbol::TRAIT_FALLBACK,
351    )]
352    UnimplementedDecode(String, String),
353
354    #[error("\
355Field `{0}: {1}` has `{v} = true` but no `{d} = ..` was set.
356The trait fallback (`<{1} as ::tinyklv::DecodeValue<..>>::decode_value`) has no length argument - \
357supply an explicit `{d}` or remove `{v}`.",
358        v = symbol::VARIABLE_LENGTH,
359        d = symbol::DECODER,
360    )]
361    VarlenFallbackRequiresExplicitDec(String, String),
362}
363/// [`Error`] implementation
364impl Error {
365    fn as_str(&self) -> std::borrow::Cow<'_, str> {
366        std::borrow::Cow::Owned(self.to_string())
367    }
368}