use serde::de::Deserialize;
use crate::{Result, Statement, Value};
pub(crate) mod error;
mod statement;
mod value;
pub use statement::*;
pub use value::*;
pub fn from_statement<T>(statement: &Statement) -> Result<T>
where
T: for<'de> Deserialize<'de>,
{
let deserializer = StatementDeserializer::new(statement);
let result = T::deserialize(deserializer)?;
Ok(result)
}
pub fn from_value<T>(value: &Value) -> Result<T>
where
T: for<'de> Deserialize<'de>,
{
let deserializer = ValueDeserializer::new(value);
let result = T::deserialize(deserializer)?;
Ok(result)
}
#[cfg(test)]
mod tests {
use indexmap::IndexMap;
use serde::Deserialize;
use super::*;
use crate::{Location, Metadata, from_str};
#[derive(Debug, PartialEq, Deserialize)]
struct TestConfig {
#[serde(rename = "versioning")]
version: String,
debug: bool,
port: u16,
timeout: f64,
}
#[derive(Debug, PartialEq, Deserialize)]
struct DatabaseConfig {
host: String,
port: u16,
ssl: bool,
}
#[derive(Debug, PartialEq, Deserialize)]
struct AppConfig {
app_name: String,
database: DatabaseConfig,
features: Vec<String>,
}
#[test]
fn deserialize_simple_values_works_correctly() {
let meta = Metadata::new(Location::new(0, 0));
let value = Value::new_string("test".to_string(), meta.clone());
let result: String = from_value(&value).expect("should deserialize string");
assert_eq!(result, "test");
let value = Value::new_int(42, meta.clone());
let result: i32 = from_value(&value).expect("should deserialize integer");
assert_eq!(result, 42);
let value = Value::new_bool(true, meta.clone());
let result: bool = from_value(&value).expect("should deserialize boolean");
assert!(result);
let value = Value::new_float(3.14, meta);
let result: f64 = from_value(&value).expect("should deserialize float");
assert_eq!(result, 3.14);
}
#[test]
fn deserialize_from_statement_works_correctly() {
let barkml = r#"
versioning = "1.0.0"
debug = true
port = 8080u16
timeout = 30.5
"#;
let statement = from_str(barkml).expect("should parse BarkML");
let config: TestConfig = from_statement(&statement).expect("should deserialize config");
assert_eq!(config.version, "1.0.0");
assert!(config.debug);
assert_eq!(config.port, 8080);
assert_eq!(config.timeout, 30.5);
}
#[test]
fn deserialize_nested_structure_works_correctly() {
let barkml = r#"
app_name = "MyApp"
features = ["auth", "logging", "metrics"]
[database]
host = "localhost"
port = 5432u16
ssl = true
"#;
let statement = from_str(barkml).expect("should parse BarkML");
let config: AppConfig = from_statement(&statement).expect("should deserialize config");
assert_eq!(config.app_name, "MyApp");
assert_eq!(config.features, vec!["auth", "logging", "metrics"]);
assert_eq!(config.database.host, "localhost");
assert_eq!(config.database.port, 5432);
assert!(config.database.ssl);
}
#[test]
fn deserialize_array_works_correctly() {
let meta = Metadata::new(Location::new(0, 0));
let array_data = vec![
Value::new_string("first".to_string(), meta.clone()),
Value::new_string("second".to_string(), meta.clone()),
Value::new_string("third".to_string(), meta),
];
let value = Value::new_array(array_data, Metadata::new(Location::new(0, 0)));
let result: Vec<String> = from_value(&value).expect("should deserialize array");
assert_eq!(result, vec!["first", "second", "third"]);
}
#[test]
fn deserialize_table_works_correctly() {
let meta = Metadata::new(Location::new(0, 0));
let mut table_data = IndexMap::new();
table_data.insert(
"name".to_string(),
Value::new_string("Alice".to_string(), meta.clone()),
);
table_data.insert("age".to_string(), Value::new_int(30, meta.clone()));
let value = Value::new_table(table_data, meta);
#[derive(Debug, PartialEq, Deserialize)]
struct Person {
name: String,
age: i32,
}
let result: Person = from_value(&value).expect("should deserialize table");
assert_eq!(result.name, "Alice");
assert_eq!(result.age, 30);
}
#[test]
fn error_handling_works_correctly() {
let meta = Metadata::new(Location::new(0, 0));
let value = Value::new_string("not_a_number".to_string(), meta);
let result: std::result::Result<i32, _> = from_value(&value);
assert!(result.is_err());
}
}