use crate::{ENCODED_BACKSLASH, ENCODED_TILDE, PATH_SEPARATOR, TILDE};
#[derive(Debug, Clone)]
pub struct JsonPath(pub Vec<String>);
impl JsonPath {
pub(crate) fn new() -> Self {
JsonPath(Vec::new())
}
pub(crate) fn add(&mut self, segment: &str) -> &mut Self {
if segment.contains(TILDE) || segment.contains(PATH_SEPARATOR) {
let segment = segment
.replace(TILDE, ENCODED_TILDE)
.replace(PATH_SEPARATOR, ENCODED_BACKSLASH);
self.0.push(segment);
} else {
self.0.push(segment.to_owned());
}
self
}
pub(crate) fn format_path(&self) -> String {
self.0.join(PATH_SEPARATOR)
}
}
#[cfg(test)]
mod test {
use crate::types::json_path::JsonPath;
use crate::{ENCODED_BACKSLASH, ENCODED_TILDE, PATH_SEPARATOR};
#[test]
fn test_new_json_path() {
let path = JsonPath::new();
assert_eq!(path.0.len(), 0);
assert_eq!(path.format_path(), "");
}
#[test]
fn test_add_simple_segment() {
let mut path = JsonPath::new();
path.add("simple");
assert_eq!(path.0.len(), 1);
assert_eq!(path.0[0], "simple");
assert_eq!(path.format_path(), "simple");
}
#[test]
fn test_add_multiple_segments() {
let mut path = JsonPath::new();
path.add("component").add("schemas").add("User");
assert_eq!(path.0.len(), 3);
assert_eq!(path.0[0], "component");
assert_eq!(path.0[1], "schemas");
assert_eq!(path.0[2], "User");
assert_eq!(path.format_path(), "component/schemas/User");
}
#[test]
fn test_add_segment_with_tilde() {
let mut path = JsonPath::new();
path.add("user~name");
assert_eq!(path.0.len(), 1);
assert_eq!(path.0[0], format!("user{}name", ENCODED_TILDE));
let formatted = path.format_path();
assert_eq!(formatted, format!("user{}name", ENCODED_TILDE));
}
#[test]
fn test_add_segment_with_slash() {
let mut path = JsonPath::new();
path.add("user/profile");
assert_eq!(path.0.len(), 1);
assert_eq!(path.0[0], format!("user{}profile", ENCODED_BACKSLASH));
let formatted = path.format_path();
assert_eq!(formatted, format!("user{}profile", ENCODED_BACKSLASH));
assert!(!formatted.contains("/"));
}
#[test]
fn test_add_segment_with_tilde_and_slash() {
let mut path = JsonPath::new();
path.add("user~/profile");
assert_eq!(path.0.len(), 1);
let expected = "user".to_string() + ENCODED_TILDE + ENCODED_BACKSLASH + "profile";
assert_eq!(path.0[0], expected);
let formatted = path.format_path();
assert_eq!(formatted, expected);
}
#[test]
fn test_format_path_empty() {
let path = JsonPath::new();
assert_eq!(path.format_path(), "");
}
#[test]
fn test_format_path_single_segment() {
let mut path = JsonPath::new();
path.add("test");
assert_eq!(path.format_path(), "test");
}
#[test]
fn test_format_path_complex() {
let mut path = JsonPath::new();
path.add("paths")
.add("/users/{id}")
.add("get")
.add("responses")
.add("200");
let expected_second = format!("{}users{}{{id}}", ENCODED_BACKSLASH, ENCODED_BACKSLASH);
assert_eq!(path.0[1], expected_second);
let expected_path = format!(
"paths{}{}{}{}{}{}{}{}",
PATH_SEPARATOR,
expected_second,
PATH_SEPARATOR,
"get",
PATH_SEPARATOR,
"responses",
PATH_SEPARATOR,
"200"
);
assert_eq!(path.format_path(), expected_path);
}
#[test]
fn test_chained_add_operations() {
let mut path = JsonPath::new();
let result = path.add("first").add("second").add("third");
assert_eq!(result.0.len(), 3);
assert_eq!(path.0.len(), 3);
assert_eq!(path.format_path(), "first/second/third");
}
#[test]
fn test_add_empty_segment() {
let mut path = JsonPath::new();
path.add("");
assert_eq!(path.0.len(), 1);
assert_eq!(path.0[0], "");
assert_eq!(path.format_path(), "");
}
#[test]
fn test_json_pointer_compatibility() {
let mut path = JsonPath::new();
path.add("components").add("schemas").add("Error");
assert_eq!(path.format_path(), "components/schemas/Error");
let mut path = JsonPath::new();
path.add("paths")
.add("/pets")
.add("get")
.add("parameters")
.add("0");
let expected_second = format!("{}pets", ENCODED_BACKSLASH);
assert_eq!(path.0[1], expected_second);
let expected_path = format!(
"paths{}{}{}{}{}{}{}{}",
PATH_SEPARATOR,
expected_second,
PATH_SEPARATOR,
"get",
PATH_SEPARATOR,
"parameters",
PATH_SEPARATOR,
"0"
);
assert_eq!(path.format_path(), expected_path);
}
#[test]
fn test_special_characters_encoding() {
let mut path = JsonPath::new();
path.add("a~b/c");
path.add("d/e~f");
path.add("~~/~~");
path.add("//");
assert_eq!(path.0.len(), 4);
assert_eq!(
path.0[0],
format!("a{}b{}c", ENCODED_TILDE, ENCODED_BACKSLASH)
);
assert_eq!(
path.0[1],
format!("d{}e{}f", ENCODED_BACKSLASH, ENCODED_TILDE)
);
assert_eq!(
path.0[2],
format!("{0}{0}{1}{0}{0}", ENCODED_TILDE, ENCODED_BACKSLASH)
);
assert_eq!(path.0[3], format!("{0}{0}", ENCODED_BACKSLASH));
let expected_path = [
format!("a{}b{}c", ENCODED_TILDE, ENCODED_BACKSLASH),
format!("d{}e{}f", ENCODED_BACKSLASH, ENCODED_TILDE),
format!("{0}{0}{1}{0}{0}", ENCODED_TILDE, ENCODED_BACKSLASH),
format!("{0}{0}", ENCODED_BACKSLASH),
]
.join(PATH_SEPARATOR);
assert_eq!(path.format_path(), expected_path);
}
#[test]
fn test_numeric_segments() {
let mut path = JsonPath::new();
path.add("items").add("0").add("name");
assert_eq!(path.0.len(), 3);
assert_eq!(path.0[0], "items");
assert_eq!(path.0[1], "0");
assert_eq!(path.0[2], "name");
assert_eq!(path.format_path(), "items/0/name");
}
#[test]
fn test_modify_existing_path() {
let mut path = JsonPath::new();
path.add("components").add("schemas");
assert_eq!(path.format_path(), "components/schemas");
path.add("User").add("properties").add("email");
assert_eq!(path.0.len(), 5);
assert_eq!(
path.format_path(),
"components/schemas/User/properties/email"
);
}
}