mod decoder;
mod encoder;
mod error;
mod string;
mod token;
pub use decoder::TextDecoder;
pub use encoder::TextEncoder;
pub use error::{ParseError, ParseErrorKind};
pub use string::{escape_bytes, escape_str, unescape, unescape_str, UnescapeError};
pub use token::{NameKind, ScalarKind, Token, TokenKind, Tokenizer};
use alloc::string::String;
pub trait TextFormat: crate::Message {
fn encode_text(&self, enc: &mut TextEncoder<'_>) -> core::fmt::Result;
fn merge_text(&mut self, dec: &mut TextDecoder<'_>) -> Result<(), ParseError>;
}
#[must_use]
pub fn encode_to_string<M: TextFormat>(msg: &M) -> String {
let mut out = String::new();
let mut enc = TextEncoder::new(&mut out);
let _ = msg.encode_text(&mut enc);
out
}
#[must_use]
pub fn encode_to_string_pretty<M: TextFormat>(msg: &M) -> String {
let mut out = String::new();
let mut enc = TextEncoder::new_pretty(&mut out);
let _ = msg.encode_text(&mut enc);
if !out.is_empty() {
out.push('\n');
}
out
}
pub fn decode_from_str<M: TextFormat + Default>(s: &str) -> Result<M, ParseError> {
let mut msg = M::default();
merge_from_str(&mut msg, s)?;
Ok(msg)
}
pub fn merge_from_str<M: TextFormat>(msg: &mut M, s: &str) -> Result<(), ParseError> {
let mut dec = TextDecoder::new(s);
msg.merge_text(&mut dec)
}
#[cfg(test)]
mod map_entry_tests {
use super::*;
#[test]
fn encode_map_entry() {
let mut s = String::new();
let mut enc = TextEncoder::new(&mut s);
enc.write_field_name("m").unwrap();
let k = 42i32;
let v = "hello";
enc.write_map_entry(|enc| {
enc.write_field_name("key")?;
enc.write_i32(k)?;
enc.write_field_name("value")?;
enc.write_string(v)?;
Ok(())
})
.unwrap();
assert_eq!(s, r#"m {key: 42 value: "hello"}"#);
}
#[test]
fn decode_map_entry() {
let mut dec = TextDecoder::new(r#"m { key: 42 value: "hello" }"#);
assert_eq!(dec.read_field_name().unwrap(), Some("m"));
let mut k: Option<i32> = None;
let mut v: Option<String> = None;
dec.merge_map_entry(|d| {
while let Some(n) = d.read_field_name()? {
match n {
"key" => k = Some(d.read_i32()?),
"value" => v = Some(d.read_string()?.into_owned()),
_ => d.skip_value()?,
}
}
Ok(())
})
.unwrap();
assert_eq!(k, Some(42));
assert_eq!(v.as_deref(), Some("hello"));
}
}