use rustyasn::schema::Schema;
use rustyfix_dictionary::Dictionary;
use std::sync::Arc;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== RustyASN Schema Architecture Demo ===\n");
let dict = Arc::new(Dictionary::fix44()?);
println!(
"Loaded FIX 4.4 dictionary with {} fields and {} messages",
dict.fields().len(),
dict.messages().len()
);
let schema = Schema::new(dict.clone());
println!("\n1. Dictionary-driven field type extraction:");
println!(" Total fields in schema: {}", schema.field_count());
let example_fields = [
(8, "BeginString"),
(35, "MsgType"),
(34, "MsgSeqNum"),
(49, "SenderCompID"),
(56, "TargetCompID"),
(52, "SendingTime"),
];
for (tag, name) in example_fields {
if let Some(field_type) = schema.get_field_type(tag) {
println!(
" Field {} ({}): {:?}, Header: {}, Trailer: {}",
tag, name, field_type.fix_type, field_type.in_header, field_type.in_trailer
);
}
}
println!("\n2. Dictionary-driven message schema extraction:");
println!(" Total messages in schema: {}", schema.message_count());
let example_messages = [
("0", "Heartbeat"),
("1", "TestRequest"),
("A", "Logon"),
("D", "NewOrderSingle"),
("8", "ExecutionReport"),
("V", "MarketDataRequest"),
];
for (msg_type, name) in example_messages {
if let Some(message_schema) = schema.get_message_schema(msg_type) {
println!(
" Message {} ({}): {} required fields, {} optional fields, {} groups",
msg_type,
name,
message_schema.required_fields.len(),
message_schema.optional_fields.len(),
message_schema.groups.len()
);
if !message_schema.required_fields.is_empty() {
let required_sample: Vec<u16> = message_schema
.required_fields
.iter()
.take(3)
.cloned()
.collect();
println!(" Required fields (sample): {required_sample:?}");
}
if !message_schema.groups.is_empty() {
println!(
" Groups: {:?}",
message_schema.groups.keys().collect::<Vec<_>>()
);
}
}
}
println!("\n3. Field type validation:");
let test_cases = [
(35, "D".as_bytes(), "MsgType (string)"),
(34, "123".as_bytes(), "MsgSeqNum (sequence number)"),
(
52,
"20240101-12:30:45".as_bytes(),
"SendingTime (UTC timestamp)",
),
(8, "FIX.4.4".as_bytes(), "BeginString (string)"),
];
for (tag, value, description) in test_cases {
match schema.map_field_type(tag, value) {
Ok(mapped_value) => {
println!(" ✓ {description} -> {mapped_value}");
}
Err(e) => {
println!(" ✗ {description} -> Error: {e}");
}
}
}
println!("\n4. Data type mapping from dictionary to schema:");
use rustyfix_dictionary::FixDatatype;
let type_examples = [
(FixDatatype::String, "String"),
(FixDatatype::Int, "Integer"),
(FixDatatype::Float, "Float"),
(FixDatatype::Price, "Price"),
(FixDatatype::Quantity, "Quantity"),
(FixDatatype::UtcTimestamp, "UTC Timestamp"),
(FixDatatype::Boolean, "Boolean"),
(FixDatatype::Char, "Character"),
];
for (dict_type, name) in type_examples {
let schema_type = schema.map_dictionary_type_to_schema_type_public(dict_type);
println!(" {name} -> {schema_type:?}");
}
println!("\n5. Header/Trailer field detection:");
let header_fields: Vec<u16> = schema
.field_types()
.filter(|(_, info)| info.in_header)
.map(|(tag, _)| tag)
.take(10)
.collect();
let trailer_fields: Vec<u16> = schema
.field_types()
.filter(|(_, info)| info.in_trailer)
.map(|(tag, _)| tag)
.collect();
println!(" Header fields (sample): {header_fields:?}");
println!(" Trailer fields: {trailer_fields:?}");
println!("\n=== Summary ===");
println!("The schema architecture has been successfully upgraded to:");
println!("• Extract ALL field definitions from the FIX dictionary");
println!("• Extract ALL message structures from the FIX dictionary");
println!("• Dynamically map dictionary types to schema types");
println!("• Automatically detect header/trailer field locations");
println!("• Process repeating groups from message layouts");
println!("• Maintain full backward compatibility with existing APIs");
Ok(())
}