rustledger_core/format/
helpers.rs1use super::format_amount;
4use crate::MetaValue;
5
6pub fn format_meta_value(value: &MetaValue) -> String {
8 match value {
9 MetaValue::String(s) => format!("\"{}\"", escape_string(s)),
10 MetaValue::Account(a) => a.to_string(),
11 MetaValue::Currency(c) => c.to_string(),
12 MetaValue::Tag(t) => format!("#{t}"),
13 MetaValue::Link(l) => format!("^{l}"),
14 MetaValue::Date(d) => d.to_string(),
15 MetaValue::Number(n) => n.to_string(),
16 MetaValue::Amount(a) => format_amount(a),
17 MetaValue::Bool(b) => if *b { "TRUE" } else { "FALSE" }.to_string(),
18 MetaValue::None => String::new(),
19 MetaValue::Int(i) => i.to_string(),
20 }
21}
22
23#[must_use]
34pub fn escape_csv(s: &str) -> String {
35 if s.contains(',') || s.contains('"') || s.contains('\n') {
36 format!("\"{}\"", s.replace('"', "\"\""))
37 } else {
38 s.to_string()
39 }
40}
41
42pub fn escape_string(s: &str) -> String {
44 let mut out = String::with_capacity(s.len());
45 for c in s.chars() {
46 match c {
47 '"' => out.push_str("\\\""),
48 '\\' => out.push_str("\\\\"),
49 '\n' => out.push_str("\\n"),
50 '\t' => out.push_str("\\t"),
54 '\r' => out.push_str("\\r"),
55 _ => out.push(c),
56 }
57 }
58 out
59}
60
61#[cfg(test)]
62mod tests {
63 use super::escape_string;
64
65 #[test]
66 fn escapes_quote_backslash_and_controls() {
67 assert_eq!(escape_string("a\"b"), "a\\\"b");
68 assert_eq!(escape_string("a\\b"), "a\\\\b");
69 assert_eq!(escape_string("a\nb"), "a\\nb");
70 assert_eq!(escape_string("a\tb"), "a\\tb");
73 assert_eq!(escape_string("a\rb"), "a\\rb");
74 }
75
76 #[test]
77 fn leaves_plain_text_untouched() {
78 assert_eq!(escape_string("plain text 123"), "plain text 123");
79 }
80}