#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct CapnpField {
pub name: String,
pub field_type: String,
pub index: usize,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct CapnpStruct {
pub name: String,
pub fields: Vec<CapnpField>,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Default)]
pub struct CapnpExport {
pub file_id: u64,
pub structs: Vec<CapnpStruct>,
}
#[allow(dead_code)]
pub fn new_capnp_export(file_id: u64) -> CapnpExport {
CapnpExport {
file_id,
structs: Vec::new(),
}
}
#[allow(dead_code)]
pub fn add_capnp_struct(doc: &mut CapnpExport, name: &str) {
doc.structs.push(CapnpStruct {
name: name.to_string(),
fields: Vec::new(),
});
}
#[allow(dead_code)]
pub fn add_capnp_field(doc: &mut CapnpExport, name: &str, field_type: &str) {
if let Some(s) = doc.structs.last_mut() {
let idx = s.fields.len();
s.fields.push(CapnpField {
name: name.to_string(),
field_type: field_type.to_string(),
index: idx,
});
}
}
#[allow(dead_code)]
pub fn capnp_struct_count(doc: &CapnpExport) -> usize {
doc.structs.len()
}
#[allow(dead_code)]
pub fn capnp_last_struct_field_count(doc: &CapnpExport) -> usize {
doc.structs.last().map_or(0, |s| s.fields.len())
}
#[allow(dead_code)]
pub fn to_capnp_schema(doc: &CapnpExport) -> String {
let mut out = format!("@0x{:016x};\n\n", doc.file_id);
for st in &doc.structs {
out.push_str(&format!("struct {} {{\n", st.name));
for f in &st.fields {
out.push_str(&format!(" {} @{} :{},\n", f.name, f.index, f.field_type));
}
out.push_str("}\n\n");
}
out
}
#[allow(dead_code)]
pub fn export_mesh_capnp_schema(vertex_count: usize, index_count: usize) -> String {
let mut doc = new_capnp_export(0xdeadbeefcafe0001);
add_capnp_struct(&mut doc, "Mesh");
add_capnp_field(&mut doc, "vertexCount", "UInt32");
add_capnp_field(&mut doc, "indexCount", "UInt32");
add_capnp_field(&mut doc, "positions", "List(Float32)");
let mut comment = format!(
"# vertexCount={}, indexCount={}\n",
vertex_count, index_count
);
comment.push_str(&to_capnp_schema(&doc));
comment
}
#[allow(dead_code)]
pub fn find_capnp_struct<'a>(doc: &'a CapnpExport, name: &str) -> Option<&'a CapnpStruct> {
doc.structs.iter().find(|s| s.name == name)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_capnp_export_empty() {
let doc = new_capnp_export(1);
assert_eq!(capnp_struct_count(&doc), 0);
}
#[test]
fn test_add_struct() {
let mut doc = new_capnp_export(1);
add_capnp_struct(&mut doc, "Vertex");
assert_eq!(capnp_struct_count(&doc), 1);
}
#[test]
fn test_add_field() {
let mut doc = new_capnp_export(1);
add_capnp_struct(&mut doc, "Mesh");
add_capnp_field(&mut doc, "count", "UInt32");
assert_eq!(capnp_last_struct_field_count(&doc), 1);
}
#[test]
fn test_to_capnp_schema_contains_struct() {
let mut doc = new_capnp_export(1);
add_capnp_struct(&mut doc, "MyStruct");
let s = to_capnp_schema(&doc);
assert!(s.contains("struct MyStruct"));
}
#[test]
fn test_to_capnp_schema_contains_field() {
let mut doc = new_capnp_export(1);
add_capnp_struct(&mut doc, "M");
add_capnp_field(&mut doc, "vertices", "UInt32");
let s = to_capnp_schema(&doc);
assert!(s.contains("vertices"));
}
#[test]
fn test_to_capnp_schema_has_file_id() {
let doc = new_capnp_export(0x1234);
let s = to_capnp_schema(&doc);
assert!(s.contains("@0x"));
}
#[test]
fn test_export_mesh_capnp_schema() {
let s = export_mesh_capnp_schema(100, 300);
assert!(s.contains("Mesh"));
assert!(s.contains("vertexCount=100"));
}
#[test]
fn test_find_capnp_struct() {
let mut doc = new_capnp_export(1);
add_capnp_struct(&mut doc, "Bone");
assert!(find_capnp_struct(&doc, "Bone").is_some());
}
#[test]
fn test_find_missing_struct() {
let doc = new_capnp_export(1);
assert!(find_capnp_struct(&doc, "Ghost").is_none());
}
#[test]
fn test_field_index_increments() {
let mut doc = new_capnp_export(1);
add_capnp_struct(&mut doc, "M");
add_capnp_field(&mut doc, "a", "Int32");
add_capnp_field(&mut doc, "b", "Int32");
let st = find_capnp_struct(&doc, "M").expect("should succeed");
assert_eq!(st.fields[1].index, 1);
}
}