1use std::sync::Arc;
36
37use super::descriptor::{Cardinality, FieldDescriptor, Kind, MessageDescriptor};
38use super::dynamic::{is_field_value_default, DynamicMessage};
39use super::value::{MapKey, Value};
40
41#[derive(Debug)]
47pub enum TextError {
48 Parse(String),
50 Schema(String),
52}
53
54impl std::fmt::Display for TextError {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 match self {
57 TextError::Parse(s) => write!(f, "text format parse error: {s}"),
58 TextError::Schema(s) => write!(f, "schema error: {s}"),
59 }
60 }
61}
62
63impl std::error::Error for TextError {}
64
65impl From<TextError> for crate::ReflectError {
66 fn from(e: TextError) -> Self {
67 crate::ReflectError::Field(e.to_string())
68 }
69}
70
71impl DynamicMessage {
76 pub fn to_text(&self) -> Result<String, TextError> {
85 let mut out = String::new();
86 encode_message(self, &mut out, 0)?;
87 Ok(out)
88 }
89
90 pub fn from_text(desc: MessageDescriptor, text: &str) -> Result<Self, TextError> {
101 let mut parser = Parser::new(text);
102 parser.parse_message(desc)
103 }
104}
105
106const INDENT: &str = " ";
111
112fn encode_message(msg: &DynamicMessage, out: &mut String, depth: usize) -> Result<(), TextError> {
113 let desc = msg.descriptor();
114 let prefix = INDENT.repeat(depth);
115
116 for field in desc.fields() {
117 let value = msg.get_field(&field);
118 if is_field_value_default(&field, &value) {
119 continue;
120 }
121 encode_field_value(&field, &value, &prefix, out, depth)?;
122 }
123 Ok(())
124}
125
126fn encode_field_value(
127 field: &FieldDescriptor,
128 value: &Value,
129 prefix: &str,
130 out: &mut String,
131 depth: usize,
132) -> Result<(), TextError> {
133 if field.is_map() {
134 return encode_map_field(field, value, prefix, out, depth);
135 }
136 if matches!(field.cardinality(), Cardinality::Repeated) {
137 return encode_repeated_field(field, value, prefix, out, depth);
138 }
139 encode_singular_field(field, value, prefix, out, depth)
140}
141
142fn encode_repeated_field(
143 field: &FieldDescriptor,
144 value: &Value,
145 prefix: &str,
146 out: &mut String,
147 depth: usize,
148) -> Result<(), TextError> {
149 if let Value::List(items) = value {
150 for item in items {
151 encode_singular_field(field, item, prefix, out, depth)?;
152 }
153 Ok(())
154 } else {
155 Err(TextError::Schema(format!(
156 "expected list for repeated field '{}'",
157 field.name()
158 )))
159 }
160}
161
162fn encode_map_field(
163 field: &FieldDescriptor,
164 value: &Value,
165 prefix: &str,
166 out: &mut String,
167 depth: usize,
168) -> Result<(), TextError> {
169 let val_field = field.map_entry_value_field().ok_or_else(|| {
170 TextError::Schema(format!(
171 "map field '{}' missing value field descriptor",
172 field.name()
173 ))
174 })?;
175 let key_field = field.map_entry_key_field().ok_or_else(|| {
176 TextError::Schema(format!(
177 "map field '{}' missing key field descriptor",
178 field.name()
179 ))
180 })?;
181
182 if let Value::Map(entries) = value {
183 let mut sorted: Vec<_> = entries.iter().collect();
184 sorted.sort_by_key(|(k, _)| map_key_sort_key(k));
185 for (k, v) in sorted {
186 out.push_str(prefix);
188 out.push_str(field.name());
189 out.push_str(" {\n");
190 let inner_prefix = format!("{prefix}{INDENT}");
191 encode_singular_field(&key_field, &k.to_value(), &inner_prefix, out, depth + 1)?;
193 encode_singular_field(&val_field, v, &inner_prefix, out, depth + 1)?;
195 out.push_str(prefix);
196 out.push_str("}\n");
197 }
198 Ok(())
199 } else {
200 Err(TextError::Schema(format!(
201 "expected map for map field '{}'",
202 field.name()
203 )))
204 }
205}
206
207fn encode_singular_field(
208 field: &FieldDescriptor,
209 value: &Value,
210 prefix: &str,
211 out: &mut String,
212 depth: usize,
213) -> Result<(), TextError> {
214 match value {
215 Value::Message(m) => {
216 out.push_str(prefix);
217 out.push_str(field.name());
218 out.push_str(" {\n");
219 encode_message(m, out, depth + 1)?;
220 out.push_str(prefix);
221 out.push_str("}\n");
222 }
223 other => {
224 out.push_str(prefix);
225 out.push_str(field.name());
226 out.push_str(": ");
227 encode_scalar_value(other, field, out)?;
228 out.push('\n');
229 }
230 }
231 Ok(())
232}
233
234fn encode_scalar_value(
235 value: &Value,
236 field: &FieldDescriptor,
237 out: &mut String,
238) -> Result<(), TextError> {
239 match value {
240 Value::F64(v) => {
241 if v.is_nan() {
242 out.push_str("nan");
243 } else if *v == f64::INFINITY {
244 out.push_str("inf");
245 } else if *v == f64::NEG_INFINITY {
246 out.push_str("-inf");
247 } else {
248 out.push_str(&format!("{v}"));
249 }
250 }
251 Value::F32(v) => {
252 let v64 = f64::from(*v);
253 if v64.is_nan() {
254 out.push_str("nan");
255 } else if v64 == f64::INFINITY {
256 out.push_str("inf");
257 } else if v64 == f64::NEG_INFINITY {
258 out.push_str("-inf");
259 } else {
260 out.push_str(&format!("{v}"));
261 }
262 }
263 Value::I32(v) => out.push_str(&v.to_string()),
264 Value::I64(v) => out.push_str(&v.to_string()),
265 Value::U32(v) => out.push_str(&v.to_string()),
266 Value::U64(v) => out.push_str(&v.to_string()),
267 Value::Bool(v) => out.push_str(if *v { "true" } else { "false" }),
268 Value::String(s) => {
269 out.push('"');
270 for c in s.chars() {
271 match c {
272 '"' => out.push_str("\\\""),
273 '\\' => out.push_str("\\\\"),
274 '\n' => out.push_str("\\n"),
275 '\r' => out.push_str("\\r"),
276 '\t' => out.push_str("\\t"),
277 '\0' => out.push_str("\\0"),
278 other => out.push(other),
279 }
280 }
281 out.push('"');
282 }
283 Value::Bytes(b) => {
284 out.push('"');
285 for byte in b {
286 out.push_str(&format!("\\x{byte:02x}"));
287 }
288 out.push('"');
289 }
290 Value::EnumNumber(n) => {
291 if let Some(enum_desc) = field.enum_type() {
293 if let Some(val_desc) = enum_desc.get_value(*n) {
294 out.push_str(val_desc.name());
295 return Ok(());
296 }
297 }
298 out.push_str(&n.to_string());
299 }
300 Value::Message(_) | Value::List(_) | Value::Map(_) => {
301 return Err(TextError::Schema(
302 "unexpected nested structure in scalar context".to_owned(),
303 ));
304 }
305 }
306 Ok(())
307}
308
309fn map_key_sort_key(k: &MapKey) -> String {
310 match k {
311 MapKey::String(s) => format!("s{s}"),
312 MapKey::I32(v) => format!("n{:020}", v),
313 MapKey::I64(v) => format!("n{:020}", v),
314 MapKey::U32(v) => format!("n{:020}", v),
315 MapKey::U64(v) => format!("n{:020}", v),
316 MapKey::Bool(v) => format!("b{}", if *v { 1 } else { 0 }),
317 }
318}
319
320struct Parser<'a> {
325 input: &'a str,
326 pos: usize,
327}
328
329impl<'a> Parser<'a> {
330 fn new(input: &'a str) -> Self {
331 Self { input, pos: 0 }
332 }
333
334 fn is_empty(&self) -> bool {
335 self.pos >= self.input.len()
336 }
337
338 fn skip_ws(&mut self) {
340 loop {
341 while self.pos < self.input.len()
342 && matches!(
343 self.input.as_bytes()[self.pos],
344 b' ' | b'\t' | b'\n' | b'\r'
345 )
346 {
347 self.pos += 1;
348 }
349 if self.pos < self.input.len() && self.input.as_bytes()[self.pos] == b'#' {
351 while self.pos < self.input.len() && self.input.as_bytes()[self.pos] != b'\n' {
352 self.pos += 1;
353 }
354 } else {
355 break;
356 }
357 }
358 }
359
360 fn peek(&mut self) -> Option<u8> {
362 self.skip_ws();
363 self.input.as_bytes().get(self.pos).copied()
364 }
365
366 fn expect(&mut self, ch: char) -> Result<(), TextError> {
368 self.skip_ws();
369 let bytes = self.input.as_bytes();
370 if self.pos < bytes.len() && bytes[self.pos] == ch as u8 {
371 self.pos += 1;
372 Ok(())
373 } else {
374 let got = if self.pos < bytes.len() {
375 format!("'{}'", bytes[self.pos] as char)
376 } else {
377 "EOF".to_owned()
378 };
379 Err(TextError::Parse(format!("expected '{ch}', got {got}")))
380 }
381 }
382
383 fn read_token(&mut self) -> Result<String, TextError> {
386 self.skip_ws();
387 let start = self.pos;
388 while self.pos < self.input.len() {
389 match self.input.as_bytes()[self.pos] {
390 b' ' | b'\t' | b'\n' | b'\r' | b':' | b'{' | b'}' | b';' | b',' => break,
391 _ => self.pos += 1,
392 }
393 }
394 if self.pos == start {
395 return Err(TextError::Parse("expected token, got empty".to_owned()));
396 }
397 Ok(self.input[start..self.pos].to_owned())
398 }
399
400 fn read_string(&mut self) -> Result<String, TextError> {
403 let bytes = self.read_string_as_bytes()?;
404 String::from_utf8(bytes)
405 .map_err(|e| TextError::Parse(format!("string field contains invalid UTF-8: {e}")))
406 }
407
408 fn read_string_as_bytes(&mut self) -> Result<Vec<u8>, TextError> {
412 self.expect('"')?;
413 let mut out: Vec<u8> = Vec::new();
414 loop {
415 if self.pos >= self.input.len() {
416 return Err(TextError::Parse("unterminated string literal".to_owned()));
417 }
418 let b = self.input.as_bytes()[self.pos];
419 self.pos += 1;
420 match b {
421 b'"' => break,
422 b'\\' => {
423 if self.pos >= self.input.len() {
424 return Err(TextError::Parse("unterminated escape".to_owned()));
425 }
426 let esc = self.input.as_bytes()[self.pos];
427 self.pos += 1;
428 match esc {
429 b'n' => out.push(b'\n'),
430 b'r' => out.push(b'\r'),
431 b't' => out.push(b'\t'),
432 b'\\' => out.push(b'\\'),
433 b'"' => out.push(b'"'),
434 b'0' => out.push(0),
435 b'x' | b'X' => {
436 let h1 = self.read_hex_digit()?;
438 let h2 = self.read_hex_digit()?;
439 out.push(h1 * 16 + h2);
440 }
441 other => {
442 out.push(b'\\');
443 out.push(other);
444 }
445 }
446 }
447 other => out.push(other),
448 }
449 }
450 Ok(out)
451 }
452
453 fn read_hex_digit(&mut self) -> Result<u8, TextError> {
454 if self.pos >= self.input.len() {
455 return Err(TextError::Parse("unexpected EOF in hex escape".to_owned()));
456 }
457 let b = self.input.as_bytes()[self.pos];
458 self.pos += 1;
459 match b {
460 b'0'..=b'9' => Ok(b - b'0'),
461 b'a'..=b'f' => Ok(b - b'a' + 10),
462 b'A'..=b'F' => Ok(b - b'A' + 10),
463 other => Err(TextError::Parse(format!(
464 "invalid hex digit: '{}'",
465 other as char
466 ))),
467 }
468 }
469
470 fn parse_message(&mut self, desc: MessageDescriptor) -> Result<DynamicMessage, TextError> {
471 let mut msg = DynamicMessage::new(desc.clone());
472 loop {
473 self.skip_ws();
474 if self.is_empty() {
475 break;
476 }
477 if self.peek() == Some(b'}') {
479 break;
480 }
481
482 let field_name = self.read_token()?;
484 self.skip_ws();
485
486 let field = desc
488 .get_field_by_name(&field_name)
489 .or_else(|| desc.get_field_by_json_name(&field_name));
490
491 let field = match field {
492 Some(f) => f,
493 None => {
494 self.skip_field_value()?;
496 if self.peek() == Some(b';') {
498 self.pos += 1;
499 }
500 continue;
501 }
502 };
503
504 let value =
506 if matches!(field.kind(), Kind::Message(_) | Kind::Group(_)) || field.is_map() {
507 self.skip_ws();
509 if self.peek() == Some(b':') {
510 self.pos += 1; self.skip_ws();
512 }
513 if self.peek() == Some(b'<') {
514 self.parse_angle_message(field.clone())?
516 } else {
517 self.parse_brace_message(field.clone())?
518 }
519 } else {
520 self.expect(':')?;
521 self.parse_scalar_value(&field)?
522 };
523
524 if matches!(field.cardinality(), Cardinality::Repeated) && !field.is_map() {
526 let existing = msg
528 .fields
529 .entry(field.number())
530 .or_insert(Value::List(Vec::new()));
531 if let Value::List(list) = existing {
532 list.push(value);
533 }
534 } else if field.is_map() {
535 match value {
538 Value::Map(new_entries) => {
539 let existing = msg
540 .fields
541 .entry(field.number())
542 .or_insert(Value::Map(std::collections::HashMap::new()));
543 if let Value::Map(map) = existing {
544 map.extend(new_entries);
545 }
546 }
547 other => {
548 return Err(TextError::Schema(format!(
549 "expected map for map field '{}', got {:?}",
550 field.name(),
551 other
552 )));
553 }
554 }
555 } else {
556 msg.set_field(&field, value);
557 }
558
559 self.skip_ws();
561 if matches!(self.peek(), Some(b';') | Some(b',')) {
562 self.pos += 1;
563 }
564 }
565 Ok(msg)
566 }
567
568 fn parse_brace_message(&mut self, field: FieldDescriptor) -> Result<Value, TextError> {
570 if field.is_map() {
571 return self.parse_map_entry(field);
572 }
573 if let Kind::Message(msg_index) = field.kind() {
574 self.expect('{')?;
575 let msg_desc = MessageDescriptor {
576 pool: Arc::clone(&field.pool),
577 index: msg_index,
578 };
579 let nested = self.parse_message(msg_desc)?;
580 self.expect('}')?;
581 Ok(Value::Message(Box::new(nested)))
582 } else {
583 Err(TextError::Schema(format!(
584 "field '{}' is not a message kind",
585 field.name()
586 )))
587 }
588 }
589
590 fn parse_angle_message(&mut self, field: FieldDescriptor) -> Result<Value, TextError> {
592 if let Kind::Message(msg_index) = field.kind() {
593 self.expect('<')?;
594 let msg_desc = MessageDescriptor {
595 pool: Arc::clone(&field.pool),
596 index: msg_index,
597 };
598 let nested = self.parse_message(msg_desc)?;
599 self.expect('>')?;
600 Ok(Value::Message(Box::new(nested)))
601 } else {
602 Err(TextError::Schema(format!(
603 "field '{}' is not a message kind",
604 field.name()
605 )))
606 }
607 }
608
609 fn parse_map_entry(&mut self, field: FieldDescriptor) -> Result<Value, TextError> {
612 let key_field = field.map_entry_key_field().ok_or_else(|| {
613 TextError::Schema(format!(
614 "map field '{}' missing key descriptor",
615 field.name()
616 ))
617 })?;
618 let val_field = field.map_entry_value_field().ok_or_else(|| {
619 TextError::Schema(format!(
620 "map field '{}' missing value descriptor",
621 field.name()
622 ))
623 })?;
624
625 self.expect('{')?;
626
627 let mut key_val: Option<Value> = None;
628 let mut entry_val: Option<Value> = None;
629
630 loop {
631 self.skip_ws();
632 if self.peek() == Some(b'}') {
633 break;
634 }
635 let fname = self.read_token()?;
636 match fname.as_str() {
637 "key" => {
638 self.expect(':')?;
639 key_val = Some(self.parse_scalar_value(&key_field)?);
640 }
641 "value" => {
642 let v = if matches!(val_field.kind(), Kind::Message(_)) {
643 self.skip_ws();
644 if self.peek() == Some(b':') {
645 self.pos += 1;
646 self.skip_ws();
647 }
648 self.parse_brace_message(val_field.clone())?
649 } else {
650 self.expect(':')?;
651 self.parse_scalar_value(&val_field)?
652 };
653 entry_val = Some(v);
654 }
655 _ => {
656 self.skip_field_value()?;
657 }
658 }
659 self.skip_ws();
660 if matches!(self.peek(), Some(b';') | Some(b',')) {
661 self.pos += 1;
662 }
663 }
664
665 self.expect('}')?;
666
667 let key = key_val.ok_or_else(|| {
668 TextError::Parse(format!("map entry for '{}' missing 'key'", field.name()))
669 })?;
670 let val = entry_val.ok_or_else(|| {
671 TextError::Parse(format!("map entry for '{}' missing 'value'", field.name()))
672 })?;
673
674 let map_key = value_to_map_key(key)?;
675 let mut map = std::collections::HashMap::new();
676 map.insert(map_key, val);
677 Ok(Value::Map(map))
678 }
679
680 fn parse_scalar_value(&mut self, field: &FieldDescriptor) -> Result<Value, TextError> {
682 self.skip_ws();
683 let next = self
684 .peek()
685 .ok_or_else(|| TextError::Parse("unexpected EOF".to_owned()))?;
686
687 if next == b'"' {
688 return match field.kind() {
691 Kind::Bytes => {
692 let raw = self.read_string_as_bytes()?;
693 Ok(Value::Bytes(raw))
694 }
695 _ => {
696 let s = self.read_string()?;
697 parse_string_for_kind(s, field)
698 }
699 };
700 }
701
702 let token = self.read_token()?;
704 parse_token_for_field(&token, field)
705 }
706
707 fn skip_field_value(&mut self) -> Result<(), TextError> {
710 self.skip_ws();
711 let next = self.peek();
712 match next {
713 Some(b':') => {
714 self.pos += 1;
715 self.skip_ws();
716 if self.peek() == Some(b'"') {
717 let _ = self.read_string()?;
718 } else if self.peek() == Some(b'{') {
719 self.skip_block()?;
720 } else {
721 let _ = self.read_token()?;
722 }
723 }
724 Some(b'{') => {
725 self.skip_block()?;
726 }
727 _ => {
728 let _ = self.read_token()?;
729 }
730 }
731 Ok(())
732 }
733
734 fn skip_block(&mut self) -> Result<(), TextError> {
736 self.expect('{')?;
737 let mut depth = 1usize;
738 while self.pos < self.input.len() && depth > 0 {
739 match self.input.as_bytes()[self.pos] {
740 b'{' => {
741 depth += 1;
742 self.pos += 1;
743 }
744 b'}' => {
745 depth -= 1;
746 self.pos += 1;
747 }
748 b'"' => {
749 self.pos += 1;
751 while self.pos < self.input.len() {
752 match self.input.as_bytes()[self.pos] {
753 b'"' => {
754 self.pos += 1;
755 break;
756 }
757 b'\\' => {
758 self.pos += 2; }
760 _ => {
761 self.pos += 1;
762 }
763 }
764 }
765 }
766 _ => {
767 self.pos += 1;
768 }
769 }
770 }
771 if depth != 0 {
772 return Err(TextError::Parse("unmatched '{' in text format".to_owned()));
773 }
774 Ok(())
775 }
776}
777
778fn parse_string_for_kind(s: String, field: &FieldDescriptor) -> Result<Value, TextError> {
783 match field.kind() {
784 Kind::String => Ok(Value::String(s)),
785 Kind::Bytes => {
786 Ok(Value::Bytes(s.into_bytes()))
788 }
789 other => Err(TextError::Schema(format!(
790 "field '{}' has kind {:?} but got a quoted string",
791 field.name(),
792 other
793 ))),
794 }
795}
796
797fn parse_token_for_field(token: &str, field: &FieldDescriptor) -> Result<Value, TextError> {
798 match field.kind() {
799 Kind::Bool => parse_bool(token),
800 Kind::Double => parse_f64(token).map(Value::F64),
801 Kind::Float => parse_f32(token).map(Value::F32),
802 Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => token
803 .parse::<i32>()
804 .map(Value::I32)
805 .map_err(|_| TextError::Parse(format!("invalid i32: {token}"))),
806 Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => token
807 .parse::<i64>()
808 .map(Value::I64)
809 .map_err(|_| TextError::Parse(format!("invalid i64: {token}"))),
810 Kind::Uint32 | Kind::Fixed32 => token
811 .parse::<u32>()
812 .map(Value::U32)
813 .map_err(|_| TextError::Parse(format!("invalid u32: {token}"))),
814 Kind::Uint64 | Kind::Fixed64 => token
815 .parse::<u64>()
816 .map(Value::U64)
817 .map_err(|_| TextError::Parse(format!("invalid u64: {token}"))),
818 Kind::String => Ok(Value::String(token.to_owned())),
819 Kind::Bytes => Ok(Value::Bytes(token.as_bytes().to_vec())),
820 Kind::Enum(_) => {
821 if let Some(enum_desc) = field.enum_type() {
823 if let Some(val_desc) = enum_desc.get_value_by_name(token) {
824 return Ok(Value::EnumNumber(val_desc.number()));
825 }
826 }
827 token.parse::<i32>().map(Value::EnumNumber).map_err(|_| {
829 TextError::Parse(format!(
830 "unknown enum value for '{}': {token}",
831 field.name()
832 ))
833 })
834 }
835 Kind::Message(_) | Kind::Group(_) => Err(TextError::Parse(format!(
836 "field '{}' is a message kind; expected '{{' delimiter, got bare token '{token}'",
837 field.name()
838 ))),
839 }
840}
841
842fn parse_bool(token: &str) -> Result<Value, TextError> {
843 match token {
844 "true" | "True" | "1" => Ok(Value::Bool(true)),
845 "false" | "False" | "0" => Ok(Value::Bool(false)),
846 other => Err(TextError::Parse(format!("invalid bool: {other}"))),
847 }
848}
849
850fn parse_f64(token: &str) -> Result<f64, TextError> {
851 match token {
852 "nan" | "NaN" => Ok(f64::NAN),
853 "inf" | "Inf" | "infinity" | "Infinity" => Ok(f64::INFINITY),
854 "-inf" | "-Inf" | "-infinity" | "-Infinity" => Ok(f64::NEG_INFINITY),
855 other => other
856 .parse::<f64>()
857 .map_err(|_| TextError::Parse(format!("invalid f64: {other}"))),
858 }
859}
860
861fn parse_f32(token: &str) -> Result<f32, TextError> {
862 match token {
863 "nan" | "NaN" => Ok(f32::NAN),
864 "inf" | "Inf" | "infinity" | "Infinity" => Ok(f32::INFINITY),
865 "-inf" | "-Inf" | "-infinity" | "-Infinity" => Ok(f32::NEG_INFINITY),
866 other => other
867 .parse::<f32>()
868 .map_err(|_| TextError::Parse(format!("invalid f32: {other}"))),
869 }
870}
871
872fn value_to_map_key(v: Value) -> Result<MapKey, TextError> {
873 match v {
874 Value::String(s) => Ok(MapKey::String(s)),
875 Value::I32(n) => Ok(MapKey::I32(n)),
876 Value::I64(n) => Ok(MapKey::I64(n)),
877 Value::U32(n) => Ok(MapKey::U32(n)),
878 Value::U64(n) => Ok(MapKey::U64(n)),
879 Value::Bool(b) => Ok(MapKey::Bool(b)),
880 other => Err(TextError::Schema(format!(
881 "invalid map key type: {other:?}"
882 ))),
883 }
884}