Lines
90.91 %
Functions
100 %
Branches
/*
* Hurl (https://hurl.dev)
* Copyright (C) 2024 Orange
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Serde-json can not be easily used for serialization here because of the orphan rule.
* It seems easier just to reimplement it from scratch (around 50 lines of code)
#[allow(dead_code)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum JValue {
Number(String),
String(String),
Boolean(bool),
List(Vec<JValue>),
Object(Vec<(String, JValue)>),
Null,
}
impl JValue {
pub fn format(&self) -> String {
match self {
JValue::Null => "null".to_string(),
JValue::Number(n) => n.to_string(),
JValue::String(s) => format!("\"{}\"", s.chars().map(format_char).collect::<String>()),
JValue::Boolean(b) => b.to_string(),
JValue::List(elem) => {
let s = elem
.iter()
.map(|e| e.format())
.collect::<Vec<String>>()
.join(",");
format!("[{s}]")
JValue::Object(key_values) => {
let s = key_values
.map(|(k, v)| {
format!(
"\"{}\":{}",
k.chars().map(format_char).collect::<String>(),
v.format()
)
})
format!("{{{s}}}")
fn format_char(c: char) -> String {
if c == '"' {
"\\\"".to_string()
} else if c == '\\' {
"\\\\".to_string()
} else if c == '\x08' {
"\\b".to_string()
} else if c == '\x0c' {
"\\f".to_string()
} else if c == '\n' {
"\\n".to_string()
} else if c == '\r' {
"\\r".to_string()
} else if c == '\t' {
"\\t".to_string()
} else if c.is_control() {
format!("\\u{:04x}", c as u32)
} else {
c.to_string()
#[cfg(test)]
pub mod tests {
use super::*;
#[test]
pub fn test_format_char() {
assert_eq!(format_char('a'), "a");
assert_eq!(format_char('"'), "\\\""); // \"
assert_eq!(format_char('\n'), "\\n");
assert_eq!(format_char('\x07'), "\\u0007");
pub fn format_scalars() {
assert_eq!(JValue::Null.format(), "null");
assert_eq!(JValue::Number("1.0".to_string()).format(), "1.0");
assert_eq!(JValue::String("hello".to_string()).format(), "\"hello\"");
assert_eq!(JValue::Boolean(true).format(), "true");
pub fn format_string() {
assert_eq!(JValue::String("\"".to_string()).format(), r#""\"""#);
pub fn format_list() {
assert_eq!(
JValue::List(vec![
JValue::Number("1".to_string()),
JValue::Number("2".to_string()),
JValue::Number("3".to_string())
])
.format(),
"[1,2,3]"
);
pub fn test_format_special_characters() {
let value = JValue::Object(vec![(
"sp\"ecial\\key".to_string(),
JValue::String("sp\nvalue\twith\x08control".to_string()),
)]);
value.format(),
r#"{"sp\"ecial\\key":"sp\nvalue\twith\bcontrol"}"#
pub fn format_object() {
JValue::Object(vec![
("name".to_string(), JValue::String("Bob".to_string())),
("age".to_string(), JValue::Number("20".to_string())),
r#"{"name":"Bob","age":20}"#