use serde_json::Value;
mod utils;
use utils::format_value;
#[derive(Debug, Clone, Default)]
pub struct LLMLOptions {
pub indent: String,
pub prefix: String,
pub strict: bool,
}
pub fn llml(data: &Value) -> String {
format_value(data, &LLMLOptions::default())
}
pub fn llml_with_options(data: &Value, options: Option<LLMLOptions>) -> String {
let opts = options.unwrap_or_default();
format_value(data, &opts)
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_empty_values() {
assert_eq!(llml(&json!({})), "");
assert_eq!(llml(&json!([])), "");
assert_eq!(llml(&Value::Null), "null");
}
#[test]
fn test_simple_values() {
let result = llml(&json!({"instructions": "Follow these steps"}));
assert_eq!(result, "<instructions>Follow these steps</instructions>");
let result = llml(&json!({"count": 42}));
assert_eq!(result, "<count>42</count>");
let result = llml(&json!({"enabled": true}));
assert_eq!(result, "<enabled>true</enabled>");
}
#[test]
fn test_list_formatting() {
let result = llml(&json!({"rules": ["first", "second", "third"]}));
let expected = "<rules>\n <rules-1>first</rules-1>\n <rules-2>second</rules-2>\n <rules-3>third</rules-3>\n</rules>";
assert_eq!(result, expected);
}
#[test]
fn test_nested_objects() {
let result = llml(&json!({
"config": {
"debug": true,
"timeout": 30
}
}));
assert!(result.contains("<config>"));
assert!(result.contains("</config>"));
assert!(result.contains("<debug>true</debug>"));
assert!(result.contains("<timeout>30</timeout>"));
}
#[test]
fn test_optional_second_argument() {
let data = json!({"instructions": "Follow these steps"});
let result1 = llml(&data);
assert_eq!(result1, "<instructions>Follow these steps</instructions>");
let options = Some(LLMLOptions {
indent: " ".to_string(),
prefix: String::new(),
strict: false,
});
let result2 = llml_with_options(&data, options);
assert_eq!(result2, " <instructions>Follow these steps</instructions>");
let result3 = llml_with_options(&data, None);
assert_eq!(result3, "<instructions>Follow these steps</instructions>");
assert_eq!(result1, result3);
}
#[test]
fn test_with_LLMLOptions_function() {
let data = json!({"test": "value"});
let options = LLMLOptions {
indent: " ".to_string(),
prefix: String::new(),
strict: false,
};
let result = llml_with_options(&data, Some(options));
assert_eq!(result, " <test>value</test>");
let options = LLMLOptions {
indent: String::new(),
prefix: "app".to_string(),
strict: false,
};
let result = llml_with_options(&data, Some(options));
assert_eq!(result, "<app-test>value</app-test>");
}
#[test]
fn test_insertion_order_preservation() {
let result = llml(&json!({
"first": "1st",
"second": "2nd",
"third": "3rd"
}));
let expected = "<first>1st</first>\n<second>2nd</second>\n<third>3rd</third>";
assert_eq!(result, expected);
}
#[test]
fn test_deterministic_output() {
let data = json!({
"alpha": "value1",
"beta": "value2",
"gamma": "value3",
"delta": "value4"
});
let result1 = llml(&data);
let result2 = llml(&data);
let result3 = llml(&data);
assert_eq!(result1, result2);
assert_eq!(result2, result3);
let expected = "<alpha>value1</alpha>\n<beta>value2</beta>\n<delta>value4</delta>\n<gamma>value3</gamma>";
assert_eq!(result1, expected);
}
}