1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use super::*;
impl Ctxt<'_, '_, '_> {
pub(super) fn value_to_string(val: &Value) -> Option<String> {
let escape_char = |val: char| match val {
'\t' => "\\t".to_string(),
'\r' => "\\r".to_string(),
'\n' => "\\n".to_string(),
'\\' => "\\\\".to_string(),
val => val.to_string(),
};
let escape_string = |val: &str| {
let val: String = val
.chars()
.map(escape_char)
.flat_map(|str| str.chars().collect::<Vec<_>>())
.collect();
format!(r#""{}""#, val)
};
match val {
Value::Bool(val) => Some(val.to_string()),
Value::Char(val) => Some(escape_char(*val)),
Value::F32(val) => Some(val.to_string()),
Value::F64(val) => Some(val.to_string()),
Value::U8(val) => Some(val.to_string()),
Value::I8(val) => Some(val.to_string()),
Value::U16(val) => Some(val.to_string()),
Value::I16(val) => Some(val.to_string()),
Value::U32(val) => Some(val.to_string()),
Value::I32(val) => Some(val.to_string()),
Value::U64(val) => Some(val.to_string()),
Value::I64(val) => Some(val.to_string()),
Value::U128(val) => Some(val.to_string()),
Value::I128(val) => Some(val.to_string()),
Value::Usize(val) => Some(val.to_string()),
Value::Isize(val) => Some(val.to_string()),
Value::String(val) => Some(escape_string(val)),
Value::Array(_) => None,
Value::Map(_) => None,
Value::None => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use test_case::test_case;
#[test_case(Value::Bool(false) => Some("false".to_string()) ; "bool, false")]
#[test_case(Value::Bool(true) => Some("true".to_string()) ; "bool, true")]
#[test_case(Value::Char('\t') => Some("\\t".to_string()) ; "char, \\t")]
#[test_case(Value::Char('\r') => Some("\\r".to_string()) ; "char, \\r")]
#[test_case(Value::Char('\n') => Some("\\n".to_string()) ; "char, \\n")]
#[test_case(Value::Char('\\') => Some("\\\\".to_string()) ; "char, \\")]
#[test_case(Value::Char('a') => Some("a".to_string()) ; "char, a")]
#[test_case(Value::F32(1.23) => Some("1.23".to_string()) ; "f32")]
#[test_case(Value::F64(1.23) => Some("1.23".to_string()) ; "f64")]
#[test_case(Value::U8(123) => Some("123".to_string()) ; "u8")]
#[test_case(Value::I8(123) => Some("123".to_string()) ; "i8")]
#[test_case(Value::U16(123) => Some("123".to_string()) ; "u16")]
#[test_case(Value::I16(123) => Some("123".to_string()) ; "i16")]
#[test_case(Value::U32(123) => Some("123".to_string()) ; "u32")]
#[test_case(Value::I32(123) => Some("123".to_string()) ; "i32")]
#[test_case(Value::U64(123) => Some("123".to_string()) ; "u64")]
#[test_case(Value::I64(123) => Some("123".to_string()) ; "i64")]
#[test_case(Value::U128(123) => Some("123".to_string()) ; "u128")]
#[test_case(Value::I128(123) => Some("123".to_string()) ; "i128")]
#[test_case(Value::Usize(123) => Some("123".to_string()) ; "usize")]
#[test_case(Value::Isize(123) => Some("123".to_string()) ; "isize")]
#[test_case(Value::String("Hello \n World!".to_string()) => Some("\"Hello \\n World!\"".to_string()) ; "string")]
#[test_case(Value::Array(Default::default()) => None ; "array")]
#[test_case(Value::Map(Default::default()) => None ; "map")]
#[test_case(Value::None => None ; "none")]
fn returns(val: Value) -> Option<String> {
Ctxt::value_to_string(&val)
}
}