#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ProtoFieldDef {
pub name: String,
pub proto_type: String,
pub field_number: u32,
pub repeated: bool,
}
#[derive(Debug, Clone, Default)]
pub struct ProtoMessageDef {
pub name: String,
pub fields: Vec<ProtoFieldDef>,
}
impl ProtoMessageDef {
pub fn new(name: &str) -> Self {
Self { name: name.into(), fields: vec![] }
}
}
#[derive(Debug, Clone, Default)]
pub struct ProtoSchemaDef {
pub syntax: String,
pub package: String,
pub messages: Vec<ProtoMessageDef>,
}
pub fn new_proto_schema(package: &str) -> ProtoSchemaDef {
ProtoSchemaDef { syntax: "proto3".into(), package: package.into(), messages: vec![] }
}
pub fn add_proto_message(schema: &mut ProtoSchemaDef, msg: ProtoMessageDef) {
schema.messages.push(msg);
}
pub fn add_field(msg: &mut ProtoMessageDef, name: &str, proto_type: &str, field_number: u32, repeated: bool) {
msg.fields.push(ProtoFieldDef {
name: name.into(),
proto_type: proto_type.into(),
field_number,
repeated,
});
}
pub fn schema_to_proto_string(schema: &ProtoSchemaDef) -> String {
let mut out = format!("syntax = \"{}\";\n\npackage {};\n\n", schema.syntax, schema.package);
for msg in &schema.messages {
out.push_str(&format!("message {} {{\n", msg.name));
for f in &msg.fields {
let rep = if f.repeated { "repeated " } else { "" };
out.push_str(&format!(" {}{} {} = {};\n", rep, f.proto_type, f.name, f.field_number));
}
out.push_str("}\n\n");
}
out
}
pub fn export_mesh_proto_schema(positions: &[[f32; 3]]) -> ProtoSchemaDef {
let mut schema = new_proto_schema("oxihuman");
let mut vertex_msg = ProtoMessageDef::new("Vertex");
add_field(&mut vertex_msg, "x", "float", 1, false);
add_field(&mut vertex_msg, "y", "float", 2, false);
add_field(&mut vertex_msg, "z", "float", 3, false);
add_proto_message(&mut schema, vertex_msg);
let mut mesh_msg = ProtoMessageDef::new("Mesh");
add_field(&mut mesh_msg, "vertices", "Vertex", 1, true);
add_field(&mut mesh_msg, "indices", "uint32", 2, true);
add_field(&mut mesh_msg, "vertex_count", "uint32", 3, false);
if let Some(last_field) = mesh_msg.fields.last_mut() {
let _ = last_field;
}
let _ = positions.len();
add_proto_message(&mut schema, mesh_msg);
schema
}
pub fn proto_message_count(schema: &ProtoSchemaDef) -> usize {
schema.messages.len()
}
pub fn proto_field_count(msg: &ProtoMessageDef) -> usize {
msg.fields.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_proto_schema() {
let s = new_proto_schema("test.pkg");
assert_eq!(s.syntax, "proto3");
assert_eq!(s.package, "test.pkg");
}
#[test]
fn test_add_message() {
let mut s = new_proto_schema("pkg");
add_proto_message(&mut s, ProtoMessageDef::new("Foo"));
assert_eq!(proto_message_count(&s), 1);
}
#[test]
fn test_add_field_increases_count() {
let mut msg = ProtoMessageDef::new("Bar");
add_field(&mut msg, "id", "uint32", 1, false);
assert_eq!(proto_field_count(&msg), 1);
}
#[test]
fn test_schema_to_proto_contains_syntax() {
let s = new_proto_schema("p");
let out = schema_to_proto_string(&s);
assert!(out.contains("syntax = \"proto3\""));
}
#[test]
fn test_schema_to_proto_contains_package() {
let s = new_proto_schema("mypkg");
assert!(schema_to_proto_string(&s).contains("mypkg"));
}
#[test]
fn test_schema_to_proto_contains_message() {
let mut s = new_proto_schema("p");
add_proto_message(&mut s, ProtoMessageDef::new("MyMsg"));
assert!(schema_to_proto_string(&s).contains("message MyMsg"));
}
#[test]
fn test_schema_to_proto_repeated_field() {
let mut s = new_proto_schema("p");
let mut msg = ProtoMessageDef::new("M");
add_field(&mut msg, "items", "float", 1, true);
add_proto_message(&mut s, msg);
assert!(schema_to_proto_string(&s).contains("repeated"));
}
#[test]
fn test_export_mesh_proto_schema() {
let p = vec![[0.0f32,0.0,0.0],[1.0,0.0,0.0]];
let s = export_mesh_proto_schema(&p);
assert_eq!(proto_message_count(&s), 2);
}
#[test]
fn test_export_mesh_proto_vertex_fields() {
let s = export_mesh_proto_schema(&[]);
assert_eq!(proto_field_count(&s.messages[0]), 3);
}
#[test]
fn test_proto_field_number() {
let mut msg = ProtoMessageDef::new("T");
add_field(&mut msg, "val", "int32", 42, false);
assert_eq!(msg.fields[0].field_number, 42);
}
}