1use crate::{
5 common,
6 indent::{IndentConfig, IndentedWriter},
7 CodeGeneratorConfig, Encoding,
8};
9use heck::CamelCase;
10use include_dir::include_dir as include_directory;
11use serde_reflection::{ContainerFormat, Format, FormatHolder, Named, Registry, VariantFormat};
12use std::{
13 collections::{BTreeMap, HashMap},
14 io::{Result, Write},
15 path::PathBuf,
16};
17
18pub struct CodeGenerator<'a> {
20 config: &'a CodeGeneratorConfig,
22 external_qualified_names: HashMap<String, String>,
25}
26
27struct JavaEmitter<'a, T> {
29 out: IndentedWriter<T>,
31 generator: &'a CodeGenerator<'a>,
33 current_namespace: Vec<String>,
35 current_reserved_names: HashMap<String, usize>,
40}
41
42impl<'a> CodeGenerator<'a> {
43 pub fn new(config: &'a CodeGeneratorConfig) -> Self {
45 if config.c_style_enums {
46 panic!("Java does not support generating c-style enums");
47 }
48 let mut external_qualified_names = HashMap::new();
49 for (namespace, names) in &config.external_definitions {
50 for name in names {
51 external_qualified_names
52 .insert(name.to_string(), format!("{}.{}", namespace, name));
53 }
54 }
55 Self {
56 config,
57 external_qualified_names,
58 }
59 }
60
61 pub fn write_source_files(
65 &self,
66 install_dir: std::path::PathBuf,
67 registry: &Registry,
68 ) -> Result<()> {
69 let current_namespace = self
70 .config
71 .module_name
72 .split('.')
73 .map(String::from)
74 .collect::<Vec<_>>();
75
76 let mut dir_path = install_dir;
77 for part in ¤t_namespace {
78 dir_path = dir_path.join(part);
79 }
80 std::fs::create_dir_all(&dir_path)?;
81
82 for (name, format) in registry {
83 self.write_container_class(&dir_path, current_namespace.clone(), name, format)?;
84 }
85 if self.config.serialization {
86 self.write_helper_class(&dir_path, current_namespace, registry)?;
87 }
88 Ok(())
89 }
90
91 fn write_container_class(
92 &self,
93 dir_path: &std::path::Path,
94 current_namespace: Vec<String>,
95 name: &str,
96 format: &ContainerFormat,
97 ) -> Result<()> {
98 let mut file = std::fs::File::create(dir_path.join(name.to_string() + ".java"))?;
99 let mut emitter = JavaEmitter {
100 out: IndentedWriter::new(&mut file, IndentConfig::Space(4)),
101 generator: self,
102 current_namespace,
103 current_reserved_names: HashMap::new(),
104 };
105
106 emitter.output_preamble()?;
107 emitter.output_container(name, format)
108 }
109
110 fn write_helper_class(
111 &self,
112 dir_path: &std::path::Path,
113 current_namespace: Vec<String>,
114 registry: &Registry,
115 ) -> Result<()> {
116 let mut file = std::fs::File::create(dir_path.join("TraitHelpers.java"))?;
117 let mut emitter = JavaEmitter {
118 out: IndentedWriter::new(&mut file, IndentConfig::Space(4)),
119 generator: self,
120 current_namespace,
121 current_reserved_names: HashMap::new(),
122 };
123
124 emitter.output_preamble()?;
125 emitter.output_trait_helpers(registry)
126 }
127}
128
129impl<'a, T> JavaEmitter<'a, T>
130where
131 T: Write,
132{
133 fn output_preamble(&mut self) -> Result<()> {
134 writeln!(self.out, "package {};\n", self.generator.config.module_name)?;
135 Ok(())
136 }
137
138 fn quote_qualified_name(&self, name: &str) -> String {
143 let qname = self
144 .generator
145 .external_qualified_names
146 .get(name)
147 .cloned()
148 .unwrap_or_else(|| format!("{}.{}", self.generator.config.module_name, name));
149 let mut path = qname.split('.').collect::<Vec<_>>();
150 if path.len() <= 1 {
151 return qname;
152 }
153 let name = path.pop().unwrap();
154 if self.current_reserved_names.contains_key(name) {
155 return qname;
156 }
157 for (index, element) in path.iter().enumerate() {
158 match self.current_namespace.get(index) {
159 Some(e) if e == element => (),
160 _ => {
161 return qname;
162 }
163 }
164 }
165 name.to_string()
166 }
167
168 fn output_comment(&mut self, name: &str) -> std::io::Result<()> {
169 let mut path = self.current_namespace.clone();
170 path.push(name.to_string());
171 if let Some(doc) = self.generator.config.comments.get(&path) {
172 let text = textwrap::indent(doc, " * ").replace("\n\n", "\n *\n");
173 writeln!(self.out, "/**\n{} */", text)?;
174 }
175 Ok(())
176 }
177
178 fn output_custom_code(&mut self) -> std::io::Result<()> {
179 if let Some(code) = self
180 .generator
181 .config
182 .custom_code
183 .get(&self.current_namespace)
184 {
185 writeln!(self.out, "\n{}", code)?;
186 }
187 Ok(())
188 }
189
190 fn quote_type(&self, format: &Format) -> String {
191 use Format::*;
192 match format {
193 TypeName(x) => self.quote_qualified_name(x),
194 Unit => "com.novi.serde.Unit".into(),
195 Bool => "Boolean".into(),
196 I8 => "Byte".into(),
197 I16 => "Short".into(),
198 I32 => "Integer".into(),
199 I64 => "Long".into(),
200 I128 => "java.math.@com.novi.serde.Int128 BigInteger".into(),
201 U8 => "@com.novi.serde.Unsigned Byte".into(),
202 U16 => "@com.novi.serde.Unsigned Short".into(),
203 U32 => "@com.novi.serde.Unsigned Integer".into(),
204 U64 => "@com.novi.serde.Unsigned Long".into(),
205 U128 => "java.math.@com.novi.serde.Unsigned @com.novi.serde.Int128 BigInteger".into(),
206 F32 => "Float".into(),
207 F64 => "Double".into(),
208 Char => "Character".into(),
209 Str => "String".into(),
210 Bytes => "com.novi.serde.Bytes".into(),
211
212 Option(format) => format!("java.util.Optional<{}>", self.quote_type(format)),
213 Seq(format) => format!("java.util.List<{}>", self.quote_type(format)),
214 Map { key, value } => format!(
215 "java.util.Map<{}, {}>",
216 self.quote_type(key),
217 self.quote_type(value)
218 ),
219 Tuple(formats) => format!(
220 "com.novi.serde.Tuple{}<{}>",
221 formats.len(),
222 self.quote_types(formats)
223 ),
224 TupleArray { content, size } => format!(
225 "java.util.@com.novi.serde.ArrayLen(length={}) List<{}>",
226 size,
227 self.quote_type(content)
228 ),
229 Variable(_) => panic!("unexpected value"),
230 }
231 }
232
233 fn enter_class(&mut self, name: &str, reserved_subclass_names: &[&str]) {
234 self.out.indent();
235 self.current_namespace.push(name.to_string());
236 for name in reserved_subclass_names {
237 let entry = self
238 .current_reserved_names
239 .entry(name.to_string())
240 .or_insert(0);
241 *entry += 1;
242 }
243 }
244
245 fn leave_class(&mut self, reserved_subclass_names: &[&str]) {
246 self.out.unindent();
247 self.current_namespace.pop();
248 for name in reserved_subclass_names {
249 let entry = self.current_reserved_names.get_mut(*name).unwrap();
250 *entry -= 1;
251 if *entry == 0 {
252 self.current_reserved_names.remove(*name);
253 }
254 }
255 }
256
257 fn quote_types(&self, formats: &[Format]) -> String {
258 formats
259 .iter()
260 .map(|f| self.quote_type(f))
261 .collect::<Vec<_>>()
262 .join(", ")
263 }
264
265 fn output_trait_helpers(&mut self, registry: &Registry) -> Result<()> {
266 let mut subtypes = BTreeMap::new();
267 for format in registry.values() {
268 format
269 .visit(&mut |f| {
270 if Self::needs_helper(f) {
271 subtypes.insert(common::mangle_type(f), f.clone());
272 }
273 Ok(())
274 })
275 .unwrap();
276 }
277 writeln!(self.out, "final class TraitHelpers {{")?;
278 let reserved_names = &[];
279 self.enter_class("TraitHelpers", reserved_names);
280 for (mangled_name, subtype) in &subtypes {
281 self.output_serialization_helper(mangled_name, subtype)?;
282 self.output_deserialization_helper(mangled_name, subtype)?;
283 }
284 self.leave_class(reserved_names);
285 writeln!(self.out, "}}\n")
286 }
287
288 fn needs_helper(format: &Format) -> bool {
289 use Format::*;
290 matches!(
291 format,
292 Option(_) | Seq(_) | Map { .. } | Tuple(_) | TupleArray { .. }
293 )
294 }
295
296 fn quote_serialize_value(&self, value: &str, format: &Format) -> String {
297 use Format::*;
298 match format {
299 TypeName(_) => format!("{}.serialize(serializer);", value),
300 Unit => format!("serializer.serialize_unit({});", value),
301 Bool => format!("serializer.serialize_bool({});", value),
302 I8 => format!("serializer.serialize_i8({});", value),
303 I16 => format!("serializer.serialize_i16({});", value),
304 I32 => format!("serializer.serialize_i32({});", value),
305 I64 => format!("serializer.serialize_i64({});", value),
306 I128 => format!("serializer.serialize_i128({});", value),
307 U8 => format!("serializer.serialize_u8({});", value),
308 U16 => format!("serializer.serialize_u16({});", value),
309 U32 => format!("serializer.serialize_u32({});", value),
310 U64 => format!("serializer.serialize_u64({});", value),
311 U128 => format!("serializer.serialize_u128({});", value),
312 F32 => format!("serializer.serialize_f32({});", value),
313 F64 => format!("serializer.serialize_f64({});", value),
314 Char => format!("serializer.serialize_char({});", value),
315 Str => format!("serializer.serialize_str({});", value),
316 Bytes => format!("serializer.serialize_bytes({});", value),
317 _ => format!(
318 "{}.serialize_{}({}, serializer);",
319 self.quote_qualified_name("TraitHelpers"),
320 common::mangle_type(format),
321 value
322 ),
323 }
324 }
325
326 fn quote_deserialize(&self, format: &Format) -> String {
327 use Format::*;
328 match format {
329 TypeName(name) => format!(
330 "{}.deserialize(deserializer)",
331 self.quote_qualified_name(name)
332 ),
333 Unit => "deserializer.deserialize_unit()".to_string(),
334 Bool => "deserializer.deserialize_bool()".to_string(),
335 I8 => "deserializer.deserialize_i8()".to_string(),
336 I16 => "deserializer.deserialize_i16()".to_string(),
337 I32 => "deserializer.deserialize_i32()".to_string(),
338 I64 => "deserializer.deserialize_i64()".to_string(),
339 I128 => "deserializer.deserialize_i128()".to_string(),
340 U8 => "deserializer.deserialize_u8()".to_string(),
341 U16 => "deserializer.deserialize_u16()".to_string(),
342 U32 => "deserializer.deserialize_u32()".to_string(),
343 U64 => "deserializer.deserialize_u64()".to_string(),
344 U128 => "deserializer.deserialize_u128()".to_string(),
345 F32 => "deserializer.deserialize_f32()".to_string(),
346 F64 => "deserializer.deserialize_f64()".to_string(),
347 Char => "deserializer.deserialize_char()".to_string(),
348 Str => "deserializer.deserialize_str()".to_string(),
349 Bytes => "deserializer.deserialize_bytes()".to_string(),
350 _ => format!(
351 "{}.deserialize_{}(deserializer)",
352 self.quote_qualified_name("TraitHelpers"),
353 common::mangle_type(format),
354 ),
355 }
356 }
357
358 fn output_serialization_helper(&mut self, name: &str, format0: &Format) -> Result<()> {
359 use Format::*;
360
361 write!(
362 self.out,
363 "static void serialize_{}({} value, com.novi.serde.Serializer serializer) throws com.novi.serde.SerializationError {{",
364 name,
365 self.quote_type(format0)
366 )?;
367 self.out.indent();
368 match format0 {
369 Option(format) => {
370 write!(
371 self.out,
372 r#"
373if (value.isPresent()) {{
374 serializer.serialize_option_tag(true);
375 {}
376}} else {{
377 serializer.serialize_option_tag(false);
378}}
379"#,
380 self.quote_serialize_value("value.get()", format)
381 )?;
382 }
383
384 Seq(format) => {
385 write!(
386 self.out,
387 r#"
388serializer.serialize_len(value.size());
389for ({} item : value) {{
390 {}
391}}
392"#,
393 self.quote_type(format),
394 self.quote_serialize_value("item", format)
395 )?;
396 }
397
398 Map { key, value } => {
399 write!(
400 self.out,
401 r#"
402serializer.serialize_len(value.size());
403int[] offsets = new int[value.size()];
404int count = 0;
405for (java.util.Map.Entry<{}, {}> entry : value.entrySet()) {{
406 offsets[count++] = serializer.get_buffer_offset();
407 {}
408 {}
409}}
410serializer.sort_map_entries(offsets);
411"#,
412 self.quote_type(key),
413 self.quote_type(value),
414 self.quote_serialize_value("entry.getKey()", key),
415 self.quote_serialize_value("entry.getValue()", value)
416 )?;
417 }
418
419 Tuple(formats) => {
420 writeln!(self.out)?;
421 for (index, format) in formats.iter().enumerate() {
422 let expr = format!("value.field{}", index);
423 writeln!(self.out, "{}", self.quote_serialize_value(&expr, format))?;
424 }
425 }
426
427 TupleArray { content, size } => {
428 write!(
429 self.out,
430 r#"
431if (value.size() != {0}) {{
432 throw new java.lang.IllegalArgumentException("Invalid length for fixed-size array: " + value.size() + " instead of "+ {0});
433}}
434for ({1} item : value) {{
435 {2}
436}}
437"#,
438 size,
439 self.quote_type(content),
440 self.quote_serialize_value("item", content),
441 )?;
442 }
443
444 _ => panic!("unexpected case"),
445 }
446 self.out.unindent();
447 writeln!(self.out, "}}\n")
448 }
449
450 fn output_deserialization_helper(&mut self, name: &str, format0: &Format) -> Result<()> {
451 use Format::*;
452
453 write!(
454 self.out,
455 "static {} deserialize_{}(com.novi.serde.Deserializer deserializer) throws com.novi.serde.DeserializationError {{",
456 self.quote_type(format0),
457 name,
458 )?;
459 self.out.indent();
460 match format0 {
461 Option(format) => {
462 write!(
463 self.out,
464 r#"
465boolean tag = deserializer.deserialize_option_tag();
466if (!tag) {{
467 return java.util.Optional.empty();
468}} else {{
469 return java.util.Optional.of({});
470}}
471"#,
472 self.quote_deserialize(format),
473 )?;
474 }
475
476 Seq(format) => {
477 write!(
478 self.out,
479 r#"
480long length = deserializer.deserialize_len();
481java.util.List<{0}> obj = new java.util.ArrayList<{0}>((int) length);
482for (long i = 0; i < length; i++) {{
483 obj.add({1});
484}}
485return obj;
486"#,
487 self.quote_type(format),
488 self.quote_deserialize(format)
489 )?;
490 }
491
492 Map { key, value } => {
493 write!(
494 self.out,
495 r#"
496long length = deserializer.deserialize_len();
497java.util.Map<{0}, {1}> obj = new java.util.HashMap<{0}, {1}>();
498int previous_key_start = 0;
499int previous_key_end = 0;
500for (long i = 0; i < length; i++) {{
501 int key_start = deserializer.get_buffer_offset();
502 {0} key = {2};
503 int key_end = deserializer.get_buffer_offset();
504 if (i > 0) {{
505 deserializer.check_that_key_slices_are_increasing(
506 new com.novi.serde.Slice(previous_key_start, previous_key_end),
507 new com.novi.serde.Slice(key_start, key_end));
508 }}
509 previous_key_start = key_start;
510 previous_key_end = key_end;
511 {1} value = {3};
512 obj.put(key, value);
513}}
514return obj;
515"#,
516 self.quote_type(key),
517 self.quote_type(value),
518 self.quote_deserialize(key),
519 self.quote_deserialize(value),
520 )?;
521 }
522
523 Tuple(formats) => {
524 write!(
525 self.out,
526 r#"
527return new {}({}
528);
529"#,
530 self.quote_type(format0),
531 formats
532 .iter()
533 .map(|f| format!("\n {}", self.quote_deserialize(f)))
534 .collect::<Vec<_>>()
535 .join(",")
536 )?;
537 }
538
539 TupleArray { content, size } => {
540 write!(
541 self.out,
542 r#"
543java.util.List<{0}> obj = new java.util.ArrayList<{0}>({1});
544for (long i = 0; i < {1}; i++) {{
545 obj.add({2});
546}}
547return obj;
548"#,
549 self.quote_type(content),
550 size,
551 self.quote_deserialize(content)
552 )?;
553 }
554
555 _ => panic!("unexpected case"),
556 }
557 self.out.unindent();
558 writeln!(self.out, "}}\n")
559 }
560
561 fn output_variant(
562 &mut self,
563 base: &str,
564 index: u32,
565 name: &str,
566 variant: &VariantFormat,
567 ) -> Result<()> {
568 use VariantFormat::*;
569 let fields = match variant {
570 Unit => Vec::new(),
571 NewType(format) => vec![Named {
572 name: "value".to_string(),
573 value: format.as_ref().clone(),
574 }],
575 Tuple(formats) => formats
576 .iter()
577 .enumerate()
578 .map(|(i, f)| Named {
579 name: format!("field{}", i),
580 value: f.clone(),
581 })
582 .collect(),
583 Struct(fields) => fields.clone(),
584 Variable(_) => panic!("incorrect value"),
585 };
586 self.output_struct_or_variant_container(Some(base), Some(index), name, &fields)
587 }
588
589 fn output_variants(
590 &mut self,
591 base: &str,
592 variants: &BTreeMap<u32, Named<VariantFormat>>,
593 ) -> Result<()> {
594 for (index, variant) in variants {
595 self.output_variant(base, *index, &variant.name, &variant.value)?;
596 }
597 Ok(())
598 }
599
600 fn output_struct_or_variant_container(
601 &mut self,
602 variant_base: Option<&str>,
603 variant_index: Option<u32>,
604 name: &str,
605 fields: &[Named<Format>],
606 ) -> Result<()> {
607 writeln!(self.out)?;
609 if let Some(base) = variant_base {
610 self.output_comment(name)?;
611 writeln!(
612 self.out,
613 "public static final class {} extends {} {{",
614 name, base
615 )?;
616 } else {
617 self.output_comment(name)?;
618 writeln!(self.out, "public final class {} {{", name)?;
619 }
620 let reserved_names = &["Builder"];
621 self.enter_class(name, reserved_names);
622 for field in fields {
624 self.output_comment(&field.name)?;
625 writeln!(
626 self.out,
627 "public final {} {};",
628 self.quote_type(&field.value),
629 field.name
630 )?;
631 }
632 if !fields.is_empty() {
633 writeln!(self.out)?;
634 }
635 writeln!(
637 self.out,
638 "public {}({}) {{",
639 name,
640 fields
641 .iter()
642 .map(|f| format!("{} {}", self.quote_type(&f.value), &f.name))
643 .collect::<Vec<_>>()
644 .join(", ")
645 )?;
646 self.out.indent();
647 for field in fields {
648 writeln!(
649 self.out,
650 "java.util.Objects.requireNonNull({0}, \"{0} must not be null\");",
651 &field.name
652 )?;
653 }
654 for field in fields {
655 writeln!(self.out, "this.{} = {};", &field.name, &field.name)?;
656 }
657 self.out.unindent();
658 writeln!(self.out, "}}")?;
659 if self.generator.config.serialization {
661 writeln!(
662 self.out,
663 "\npublic void serialize(com.novi.serde.Serializer serializer) throws com.novi.serde.SerializationError {{",
664 )?;
665 self.out.indent();
666 writeln!(self.out, "serializer.increase_container_depth();")?;
667 if let Some(index) = variant_index {
668 writeln!(self.out, "serializer.serialize_variant_index({});", index)?;
669 }
670 for field in fields {
671 writeln!(
672 self.out,
673 "{}",
674 self.quote_serialize_value(&field.name, &field.value)
675 )?;
676 }
677 writeln!(self.out, "serializer.decrease_container_depth();")?;
678 self.out.unindent();
679 writeln!(self.out, "}}")?;
680
681 if variant_index.is_none() {
682 for encoding in &self.generator.config.encodings {
683 self.output_class_serialize_for_encoding(*encoding)?;
684 }
685 }
686 }
687 if self.generator.config.serialization {
689 if variant_index.is_none() {
690 writeln!(
691 self.out,
692 "\npublic static {} deserialize(com.novi.serde.Deserializer deserializer) throws com.novi.serde.DeserializationError {{",
693 name,
694 )?;
695 } else {
696 writeln!(
697 self.out,
698 "\nstatic {} load(com.novi.serde.Deserializer deserializer) throws com.novi.serde.DeserializationError {{",
699 name,
700 )?;
701 }
702 self.out.indent();
703 writeln!(self.out, "deserializer.increase_container_depth();")?;
704 writeln!(self.out, "Builder builder = new Builder();")?;
705 for field in fields {
706 writeln!(
707 self.out,
708 "builder.{} = {};",
709 field.name,
710 self.quote_deserialize(&field.value)
711 )?;
712 }
713 writeln!(self.out, "deserializer.decrease_container_depth();")?;
714 writeln!(self.out, "return builder.build();")?;
715 self.out.unindent();
716 writeln!(self.out, "}}")?;
717
718 if variant_index.is_none() {
719 for encoding in &self.generator.config.encodings {
720 self.output_class_deserialize_for_encoding(name, *encoding)?;
721 }
722 }
723 }
724 write!(self.out, "\npublic boolean equals(Object obj) {{")?;
726 self.out.indent();
727 writeln!(
728 self.out,
729 r#"
730if (this == obj) return true;
731if (obj == null) return false;
732if (getClass() != obj.getClass()) return false;
733{0} other = ({0}) obj;"#,
734 name,
735 )?;
736 for field in fields {
737 writeln!(
738 self.out,
739 "if (!java.util.Objects.equals(this.{0}, other.{0})) {{ return false; }}",
740 &field.name,
741 )?;
742 }
743 writeln!(self.out, "return true;")?;
744 self.out.unindent();
745 writeln!(self.out, "}}")?;
746 writeln!(self.out, "\npublic int hashCode() {{")?;
748 self.out.indent();
749 writeln!(self.out, "int value = 7;",)?;
750 for field in fields {
751 writeln!(
752 self.out,
753 "value = 31 * value + (this.{0} != null ? this.{0}.hashCode() : 0);",
754 &field.name
755 )?;
756 }
757 writeln!(self.out, "return value;")?;
758 self.out.unindent();
759 writeln!(self.out, "}}")?;
760 self.output_struct_or_variant_container_builder(name, fields)?;
762 self.output_custom_code()?;
764 self.leave_class(reserved_names);
766 writeln!(self.out, "}}")
767 }
768
769 fn output_struct_or_variant_container_builder(
770 &mut self,
771 name: &str,
772 fields: &[Named<Format>],
773 ) -> Result<()> {
774 writeln!(self.out)?;
776 writeln!(self.out, "public static final class Builder {{")?;
777 let reserved_names = &[];
778 self.enter_class("Builder", reserved_names);
779 for field in fields {
781 writeln!(
782 self.out,
783 "public {} {};",
784 self.quote_type(&field.value),
785 field.name
786 )?;
787 }
788 if !fields.is_empty() {
789 writeln!(self.out)?;
790 }
791 writeln!(
793 self.out,
794 r#"public {0} build() {{
795 return new {0}({1}
796 );
797}}"#,
798 name,
799 fields
800 .iter()
801 .map(|f| format!("\n {}", f.name))
802 .collect::<Vec<_>>()
803 .join(",")
804 )?;
805 self.output_custom_code()?;
807 self.leave_class(reserved_names);
809 writeln!(self.out, "}}")
810 }
811
812 fn output_enum_container(
813 &mut self,
814 name: &str,
815 variants: &BTreeMap<u32, Named<VariantFormat>>,
816 ) -> Result<()> {
817 writeln!(self.out)?;
818 self.output_comment(name)?;
819 writeln!(self.out, "public abstract class {} {{", name)?;
820 let reserved_names = variants
821 .values()
822 .map(|v| v.name.as_str())
823 .collect::<Vec<_>>();
824 self.enter_class(name, &reserved_names);
825 if self.generator.config.serialization {
826 writeln!(
827 self.out,
828 "\nabstract public void serialize(com.novi.serde.Serializer serializer) throws com.novi.serde.SerializationError;"
829 )?;
830 write!(
831 self.out,
832 "\npublic static {} deserialize(com.novi.serde.Deserializer deserializer) throws com.novi.serde.DeserializationError {{",
833 name
834 )?;
835 self.out.indent();
836 writeln!(
837 self.out,
838 r#"
839int index = deserializer.deserialize_variant_index();
840switch (index) {{"#,
841 )?;
842 self.out.indent();
843 for (index, variant) in variants {
844 writeln!(
845 self.out,
846 "case {}: return {}.load(deserializer);",
847 index, variant.name,
848 )?;
849 }
850 writeln!(
851 self.out,
852 "default: throw new com.novi.serde.DeserializationError(\"Unknown variant index for {}: \" + index);",
853 name,
854 )?;
855 self.out.unindent();
856 writeln!(self.out, "}}")?;
857 self.out.unindent();
858 writeln!(self.out, "}}")?;
859
860 for encoding in &self.generator.config.encodings {
861 self.output_class_serialize_for_encoding(*encoding)?;
862 self.output_class_deserialize_for_encoding(name, *encoding)?;
863 }
864 }
865
866 self.output_variants(name, variants)?;
867 self.leave_class(&reserved_names);
868 writeln!(self.out, "}}\n")
869 }
870
871 fn output_class_serialize_for_encoding(&mut self, encoding: Encoding) -> Result<()> {
872 writeln!(
873 self.out,
874 r#"
875public byte[] {0}Serialize() throws com.novi.serde.SerializationError {{
876 com.novi.serde.Serializer serializer = new com.novi.{0}.{1}Serializer();
877 serialize(serializer);
878 return serializer.get_bytes();
879}}"#,
880 encoding.name(),
881 encoding.name().to_camel_case()
882 )
883 }
884
885 fn output_class_deserialize_for_encoding(
886 &mut self,
887 name: &str,
888 encoding: Encoding,
889 ) -> Result<()> {
890 writeln!(
891 self.out,
892 r#"
893public static {0} {1}Deserialize(byte[] input) throws com.novi.serde.DeserializationError {{
894 if (input == null) {{
895 throw new com.novi.serde.DeserializationError("Cannot deserialize null array");
896 }}
897 com.novi.serde.Deserializer deserializer = new com.novi.{1}.{2}Deserializer(input);
898 {0} value = deserialize(deserializer);
899 if (deserializer.get_buffer_offset() < input.length) {{
900 throw new com.novi.serde.DeserializationError("Some input bytes were not read");
901 }}
902 return value;
903}}"#,
904 name,
905 encoding.name(),
906 encoding.name().to_camel_case()
907 )
908 }
909
910 fn output_container(&mut self, name: &str, format: &ContainerFormat) -> Result<()> {
911 use ContainerFormat::*;
912 let fields = match format {
913 UnitStruct => Vec::new(),
914 NewTypeStruct(format) => vec![Named {
915 name: "value".to_string(),
916 value: format.as_ref().clone(),
917 }],
918 TupleStruct(formats) => formats
919 .iter()
920 .enumerate()
921 .map(|(i, f)| Named {
922 name: format!("field{}", i),
923 value: f.clone(),
924 })
925 .collect::<Vec<_>>(),
926 Struct(fields) => fields.clone(),
927 Enum(variants) => {
928 self.output_enum_container(name, variants)?;
929 return Ok(());
930 }
931 };
932 self.output_struct_or_variant_container(None, None, name, &fields)
933 }
934}
935
936pub struct Installer {
938 install_dir: PathBuf,
939}
940
941impl Installer {
942 pub fn new(install_dir: PathBuf) -> Self {
943 Installer { install_dir }
944 }
945
946 fn install_runtime(
947 &self,
948 source_dir: include_dir::Dir,
949 path: &str,
950 ) -> std::result::Result<(), Box<dyn std::error::Error>> {
951 let dir_path = self.install_dir.join(path);
952 std::fs::create_dir_all(&dir_path)?;
953 for entry in source_dir.files() {
954 let mut file = std::fs::File::create(dir_path.join(entry.path()))?;
955 file.write_all(entry.contents())?;
956 }
957 Ok(())
958 }
959}
960
961impl crate::SourceInstaller for Installer {
962 type Error = Box<dyn std::error::Error>;
963
964 fn install_module(
965 &self,
966 config: &CodeGeneratorConfig,
967 registry: &Registry,
968 ) -> std::result::Result<(), Self::Error> {
969 let generator = CodeGenerator::new(config);
970 generator.write_source_files(self.install_dir.clone(), registry)?;
971 Ok(())
972 }
973
974 fn install_serde_runtime(&self) -> std::result::Result<(), Self::Error> {
975 self.install_runtime(
976 include_directory!("runtime/java/com/novi/serde"),
977 "com/novi/serde",
978 )
979 }
980
981 fn install_bincode_runtime(&self) -> std::result::Result<(), Self::Error> {
982 self.install_runtime(
983 include_directory!("runtime/java/com/novi/bincode"),
984 "com/novi/bincode",
985 )
986 }
987
988 fn install_bcs_runtime(&self) -> std::result::Result<(), Self::Error> {
989 self.install_runtime(
990 include_directory!("runtime/java/com/novi/bcs"),
991 "com/novi/bcs",
992 )
993 }
994}