use ironsbe_schema::ir::SchemaIr;
use crate::rust::{EnumGenerator, MessageGenerator, TypeGenerator};
pub struct Generator<'a> {
ir: &'a SchemaIr,
}
impl<'a> Generator<'a> {
#[must_use]
pub fn new(ir: &'a SchemaIr) -> Self {
Self { ir }
}
#[must_use]
pub fn generate(&self) -> String {
let mut output = String::with_capacity(64 * 1024);
self.generate_header(&mut output);
self.generate_constants(&mut output);
let type_gen = TypeGenerator::new(self.ir);
output.push_str(&type_gen.generate());
let enum_gen = EnumGenerator::new(self.ir);
output.push_str(&enum_gen.generate());
let msg_gen = MessageGenerator::new(self.ir);
output.push_str(&msg_gen.generate());
output
}
fn generate_header(&self, output: &mut String) {
output.push_str("// Generated by IronSBE codegen - DO NOT EDIT\n");
output.push_str(&format!(
"// Schema: {} v{}\n",
self.ir.package, self.ir.schema_version
));
output.push('\n');
output.push_str("use ironsbe_core::{\n");
output.push_str(" buffer::{ReadBuffer, WriteBuffer},\n");
output.push_str(" header::{MessageHeader, GroupHeader, VarDataHeader},\n");
output.push_str(" decoder::{SbeDecoder, DecodeError},\n");
output.push_str(" encoder::SbeEncoder,\n");
output.push_str("};\n");
output.push('\n');
}
fn generate_constants(&self, output: &mut String) {
output.push_str(&format!(
"/// Schema ID for this protocol.\n\
pub const SCHEMA_ID: u16 = {};\n",
self.ir.schema_id
));
output.push_str(&format!(
"/// Schema version for this protocol.\n\
pub const SCHEMA_VERSION: u16 = {};\n",
self.ir.schema_version
));
output.push('\n');
}
}
#[cfg(test)]
mod tests {
use super::*;
use ironsbe_schema::parse_schema;
#[test]
fn test_generate_simple_schema() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<sbe:messageSchema xmlns:sbe="http://fixprotocol.io/2016/sbe"
package="test" id="1" version="1" byteOrder="littleEndian">
<types>
<type name="uint64" primitiveType="uint64"/>
</types>
<sbe:message name="TestMessage" id="1" blockLength="8">
<field name="value" id="1" type="uint64" offset="0"/>
</sbe:message>
</sbe:messageSchema>"#;
let schema = parse_schema(xml).expect("Failed to parse");
let ir = SchemaIr::from_schema(&schema);
let generator = Generator::new(&ir);
let code = generator.generate();
assert!(code.contains("SCHEMA_ID: u16 = 1"));
assert!(code.contains("SCHEMA_VERSION: u16 = 1"));
assert!(code.contains("TestMessageDecoder"));
assert!(code.contains("TestMessageEncoder"));
}
}