1use std::collections::HashMap;
2use std::fmt::Write;
3use trans_gen_core::trans_schema::*;
4use trans_gen_core::Writer;
5
6fn conv(name: &str) -> String {
7 name.replace("Int32", "Int")
8 .replace("Int64", "Long")
9 .replace("Float32", "Float")
10 .replace("Float64", "Double")
11}
12
13pub struct Generator {
14 files: HashMap<String, String>,
15}
16
17fn type_name(schema: &Schema) -> String {
18 match schema {
19 Schema::Bool => "bool".to_owned(),
20 Schema::Int32 => "int".to_owned(),
21 Schema::Int64 => "long long".to_owned(),
22 Schema::Float32 => "float".to_owned(),
23 Schema::Float64 => "double".to_owned(),
24 Schema::String => "std::string".to_owned(),
25 Schema::OneOf {
26 base_name: name, ..
27 } => format!("std::shared_ptr<{}>", name.camel_case(conv)),
28 Schema::Struct(Struct { name, .. })
29 | Schema::Enum {
30 base_name: name, ..
31 } => format!("{}", name.camel_case(conv)),
32 Schema::Option(inner) => format!("std::shared_ptr<{}>", type_name(inner)),
33 Schema::Vec(inner) => format!("std::vector<{}>", type_name(inner)),
34 Schema::Map(key, value) => format!(
35 "std::unordered_map<{}, {}>",
36 type_name(key),
37 type_name(value)
38 ),
39 }
40}
41
42fn index_var_name(index_var: &mut usize) -> String {
43 let result = "ijk".chars().nth(*index_var).unwrap();
44 *index_var += 1;
45 result.to_string()
46}
47
48fn var_name(name: &str) -> &str {
49 match name.rfind('.') {
50 Some(index) => &name[(index + 1)..],
51 None => name,
52 }
53}
54
55fn write_includes(writer: &mut Writer, schema: &Schema, current: bool) -> std::fmt::Result {
56 let mut includes = vec!["<string>".to_string(), "\"../Stream.hpp\"".to_string()];
57 collect_includes(&mut includes, schema, current);
58 includes.sort();
59 includes.dedup();
60 for include in includes {
61 writeln!(writer, "#include {}", include)?;
62 }
63 Ok(())
64}
65
66fn collect_includes(result: &mut Vec<String>, schema: &Schema, current: bool) {
67 if current {
68 match schema {
69 Schema::Bool
70 | Schema::Int32
71 | Schema::Int64
72 | Schema::Float32
73 | Schema::Float64
74 | Schema::String => {}
75 Schema::Option(_) => {
76 result.push("<memory>".to_string());
77 }
78 Schema::Map(_, _) => {
79 result.push("<unordered_map>".to_string());
80 }
81 Schema::Vec(_) => {
82 result.push("<vector>".to_string());
83 }
84 Schema::Struct(Struct { name, .. })
85 | Schema::OneOf {
86 base_name: name, ..
87 }
88 | Schema::Enum {
89 base_name: name, ..
90 } => {
91 result.push("<stdexcept>".to_string());
92 result.push(format!("\"{}.hpp\"", name.camel_case(conv)));
93 }
94 }
95 }
96 match schema {
97 Schema::Bool
98 | Schema::Int32
99 | Schema::Int64
100 | Schema::Float32
101 | Schema::Float64
102 | Schema::String
103 | Schema::Enum { .. } => {}
104 Schema::Option(inner) => {
105 collect_includes(result, inner, true);
106 }
107 Schema::Map(key_type, value_type) => {
108 collect_includes(result, key_type, true);
109 collect_includes(result, value_type, true);
110 }
111 Schema::Vec(inner) => {
112 collect_includes(result, inner, true);
113 }
114 Schema::Struct(Struct { fields, .. }) => {
115 for field in fields {
116 collect_includes(result, &field.schema, true);
117 }
118 }
119 Schema::OneOf { variants, .. } => {
120 for variant in variants {
121 for field in &variant.fields {
122 collect_includes(result, &field.schema, true);
123 }
124 }
125 }
126 }
127}
128
129fn write_struct_def(
130 writer: &mut Writer,
131 schema: &Schema,
132 struc: &Struct,
133 base: Option<(&Name, usize)>,
134) -> std::fmt::Result {
135 let full_name = if let Some((base_name, _)) = base {
136 format!(
137 "{}::{}",
138 base_name.camel_case(conv),
139 struc.name.camel_case(conv)
140 )
141 } else {
142 struc.name.camel_case(conv)
143 };
144
145 if let Some((base_name, _)) = base {
147 writeln!(
148 writer,
149 "class {}::{} : public {} {{",
150 base_name.camel_case(conv),
151 struc.name.camel_case(conv),
152 base_name.camel_case(conv),
153 )?;
154 } else {
155 writeln!(writer, "class {} {{", struc.name.camel_case(conv))?;
156 }
157 writer.inc_ident();
158 if let Some((_, discriminant)) = base {
159 writer.dec_ident();
160 writeln!(writer, "public:")?;
161 writer.inc_ident();
162 writeln!(writer, "static const int TAG = {};", discriminant)?;
163 }
164
165 writer.dec_ident();
167 writeln!(writer, "public:")?;
168 writer.inc_ident();
169 for field in &struc.fields {
170 writeln!(
171 writer,
172 "{} {};",
173 type_name(&field.schema),
174 field.name.mixed_case(conv)
175 )?;
176 }
177
178 writeln!(writer, "{}();", struc.name.camel_case(conv))?;
180 if !struc.fields.is_empty() {
181 write!(writer, "{}(", struc.name.camel_case(conv))?;
182 for (index, field) in struc.fields.iter().enumerate() {
183 if index > 0 {
184 write!(writer, ", ")?;
185 }
186 write!(
187 writer,
188 "{} {}",
189 type_name(&field.schema),
190 field.name.mixed_case(conv)
191 )?;
192 }
193 writeln!(writer, ");")?;
194 }
195
196 writeln!(
198 writer,
199 "static {} readFrom(InputStream& stream);",
200 struc.name.camel_case(conv)
201 )?;
202 writeln!(writer, "void writeTo(OutputStream& stream) const;")?;
203
204 if schema.hashable() {
206 writeln!(
207 writer,
208 "bool operator ==(const {}& other) const;",
209 struc.name.camel_case(conv)
210 )?;
211 }
212
213 writeln!(
215 writer,
216 "std::string toString() const{};",
217 if base.is_some() { " override" } else { "" }
218 )?;
219
220 writer.dec_ident();
221 writeln!(writer, "}};").unwrap();
222
223 if schema.hashable() {
225 writeln!(writer, "namespace std {{")?;
226 writer.inc_ident();
227 writeln!(writer, "template<>")?;
228 writeln!(writer, "struct hash<{}> {{", full_name)?;
229 writeln!(
230 writer,
231 " size_t operator ()(const {}& value) const;",
232 full_name
233 )?;
234 writeln!(writer, "}};")?;
235 writer.dec_ident();
236 writeln!(writer, "}}")?;
237 }
238
239 Ok(())
240}
241
242fn write_struct_impl(
243 writer: &mut Writer,
244 schema: &Schema,
245 struc: &Struct,
246 base: Option<(&Name, usize)>,
247) -> std::fmt::Result {
248 let full_name = if let Some((base_name, _)) = base {
249 format!(
250 "{}::{}",
251 base_name.camel_case(conv),
252 struc.name.camel_case(conv)
253 )
254 } else {
255 struc.name.camel_case(conv)
256 };
257
258 writeln!(
260 writer,
261 "{}::{}() {{ }}",
262 full_name,
263 struc.name.camel_case(conv)
264 )?;
265 if !struc.fields.is_empty() {
266 write!(writer, "{}::{}(", full_name, struc.name.camel_case(conv))?;
267 for (index, field) in struc.fields.iter().enumerate() {
268 if index > 0 {
269 write!(writer, ", ")?;
270 }
271 write!(
272 writer,
273 "{} {}",
274 type_name(&field.schema),
275 field.name.mixed_case(conv),
276 )?;
277 }
278 write!(writer, ") : ")?;
279 for (index, field) in struc.fields.iter().enumerate() {
280 write!(
281 writer,
282 "{}({})",
283 field.name.mixed_case(conv),
284 field.name.mixed_case(conv),
285 )?;
286 if index + 1 < struc.fields.len() {
287 write!(writer, ", ")?;
288 } else {
289 writeln!(writer, " {{ }}")?;
290 }
291 }
292 }
293
294 writeln!(
296 writer,
297 "{} {}::readFrom(InputStream& stream) {{",
298 full_name, full_name,
299 )?;
300 writer.inc_ident();
301 writeln!(writer, "{} result;", full_name)?;
302 for field in &struc.fields {
303 fn assign(
304 writer: &mut Writer,
305 to: &str,
306 schema: &Schema,
307 index_var: &mut usize,
308 ) -> std::fmt::Result {
309 match schema {
310 Schema::Bool => {
311 writeln!(writer, "{} = stream.readBool();", to)?;
312 }
313 Schema::Int32 => {
314 writeln!(writer, "{} = stream.readInt();", to)?;
315 }
316 Schema::Int64 => {
317 writeln!(writer, "{} = stream.readLongLong();", to)?;
318 }
319 Schema::Float32 => {
320 writeln!(writer, "{} = stream.readFloat();", to)?;
321 }
322 Schema::Float64 => {
323 writeln!(writer, "{} = stream.readDouble();", to)?;
324 }
325 Schema::String => {
326 writeln!(writer, "{} = stream.readString();", to)?;
327 }
328 Schema::Struct(Struct { name, .. })
329 | Schema::OneOf {
330 base_name: name, ..
331 } => {
332 writeln!(
333 writer,
334 "{} = {}::readFrom(stream);",
335 to,
336 name.camel_case(conv)
337 )?;
338 }
339 Schema::Option(inner) => {
340 writeln!(writer, "if (stream.readBool()) {{")?;
341 writer.inc_ident();
342 writeln!(
343 writer,
344 "{} = std::shared_ptr<{}>(new {}());",
345 to,
346 type_name(inner),
347 type_name(inner)
348 )?;
349 assign(writer, &format!("*{}", to), inner, index_var)?;
350 writer.dec_ident();
351 writeln!(writer, "}} else {{")?;
352 writeln!(
353 writer,
354 " {} = std::shared_ptr<{}>();",
355 to,
356 type_name(inner)
357 )?;
358 writeln!(writer, "}}")?;
359 }
360 Schema::Vec(inner) => {
361 writeln!(
362 writer,
363 "{} = std::vector<{}>(stream.readInt());",
364 to,
365 type_name(inner),
366 )?;
367 let index_var_name = index_var_name(index_var);
368 writeln!(
369 writer,
370 "for (size_t {} = 0; {} < {}.size(); {}++) {{",
371 index_var_name, index_var_name, to, index_var_name
372 )?;
373 writer.inc_ident();
374 assign(
375 writer,
376 &format!("{}[{}]", to, index_var_name),
377 inner,
378 index_var,
379 )?;
380 writer.dec_ident();
381 writeln!(writer, "}}")?;
382 }
383 Schema::Map(key_type, value_type) => {
384 let to_size = format!("{}Size", var_name(to));
385 writeln!(writer, "size_t {} = stream.readInt();", to_size)?;
386 writeln!(
387 writer,
388 "{} = std::unordered_map<{}, {}>();",
389 to,
390 type_name(key_type),
391 type_name(value_type)
392 )?;
393 writeln!(writer, "{}.reserve({});", to, to_size)?;
394 let index_var_name = index_var_name(index_var);
395 writeln!(
396 writer,
397 "for (size_t {} = 0; {} < {}; {}++) {{",
398 index_var_name, index_var_name, to_size, index_var_name
399 )?;
400 writer.inc_ident();
401 writeln!(writer, "{} {}Key;", type_name(key_type), var_name(to))?;
402 assign(writer, &format!("{}Key", var_name(to)), key_type, index_var)?;
403 writeln!(writer, "{} {}Value;", type_name(value_type), var_name(to))?;
404 assign(
405 writer,
406 &format!("{}Value", var_name(to)),
407 value_type,
408 index_var,
409 )?;
410 writeln!(
411 writer,
412 "{}.emplace(std::make_pair({}Key, {}Value));",
413 to,
414 var_name(to),
415 var_name(to)
416 )?;
417 writer.dec_ident();
418 writeln!(writer, "}}")?;
419 }
420 Schema::Enum {
421 base_name,
422 variants,
423 } => {
424 writeln!(writer, "switch (stream.readInt()) {{")?;
425 for (discriminant, variant) in variants.iter().enumerate() {
426 writeln!(writer, "case {}:", discriminant)?;
427 writeln!(
428 writer,
429 " {} = {}::{};",
430 to,
431 base_name.camel_case(conv),
432 variant.shouty_snake_case(conv)
433 )?;
434 writeln!(writer, " break;")?;
435 }
436 writeln!(writer, "default:")?;
437 writeln!(
438 writer,
439 " throw std::runtime_error(\"Unexpected discriminant value\");"
440 )?;
441 writeln!(writer, "}}")?;
442 }
443 }
444 Ok(())
445 }
446 assign(
447 writer,
448 &format!("result.{}", field.name.mixed_case(conv)),
449 &field.schema,
450 &mut 0,
451 )?;
452 }
453 writeln!(writer, "return result;")?;
454 writer.dec_ident();
455 writeln!(writer, "}}")?;
456
457 writeln!(
459 writer,
460 "void {}::writeTo(OutputStream& stream) const {{",
461 full_name,
462 )?;
463 writer.inc_ident();
464 if base.is_some() {
465 writeln!(writer, "stream.write(TAG);")?;
466 }
467 if let Some(magic) = struc.magic {
468 writeln!(writer, "stream.write({});", magic)?;
469 }
470 for field in &struc.fields {
471 fn write(writer: &mut Writer, value: &str, schema: &Schema) -> std::fmt::Result {
472 match schema {
473 Schema::Bool => {
474 writeln!(writer, "stream.write({});", value)?;
475 }
476 Schema::Int32 => {
477 writeln!(writer, "stream.write({});", value)?;
478 }
479 Schema::Int64 => {
480 writeln!(writer, "stream.write({});", value)?;
481 }
482 Schema::Float32 => {
483 writeln!(writer, "stream.write({});", value)?;
484 }
485 Schema::Float64 => {
486 writeln!(writer, "stream.write({});", value)?;
487 }
488 Schema::String => {
489 writeln!(writer, "stream.write({});", value)?;
490 }
491 Schema::Struct(_) => {
492 writeln!(writer, "{}.writeTo(stream);", value)?;
493 }
494 Schema::OneOf { .. } => {
495 writeln!(writer, "{}->writeTo(stream);", value)?;
496 }
497 Schema::Option(inner) => {
498 writeln!(writer, "if ({}) {{", value)?;
499 writer.inc_ident();
500 writeln!(writer, "stream.write(true);")?;
501 write(writer, &format!("(*{})", value), inner)?;
502 writer.dec_ident();
503 writeln!(writer, "}} else {{")?;
504 writeln!(writer, " stream.write(false);")?;
505 writeln!(writer, "}}")?;
506 }
507 Schema::Vec(inner) => {
508 writeln!(writer, "stream.write((int)({}.size()));", value)?;
509 writeln!(
510 writer,
511 "for (const {}& {}Element : {}) {{",
512 type_name(inner),
513 var_name(value),
514 value
515 )?;
516 writer.inc_ident();
517 write(writer, &format!("{}Element", var_name(value)), inner)?;
518 writer.dec_ident();
519 writeln!(writer, "}}")?;
520 }
521 Schema::Map(key_type, value_type) => {
522 writeln!(writer, "stream.write((int)({}.size()));", value)?;
523 writeln!(
524 writer,
525 "for (const auto& {}Entry : {}) {{",
526 var_name(value),
527 value
528 )?;
529 writer.inc_ident();
530 write(writer, &format!("{}Entry.first", var_name(value)), key_type)?;
531 write(
532 writer,
533 &format!("{}Entry.second", var_name(value)),
534 value_type,
535 )?;
536 writer.dec_ident();
537 writeln!(writer, "}}")?;
538 }
539 Schema::Enum { .. } => {
540 writeln!(writer, "stream.write((int)({}));", value)?;
541 }
542 }
543 Ok(())
544 }
545 write(writer, &field.name.mixed_case(conv), &field.schema)?;
546 }
547 writer.dec_ident();
548 writeln!(writer, "}}")?;
549
550 if schema.hashable() {
552 writeln!(
553 writer,
554 "bool {}::operator ==(const {}& other) const {{",
555 full_name, full_name,
556 )?;
557 write!(writer, " return ")?;
558 for (index, field) in struc.fields.iter().enumerate() {
559 if index > 0 {
560 write!(writer, " && ")?;
561 }
562 write!(
563 writer,
564 "{} == other.{}",
565 field.name.mixed_case(conv),
566 field.name.mixed_case(conv),
567 )?;
568 }
569 writeln!(writer, ";")?;
570 writeln!(writer, "}}")?;
571 }
572
573 if schema.hashable() {
575 writeln!(
576 writer,
577 "size_t std::hash<{}>::operator ()(const {}& value) const {{",
578 full_name, full_name,
579 )?;
580 writer.inc_ident();
581 writeln!(writer, "size_t result = 0;")?;
582 for field in &struc.fields {
583 writeln!(
584 writer,
585 "result ^= std::hash<{}>{{}}(value.{}) + 0x9e3779b9 + (result<<6) + (result>>2);",
586 type_name(&field.schema),
587 field.name.mixed_case(conv),
588 )?;
589 }
590 writeln!(writer, "return result;")?;
591 writer.dec_ident();
592 writeln!(writer, "}}")?;
593 }
594
595 writeln!(writer, "std::string {}::toString() const {{", full_name)?;
597 writer.inc_ident();
598 writeln!(writer, "return std::string({:?}) + \"(\" +", full_name)?;
599 writer.inc_ident();
600 for field in &struc.fields {
601 match *field.schema {
602 Schema::Struct(_) => {
603 writeln!(writer, "{}.toString() +", field.name.mixed_case(conv))?;
604 }
605 Schema::OneOf { .. } => {
606 writeln!(writer, "{}->toString() +", field.name.mixed_case(conv))?;
607 }
608 Schema::Bool => {
609 writeln!(
610 writer,
611 "({} ? \"true\" : \"false\") + ",
612 field.name.mixed_case(conv)
613 )?;
614 }
615 Schema::String => {
616 writeln!(writer, "{} + ", field.name.mixed_case(conv))?;
617 }
618 Schema::Int32 | Schema::Int64 | Schema::Float32 | Schema::Float64 => {
619 writeln!(writer, "std::to_string({}) +", field.name.mixed_case(conv))?;
620 }
621 _ => {
622 writeln!(writer, "\"TODO\" + ")?;
623 }
624 }
625 }
626 writeln!(writer, "\")\";")?;
627 writer.dec_ident();
628 writer.dec_ident();
629 writeln!(writer, "}}")?;
630
631 Ok(())
632}
633
634impl trans_gen_core::Generator for Generator {
635 fn new(name: &str, version: &str) -> Self {
636 let mut files = HashMap::new();
637 files.insert(
638 "Stream.hpp".to_owned(),
639 include_str!("../template/Stream.hpp").to_owned(),
640 );
641 files.insert(
642 "Stream.cpp".to_owned(),
643 include_str!("../template/Stream.cpp").to_owned(),
644 );
645 Self { files }
646 }
647 fn result(self) -> HashMap<String, String> {
648 self.files
649 }
650 fn add_only(&mut self, schema: &Schema) {
651 match schema {
652 Schema::Enum {
653 base_name,
654 variants,
655 } => {
656 let file_name = format!("model/{}.hpp", base_name.camel_case(conv));
657 let mut writer = Writer::new();
658 writeln!(
659 writer,
660 "#ifndef _MODEL_{}_HPP_",
661 base_name.shouty_snake_case(conv)
662 )
663 .unwrap();
664 writeln!(
665 writer,
666 "#define _MODEL_{}_HPP_",
667 base_name.shouty_snake_case(conv)
668 )
669 .unwrap();
670 writeln!(writer).unwrap();
671 writeln!(writer, "#include \"../Stream.hpp\"").unwrap();
672 writeln!(writer).unwrap();
673 writeln!(writer, "enum {} {{", base_name.camel_case(conv)).unwrap();
674 writer.inc_ident();
675 for (index, variant) in variants.iter().enumerate() {
676 writeln!(
677 writer,
678 "{} = {}{}",
679 variant.shouty_snake_case(conv),
680 index,
681 if index + 1 < variants.len() { "," } else { "" }
682 )
683 .unwrap();
684 }
685 writer.dec_ident();
686 writeln!(writer, "}};").unwrap();
687 writeln!(writer).unwrap();
688 writeln!(writer, "#endif").unwrap();
689 self.files.insert(file_name, writer.get());
690 }
691 Schema::Struct(struc) => {
692 let file_name = format!("model/{}.hpp", struc.name.camel_case(conv));
693 let mut writer = Writer::new();
694 writeln!(
695 writer,
696 "#ifndef _MODEL_{}_HPP_",
697 struc.name.shouty_snake_case(conv)
698 )
699 .unwrap();
700 writeln!(
701 writer,
702 "#define _MODEL_{}_HPP_",
703 struc.name.shouty_snake_case(conv)
704 )
705 .unwrap();
706 writeln!(writer).unwrap();
707 write_includes(&mut writer, schema, false).unwrap();
708 writeln!(writer).unwrap();
709 write_struct_def(&mut writer, schema, struc, None).unwrap();
710 writeln!(writer).unwrap();
711 writeln!(writer, "#endif").unwrap();
712 self.files.insert(file_name, writer.get());
713
714 let file_name = format!("model/{}.cpp", struc.name.camel_case(conv));
715 let mut writer = Writer::new();
716 writeln!(writer, "#include \"{}.hpp\"", struc.name.camel_case(conv)).unwrap();
717 writeln!(writer).unwrap();
718 write_struct_impl(&mut writer, schema, struc, None).unwrap();
719 self.files.insert(file_name, writer.get());
720 }
721 Schema::OneOf {
722 base_name,
723 variants,
724 } => {
725 let file_name = format!("model/{}.hpp", base_name.camel_case(conv));
726 let mut writer = Writer::new();
727 writeln!(
728 writer,
729 "#ifndef _MODEL_{}_HPP_",
730 base_name.shouty_snake_case(conv)
731 )
732 .unwrap();
733 writeln!(
734 writer,
735 "#define _MODEL_{}_HPP_",
736 base_name.shouty_snake_case(conv)
737 )
738 .unwrap();
739 writeln!(writer).unwrap();
740 writeln!(writer, "#include <memory>").unwrap();
741 write_includes(&mut writer, schema, false).unwrap();
742 writeln!(writer).unwrap();
743 writeln!(writer, "class {} {{", base_name.camel_case(conv)).unwrap();
744 writeln!(writer, "public:").unwrap();
745 writer.inc_ident();
746 for variant in variants {
747 writeln!(writer, "class {};", variant.name.camel_case(conv)).unwrap();
748 }
749 writeln!(writer).unwrap();
750 writeln!(
751 writer,
752 "static std::shared_ptr<{}> readFrom(InputStream& stream);",
753 base_name.camel_case(conv)
754 )
755 .unwrap();
756 writeln!(
757 writer,
758 "virtual void writeTo(OutputStream& stream) const = 0;",
759 )
760 .unwrap();
761 writeln!(writer, "virtual std::string toString() const = 0;").unwrap();
762 writer.dec_ident();
763 writeln!(writer, "}};").unwrap();
764 for (discriminant, variant) in variants.iter().enumerate() {
765 writeln!(writer).unwrap();
766 write_struct_def(
767 &mut writer,
768 schema,
769 variant,
770 Some((base_name, discriminant)),
771 )
772 .unwrap();
773 }
774 writeln!(writer).unwrap();
775 writeln!(writer, "#endif").unwrap();
776 self.files.insert(file_name, writer.get());
777
778 let file_name = format!("model/{}.cpp", base_name.camel_case(conv));
779 let mut writer = Writer::new();
780 writeln!(writer, "#include \"{}.hpp\"", base_name.camel_case(conv)).unwrap();
781 writeln!(writer, "#include <stdexcept>").unwrap();
782 for (discriminant, variant) in variants.iter().enumerate() {
783 writeln!(writer).unwrap();
784 write_struct_impl(
785 &mut writer,
786 schema,
787 variant,
788 Some((base_name, discriminant)),
789 )
790 .unwrap();
791 }
792
793 writeln!(
795 writer,
796 "std::shared_ptr<{}> {}::readFrom(InputStream& stream) {{",
797 base_name.camel_case(conv),
798 base_name.camel_case(conv),
799 )
800 .unwrap();
801 writer.inc_ident();
802 writeln!(writer, "switch (stream.readInt()) {{").unwrap();
803 for (discriminant, variant) in variants.iter().enumerate() {
804 writeln!(writer, "case {}:", discriminant).unwrap();
805 let variant_name = format!(
806 "{}::{}",
807 base_name.camel_case(conv),
808 variant.name.camel_case(conv)
809 );
810 writeln!(
811 writer,
812 " return std::shared_ptr<{}>(new {}({}::readFrom(stream)));",
813 variant_name, variant_name, variant_name,
814 )
815 .unwrap();
816 }
817 writeln!(writer, "default:").unwrap();
818 writeln!(
819 writer,
820 " throw std::runtime_error(\"Unexpected discriminant value\");"
821 )
822 .unwrap();
823 writeln!(writer, "}}").unwrap();
824 writer.dec_ident();
825 writeln!(writer, "}};").unwrap();
826
827 self.files.insert(file_name, writer.get());
828 }
829 Schema::Bool
830 | Schema::Int32
831 | Schema::Int64
832 | Schema::Float32
833 | Schema::Float64
834 | Schema::String
835 | Schema::Option(_)
836 | Schema::Vec(_)
837 | Schema::Map(_, _) => {}
838 }
839 }
840}