1use proc_macro::TokenStream;
5use proc_macro2::Span;
6use quote::quote;
7use syn::{self, DeriveInput, Data, Attribute, Ident, Meta, NestedMeta, Lit, LitByteStr, Generics, ImplGenerics, TypeGenerics, GenericParam, TypeParam};
8use std::borrow::Cow;
9use std::mem;
10use std::collections::{HashMap, HashSet};
11
12const HEX_DIGITS: [u8; 16] = [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F'];
13
14fn escape(s: &str) -> Cow<str>
16{ let bytes = s.as_bytes();
17 if let Some(mut pos) = bytes.iter().position(|c| match *c {b'"' | b'\\' | 0..=31 => true, _ => false})
18 { let mut buffer = Vec::with_capacity(bytes.len() + 8);
19 let mut from = 0;
20 loop
21 { buffer.extend_from_slice(&bytes[from .. pos]);
22 let c = bytes[pos];
23 if c >= 32
24 { buffer.push(b'\\');
25 buffer.push(c);
26 }
27 else
28 { match c
29 { 9 =>
30 { buffer.push(b'\\');
31 buffer.push(b't');
32 }
33 13 =>
34 { buffer.push(b'\\');
35 buffer.push(b'r');
36 }
37 10 =>
38 { buffer.push(b'\\');
39 buffer.push(b'n');
40 }
41 8 =>
42 { buffer.push(b'\\');
43 buffer.push(b'b');
44 }
45 12 =>
46 { buffer.push(b'\\');
47 buffer.push(b'f');
48 }
49 _ =>
50 { buffer.push(b'\\');
51 buffer.push(b'u');
52 buffer.push(b'0');
53 buffer.push(b'0');
54 buffer.push(HEX_DIGITS[(c >> 4) as usize]);
55 buffer.push(HEX_DIGITS[(c & 0xF) as usize]);
56 }
57 }
58 }
59 from = pos + 1;
60 if let Some(new_pos) = &bytes[from ..].iter().position(|c| match *c {b'"' | b'\\' | 0..=31 => true, _ => false})
61 { pos = from + *new_pos;
62 }
63 else
64 { buffer.extend_from_slice(&bytes[from .. ]);
65 break;
66 }
67 }
68 Cow::Owned(String::from_utf8(buffer).unwrap())
69 }
70 else
71 { Cow::Borrowed(s)
72 }
73}
74
75#[proc_macro_derive(TryFromJson, attributes(json, json_ignore))]
80pub fn derive_try_from_json(input: TokenStream) -> TokenStream
81{ let ast: &mut DeriveInput = &mut syn::parse(input).unwrap();
82 match impl_try_from_json(ast)
83 { Ok(ts) => ts,
84 Err(error) =>
85 { panic!("{}", error);
86 }
87 }
88}
89
90fn impl_try_from_json(ast: &mut DeriveInput) -> Result<TokenStream, String>
91{ let name = &ast.ident;
92 let mut json_ignore = HashMap::new();
93 let mut is_ignore_all = get_json_ignore(&ast.attrs, usize::MAX, &mut json_ignore, false)?;
94 let mut variants = Vec::new();
95 let mut enum_variant_cannot_be = HashMap::new();
96 let mut code = quote!();
97 let mut code_2 = quote!();
98 let mut code_3 = quote!();
99 match &ast.data
100 { Data::Struct(data_struct) =>
101 { for field in data_struct.fields.iter()
102 { if let Some(ref field_name) = field.ident
103 { let mut json_str = get_json_name(&field.attrs, "struct field")?.unwrap_or_else(|| field_name.to_string());
104 let is_transient = json_str.is_empty();
105 if is_transient
106 { json_str = field_name.to_string();
107 }
108 if !is_transient
110 { code = quote!( #code let mut #field_name = None; );
111 }
112 let b = LitByteStr::new(json_str.as_bytes(), Span::call_site());
114 if !is_transient
115 { code_2 = quote!( #code_2 #b => #field_name = reader.read_prop(#json_str)?, );
116 }
117 else
118 { code_2 = quote!( #code_2 #b => {let skip: () = reader.read_prop(#json_str)?;}, );
119 }
120 if !is_transient
122 { code_3 = quote!( #code_3 #field_name: #field_name.unwrap_or_default(), );
123 }
124 else
125 { code_3 = quote!( #code_3 #field_name: Default::default(), );
126 }
127 }
128 }
129 code_3 = quote!( let result = Self{#code_3} );
130 },
131 Data::Enum(data_enum) =>
132 { let enum_json_name = get_json_name(&ast.attrs, "enum")?.unwrap_or_default();
133 let mut fields = Vec::new();
134 let mut fields_by_json_name = HashMap::new();
135 for (n_variant, variant) in data_enum.variants.iter().enumerate()
137 { let variant_name = &variant.ident;
138 let (variant_name_str, json_names) = get_json_name_for_enum_variant(&variant.attrs, variant_name, variant.fields.len())?;
139 is_ignore_all = get_json_ignore(&variant.attrs, n_variant, &mut json_ignore, is_ignore_all)?;
140 let variant_name_str = variant_name_str.unwrap_or_else(|| variant_name.to_string());
141 let mut n_field = 0;
142 for json_name in &json_names
143 { if !json_name.is_empty() { let cur = fields_by_json_name.get_mut(json_name);
145 match cur
146 { None =>
147 { fields_by_json_name.insert(json_name.clone(), (Ident::new(&format!("val_{}_{}", variant_name, n_field), Span::call_site()), 1));
148 }
149 Some(cur) =>
150 { cur.1 += 1;
151 }
152 }
153 let (val_field, n_occurances) = fields_by_json_name.get(json_name).unwrap();
154 fields.push((variants.len(), json_name.clone(), val_field.clone(), *n_occurances>1));
155 n_field += 1;
156 }
157 else
158 { fields.push((variants.len(), json_name.clone(), Ident::new("u", Span::call_site()), false));
159 }
160 }
161 variants.push((variant_name, variant_name_str, json_names));
162 }
163 for (json_name, ignore_in_variants) in &json_ignore
165 { if ignore_in_variants.len() != variants.len() && !ignore_in_variants.contains(&usize::MAX)
166 { for (n_variant, (variant_name, _variant_name_str, json_names)) in variants.iter().enumerate()
168 { if !ignore_in_variants.contains(&n_variant) && !json_names.contains(json_name)
169 { let enum_name = format!("{}::{}", name, variant_name);
171 let var_name = Ident::new(&format!("enum_variant_cannot_be_{}", n_variant), Span::call_site());
172 let code_c = quote!
173 ( if let Some(prop_name) = #var_name
174 { return Err(reader.format_error_fmt(format_args!("Field {} is invalid in variant {}", String::from_utf8_lossy(prop_name), #enum_name)));
175 }
176 );
177 code = quote!( #code let mut #var_name: Option<&[u8]> = None; );
178 enum_variant_cannot_be.insert(n_variant, (var_name, code_c));
179 }
180 }
181 }
182 }
183 let mut code_4 = quote!();
185 for (n_variant, (variant_name, variant_name_str, json_names)) in variants.iter().enumerate()
186 { let mut code_5 = quote!();
187 let has_fields = !json_names.is_empty();
188 for json_name in json_names
189 { if !json_name.is_empty() { let (val_field, n_occurances) = fields_by_json_name.get(json_name).unwrap();
191 if *n_occurances <= 1
192 { code_5 = quote!( #code_5 #val_field.unwrap_or_default(), );
193 }
194 else
195 { code_5 = quote!( #code_5 #val_field.try_into().unwrap_or_default(), );
196 }
197 }
198 else
199 { code_5 = quote!( #code_5 Default::default(), );
200 }
201 }
202 let pref_variant_name = Ident::new(&format!("Var{}", variant_name), Span::call_site());
203 if !enum_json_name.is_empty()
204 { let b = LitByteStr::new(variant_name_str.as_bytes(), Span::call_site());
205 code_2 = quote!( #code_2 #b => EnumVariant::#pref_variant_name, );
206 code_3 = quote!( #code_3 #pref_variant_name, );
207 if has_fields
208 { code_5 = quote!( (#code_5) );
209 }
210 let mut code_c = quote!();
211 if let Some((_, code_c_2)) = enum_variant_cannot_be.get(&n_variant)
212 { code_c = quote!(#code_c #code_c_2);
213 };
214 code_4 = quote!( #code_4 EnumVariant::#pref_variant_name => {#code_c Self::#variant_name #code_5}, );
215 }
216 }
217 if !enum_json_name.is_empty()
218 { code = quote!( #code enum EnumVariant {Invalid, #code_3} let mut enum_variant_field = EnumVariant::Invalid; );
219 let b = LitByteStr::new(enum_json_name.as_bytes(), Span::call_site());
220 code_2 = quote!
221 { #b =>
222 { enum_variant_field = match reader.read_bytes()?
223 { #code_2
224 _ => return Err(reader.format_error("Invalid enum variant"))
225 };
226 },
227 };
228 }
229 let mut code_5 = quote!();
231 for (_n_variant, json_name, val_field, is_dup_json_name) in &fields
232 { if !json_name.is_empty() { let (_val_field, n_occurances) = fields_by_json_name.get(json_name).unwrap();
235 if *n_occurances <= 1
236 { code = quote!( #code let mut #val_field = None; );
238 }
239 else if !*is_dup_json_name
240 { code = quote!( #code let mut #val_field = nop_json::Value::Null; );
242 }
243 if !*is_dup_json_name
245 { let b = LitByteStr::new(json_name.as_bytes(), Span::call_site());
246 code_2 = quote!( #code_2 #b => #val_field = reader.read_prop(#json_name)?, );
247 }
248 code_5 = quote!( #code_5 #val_field, );
250 }
251 }
252 if !enum_json_name.is_empty()
253 { code_3 = quote!
254 { let result = match enum_variant_field
255 { EnumVariant::Invalid => return Err(reader.format_error(concat!("Field ", #enum_json_name, " is required"))),
256 #code_4
257 }
258 };
259 }
260 else
261 { for n_variant in 0..data_enum.variants.len()
262 { let mut code_6 = quote!();
263 let mut code_7 = quote!();
264 let mut has_fields = false;
265 for (field_n_variant, json_name, val_field, _is_dup_json_name) in &fields
266 { if *field_n_variant == n_variant
267 { if !json_name.is_empty() { code_6 = quote!( #code_6 Some(#val_field), );
269 code_7 = quote!( #code_7 #val_field, );
270 }
271 else
272 { code_7 = quote!( #code_7 Default::default(), );
273 }
274 has_fields = true;
275 }
276 else if !json_name.is_empty() { code_6 = quote!( #code_6 None, );
278 }
279 }
280 if has_fields
281 { code_7 = quote!( (#code_7) );
282 }
283 let variant_name = &data_enum.variants[n_variant].ident;
284 let mut code_c = quote!();
285 if let Some((_, code_c_2)) = enum_variant_cannot_be.get(&n_variant)
286 { code_c = quote!(#code_c #code_c_2);
287 };
288 code_3 = quote!( #code_3 (#code_6) => {#code_c Self::#variant_name #code_7}, );
289 }
290 code_3 = quote!( let result = match (#code_5) { #code_3 _ => return Err(reader.format_error("Invalid combination of properties"))} );
291 }
292 },
293 Data::Union(_data_union) =>
294 { return Err("Cannot deserialize union".to_string());
295 },
296 };
297 let code_8 = if is_ignore_all
299 { quote!( _ => { reader.read::<()>()? })
301 }
302 else
303 { let mut code_8 = quote!();
304 for (json_name, ignore_in_variants) in json_ignore
306 { let b = LitByteStr::new(json_name.as_bytes(), Span::call_site());
307 let mut code_9 = quote!();
308 if ignore_in_variants.len() != variants.len() && !ignore_in_variants.contains(&usize::MAX)
309 { for (n_variant, (_variant_name, _variant_name_str, json_names)) in variants.iter().enumerate()
311 { if !ignore_in_variants.contains(&n_variant) && !json_names.contains(&json_name)
312 { let var_name = &enum_variant_cannot_be.get(&n_variant).unwrap().0;
314 code_9 = quote!( #code_9 #var_name = Some(#b); );
315 }
316 }
317 }
318 code_8 = quote!( #code_8 #b => { reader.read::<()>()?; #code_9 }, );
319 }
320 quote!( #code_8 _ => {return Err(reader.format_error_fmt(format_args!("Invalid property: {}", String::from_utf8_lossy(reader.get_key()))))} )
321 };
322 let (impl_generics, ty_generics, where_clause) = get_generics_debug_to_json(&ast.generics);
324 code = quote!
325 { impl #impl_generics nop_json::TryFromJson for #name #ty_generics #where_clause
326 { fn try_from_json<T>(reader: &mut nop_json::Reader<T>) -> std::io::Result<Self> where T: Iterator<Item=u8>
327 { use nop_json::ValidateJson;
328 use std::convert::TryInto;
329 #code
330 reader.read_object_use_buffer
331 ( |reader|
332 { match reader.get_key()
333 { #code_2
334 #code_8
335 }
336 Ok(())
337 }
338 )?;
339 #code_3;
340 result.validate_json().map_err(|msg| reader.format_error(&msg))
341 }
342 }
343 };
344 Ok(code.into())
348}
349
350
351#[proc_macro_derive(DebugToJson, attributes(json))]
356pub fn derive_debug_to_json(input: TokenStream) -> TokenStream
357{ let ast: &mut DeriveInput = &mut syn::parse(input).unwrap();
358 match impl_debug_or_write_to_json(ast, false)
359 { Ok(ts) => ts,
360 Err(error) =>
361 { panic!("{}", error);
362 }
363 }
364}
365
366fn impl_debug_or_write_to_json(ast: &mut DeriveInput, is_write_to_json: bool) -> Result<TokenStream, String>
367{ let name = &ast.ident; let mut code = quote!();
369 match &ast.data
370 { Data::Struct(data_struct) =>
371 { let mut n_field = 0;
372 for field in data_struct.fields.iter()
373 { if let Some(ref field_name) = field.ident
374 { let json_str = get_json_name(&field.attrs, "struct field")?.unwrap_or_else(|| field_name.to_string());
375 if !json_str.is_empty() { let fmt = if n_field == 0
377 { format!("{{{{\"{}\":", escape(&json_str))
378 }
379 else
380 { format!(",\"{}\":", escape(&json_str))
381 };
382 code = if !is_write_to_json
383 { quote!( #code write!(out, #fmt)?; nop_json::DebugToJson::fmt(&self.#field_name, out)?; )
384 }
385 else
386 { quote!( #code write!(out, #fmt)?; nop_json::WriteToJson::write_to_json(&self.#field_name, out)?; )
387 };
388 n_field += 1;
389 }
390 }
391 }
392 if n_field == 0
393 { code = quote!( #code write!(out, "{{}}") );
394 }
395 else
396 { code = quote!( #code write!(out, "}}") );
397 }
398 },
399 Data::Enum(data_enum) =>
400 { let enum_json_name = get_json_name(&ast.attrs, "enum")?.unwrap_or_default();
401 for variant in &data_enum.variants
402 { let variant_name = &variant.ident;
403 let (variant_name_str, json_names) = get_json_name_for_enum_variant(&variant.attrs, variant_name, variant.fields.len())?;
404 let mut n_field = 0;
405 let mut has_named_fields = false;
406 let mut code_2 = quote!();
407 let mut code_3 = quote!();
408 if !enum_json_name.is_empty()
409 { let variant_name_str = variant_name_str.unwrap_or_else(|| variant_name.to_string());
410 let fmt = format!("{{{{\"{}\":\"{}\"", escape(&enum_json_name), escape(&variant_name_str));
411 code_3 = quote!( #code_3 write!(out, #fmt)?; );
412 has_named_fields = true;
413 }
414 for json_name in json_names
415 { let is_transient = json_name.is_empty();
416 let val_field = Ident::new(&format!("{}val_{}", if is_transient {"_"} else {""}, n_field), Span::call_site());
418 code_2 = quote!( #code_2 ref #val_field, );
419 if !is_transient
420 { let fmt = if n_field==0 && enum_json_name.is_empty()
422 { format!("{{{{\"{}\":", escape(&json_name))
423 }
424 else
425 { format!(",\"{}\":", escape(&json_name))
426 };
427 code_3 = if !is_write_to_json
428 { quote!( #code_3 write!(out, #fmt)?; nop_json::DebugToJson::fmt(#val_field, out)?; )
429 }
430 else
431 { quote!( #code_3 write!(out, #fmt)?; nop_json::WriteToJson::write_to_json(#val_field, out)?; )
432 };
433 has_named_fields = true;
434 }
435 n_field += 1;
437 }
438 if n_field > 0
439 { code_2 = quote!( (#code_2) );
440 }
441 if !has_named_fields
442 { code_3 = quote!( #code_3 write!(out, "{{")?; );
443 }
444 code = quote!( #code #name::#variant_name #code_2 => {#code_3} );
445 }
446 code = quote!( match *self {#code} write!(out, "}}") );
447 },
448 Data::Union(_data_union) =>
449 { return Err("Cannot serialize union".to_string());
450 },
451 };
452 if !is_write_to_json
454 { let (impl_generics, ty_generics, where_clause) = get_generics_debug_to_json(&ast.generics);
456 code = quote!
458 { impl #impl_generics nop_json::DebugToJson for #name #ty_generics #where_clause
459 { fn fmt(&self, out: &mut std::fmt::Formatter) -> std::fmt::Result
460 { #code
461 }
462 }
463 impl #impl_generics std::fmt::Debug for #name #ty_generics #where_clause
464 { fn fmt(&self, out: &mut std::fmt::Formatter) -> std::fmt::Result
465 { nop_json::DebugToJson::fmt(self, out)
466 }
467 }
468 };
469 }
470 else
471 { let mut generics = mem::take(&mut ast.generics);
473 let (impl_generics, ty_generics, where_clause) = get_generics_write_to_json(&mut generics);
474 code = quote!
476 { impl #impl_generics nop_json::WriteToJson<WriteToJsonPriv1> for #name #ty_generics #where_clause
477 { fn write_to_json(&self, out: &mut WriteToJsonPriv1) -> std::io::Result<()>
478 { #code
479 }
480 }
481 };
482 }
483 Ok(code.into())
487}
488
489fn get_json_name(attrs: &Vec<Attribute>, what: &str) -> Result<Option<String>, String>
490{ let mut result = parse_json_attr(attrs, 0, None)?;
491 if result.0.is_some()
492 { return Err(format!("Cannot parse #[json(...)] for {}", what));
493 }
494 if result.1.len() > 1
495 { return Err(format!("#[json(...)] for {} must contain 1 field name", what));
496 }
497 Ok(result.1.pop())
498}
499
500fn get_json_name_for_enum_variant(attrs: &Vec<Attribute>, variant_name: &Ident, n_fields: usize) -> Result<(Option<String>, Vec<String>), String>
501{ parse_json_attr(attrs, n_fields, Some(variant_name))
502}
503
504fn parse_json_attr(attrs: &Vec<Attribute>, n_fields: usize, variant_name: Option<&Ident>) -> Result<(Option<String>, Vec<String>), String>
505{ parse_json_attr_sub(attrs, n_fields, variant_name.is_some()).map_err
506 ( |e|
507 if let Some(variant_name) = variant_name
508 { format!("Cannot parse #[json(...)] in enum variant {}{}{}", variant_name, if e.is_empty() {""} else {": "}, e)
509 }
510 else
511 { format!("Cannot parse #[json(...)]{}{}", if e.is_empty() {""} else {": "}, e)
512 }
513 )
514}
515
516fn parse_json_attr_sub(attrs: &Vec<Attribute>, n_fields: usize, is_enum: bool) -> Result<(Option<String>, Vec<String>), String>
517{ let mut group_name = None;
518 let mut json_names = Vec::new();
519 let mut is_var_str = false;
520 for a in attrs
521 { match a.parse_meta()
522 { Ok(Meta::List(list)) =>
523 { if list.path.is_ident("json")
524 { for a in list.nested
525 { match a
526 { NestedMeta::Lit(Lit::Str(s)) =>
527 { if group_name.is_some() && !is_var_str
528 { return Err("Couldn't interpret #[json] attribute".to_string());
529 }
530 json_names.push(s.value());
531 },
532 NestedMeta::Meta(Meta::Path(meta)) =>
533 { if group_name.is_some() && !is_var_str
534 { return Err("Couldn't interpret #[json] attribute".to_string());
535 }
536 if let Some(name) = meta.get_ident()
537 { json_names.push(name.to_string());
538 }
539 },
540 NestedMeta::Meta(Meta::List(list)) =>
541 { if is_enum
542 { if json_names.len() > 0
543 { return Err("Couldn't interpret #[json] attribute".to_string());
544 }
545 if let Some(name) = list.path.get_ident()
546 { group_name = Some(name.to_string());
547 for a in list.nested
548 { match a
549 { NestedMeta::Lit(Lit::Str(s)) =>
550 { json_names.push(s.value());
551 },
552 NestedMeta::Meta(Meta::Path(meta)) =>
553 { if let Some(name) = meta.get_ident()
554 { json_names.push(name.to_string());
555 }
556 },
557 _ =>
558 { return Err("Couldn't interpret #[json] attribute".to_string());
559 }
560 }
561 }
562 }
563 if json_names.len() == 0
564 { return Err("Couldn't interpret #[json] attribute".to_string());
565 }
566 }
567 else
568 { return Err("Couldn't interpret #[json] attribute".to_string());
569 }
570 },
571 NestedMeta::Meta(Meta::NameValue(list)) =>
572 { if is_enum
573 { if group_name.is_some()
574 { return Err("Couldn't interpret #[json] attribute".to_string());
575 }
576 if list.path.is_ident("var")
577 { match list.lit
578 { Lit::Str(s) =>
579 { group_name = Some(s.value());
580 is_var_str = true;
581 },
582 _ => {}
583 }
584 }
585 if group_name.is_none()
586 { return Err("Couldn't interpret #[json] attribute".to_string());
587 }
588 }
589 else
590 { return Err("Couldn't interpret #[json] attribute".to_string());
591 }
592 },
593 _ =>
594 { return Err("Couldn't interpret #[json] attribute".to_string());
595 }
596 }
597 }
598 }
599 },
600 _ => {}
601 }
602 }
603 if is_enum
604 { if json_names.len() != n_fields
605 { if json_names.len()==0
606 { return Err(format!("Enum variant must have #[json(name_1, name_2, ...)] or #[json(variant_name(name_1, name_2, ...))] or #[json(var=\"variant_name\", name_1, name_2, ...)]"));
607 }
608 else if n_fields==0 && json_names.len()==1 && group_name.is_none()
609 { group_name = Some(json_names.pop().unwrap());
610 }
611 else
612 { return Err(format!("Must specify names for each member"));
613 }
614 }
615 }
616 Ok((group_name, json_names))
617}
618
619fn get_json_ignore(attrs: &Vec<Attribute>, n_variant: usize, json_ignore: &mut HashMap<String, HashSet<usize>>, is_ignore_all: bool) -> Result<bool, String>
620{ let mut has_ignore = false;
621 for a in attrs
622 { match a.parse_meta()
623 { Ok(Meta::Path(path)) =>
624 { if path.is_ident("json_ignore")
625 { has_ignore = true;
626 }
627 },
628 Ok(Meta::List(list)) =>
629 { if list.path.is_ident("json_ignore")
630 { has_ignore = true;
631 for a in list.nested
632 { let name = match a
633 { NestedMeta::Lit(Lit::Str(s)) =>
634 { if is_ignore_all
635 { return Err("#[json_ignore] after ignoring all".to_string());
636 }
637 Some(s.value())
638 },
639 NestedMeta::Meta(Meta::Path(meta)) =>
640 { if let Some(name) = meta.get_ident()
641 { if is_ignore_all
642 { return Err("#[json_ignore] after ignoring all".to_string());
643 }
644 Some(name.to_string())
645 }
646 else
647 { None
648 }
649 },
650 _ =>
651 { None
652 }
653 };
654 if let Some(name) = name
655 { match json_ignore.get_mut(&name)
656 { Some(variants) =>
657 { variants.insert(n_variant);
658 }
659 None =>
660 { let mut variants = HashSet::new();
661 variants.insert(n_variant);
662 json_ignore.insert(name, variants);
663 }
664 }
665 }
666 }
667 }
668 },
669 _ => {}
670 }
671 }
672 Ok(is_ignore_all || has_ignore && json_ignore.is_empty())
673}
674
675fn get_generics_debug_to_json(generics: &Generics) -> (ImplGenerics, TypeGenerics, proc_macro2::TokenStream)
677{ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
678 let mut wher = quote!();
680 let mut i = 0;
681 for p in &generics.params
682 { match p
683 { GenericParam::Type(ty) =>
684 { let ty = &ty.ident;
685 if i == 0
686 { wher = if where_clause.is_none() {quote!(where)} else {quote!(#where_clause,)};
687 wher = quote!( #wher #ty: nop_json::DebugToJson );
688 }
689 else
690 { wher = quote!( #wher, #ty: nop_json::DebugToJson );
691 }
692 i += 1;
693 },
694 _=> {},
695 }
696 }
697 if i == 0
698 { wher = quote!(#where_clause);
699 }
700 (impl_generics, ty_generics, wher)
701}
702
703fn get_generics_write_to_json(generics: &mut Generics) -> (ImplGenerics, proc_macro2::TokenStream, proc_macro2::TokenStream)
705{ let (_impl_generics, ty_generics, where_clause) = generics.split_for_impl();
706 let mut wher = if where_clause.is_none() {quote!(where WriteToJsonPriv1: std::io::Write)} else {quote!(#where_clause, WriteToJsonPriv1: std::io::Write)};
708 for p in &generics.params
709 { match p
710 { GenericParam::Type(ty) =>
711 { let ty = &ty.ident;
712 wher = quote!( #wher, #ty: nop_json::WriteToJson<WriteToJsonPriv1> );
713 },
714 _=> {},
715 }
716 }
717 let ty_generics = quote!(#ty_generics);
719 let ident = Ident::new("WriteToJsonPriv1", Span::call_site());
720 generics.params.push(GenericParam::Type(TypeParam {attrs: Default::default(), ident, colon_token: None, bounds: Default::default(), eq_token: None, default: None}));
721 let impl_generics = generics.split_for_impl().0;
722 (impl_generics, ty_generics, wher)
723}
724
725
726#[proc_macro_derive(WriteToJson, attributes(json))]
731pub fn derive_write_to_json(input: TokenStream) -> TokenStream
732{ let ast: &mut DeriveInput = &mut syn::parse(input).unwrap();
733 match impl_debug_or_write_to_json(ast, true)
734 { Ok(ts) => ts,
735 Err(error) =>
736 { panic!("{}", error);
737 }
738 }
739}
740
741#[proc_macro_derive(ValidateJson)]
745pub fn derive_validate_json(input: TokenStream) -> TokenStream
746{ let ast: &mut DeriveInput = &mut syn::parse(input).unwrap();
747 match impl_validate_json(ast)
748 { Ok(ts) => ts,
749 Err(error) =>
750 { panic!("{}", error);
751 }
752 }
753}
754
755fn impl_validate_json(ast: &mut DeriveInput) -> Result<TokenStream, String>
756{ let name = &ast.ident; let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
759 let code = quote!
761 { impl #impl_generics nop_json::ValidateJson for #name #ty_generics #where_clause {}
762 };
763 Ok(code.into())
767}