onnx_std/textproto/
mod.rs1use prost_reflect::{DynamicMessage, text_format::FormatOptions};
7
8use crate::{Error, Model, Result};
9
10pub fn to_textproto(model: &Model) -> Result<String> {
12 let dynamic = crate::proto_serde::to_dynamic(&model.to_proto()?)
13 .map_err(|error| textproto_error(error.to_string()))?;
14 Ok(dynamic.to_text_format_with_options(&FormatOptions::new().pretty(true)))
15}
16
17pub fn from_textproto(source: &str) -> Result<Model> {
19 let dynamic = DynamicMessage::parse_text_format(crate::proto_serde::descriptor(), source)
20 .map_err(|error| textproto_error(error.to_string()))?;
21 let proto = crate::proto_serde::from_dynamic(&dynamic)
22 .map_err(|error| textproto_error(error.to_string()))?;
23 Model::from_proto(proto)
24}
25
26pub fn to_binary(source: &str) -> Result<Vec<u8>> {
39 use prost::Message;
40 let dynamic = DynamicMessage::parse_text_format(crate::proto_serde::descriptor(), source)
41 .map_err(|error| textproto_error(error.to_string()))?;
42 Ok(dynamic.encode_to_vec())
43}
44
45fn textproto_error(message: impl Into<String>) -> Error {
46 Error::TextProto(message.into())
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn parses_comments_and_alternate_delimiters() {
55 let source = r#"
56 # protobuf comment
57 ir_version: 10
58 opset_import < domain: "" version: 21 >
59 graph {
60 name: "main"
61 input {
62 name: "X"
63 type { tensor_type { elem_type: 1 shape { dim { dim_value: 2 } } } }
64 }
65 output {
66 name: "Y"
67 type { tensor_type { elem_type: 1 shape { dim { dim_value: 2 } } } }
68 }
69 node { input: "X" output: "Y" op_type: "Identity" }
70 }
71 "#;
72 let model = from_textproto(source).unwrap();
73 assert_eq!(model.graph.num_nodes(), 1);
74 let printed = to_textproto(&model).unwrap();
75 assert!(printed.contains("elem_type: 1"));
76 assert!(printed.contains("op_type: \"Identity\""));
77 }
78}