use rbs::Value;
use rbs::value::Table;
use rbs::value::map::ValueMap;
use serde_json;
#[test]
fn test_table_basic() {
let mut table = Table::new();
table.add_column(Value::String("id".to_string()));
table.add_column(Value::String("name".to_string()));
table.add_row(vec![Value::I32(1), Value::String("Alice".to_string())]);
table.add_row(vec![Value::I32(2), Value::String("Bob".to_string())]);
let value = Value::Table(table.clone());
assert!(value.is_table());
let t = value.as_table().unwrap();
assert_eq!(t.column_count(), 2);
assert_eq!(t.row_count(), 2);
assert_eq!(t.get(0, 0), Some(&Value::I32(1)));
assert_eq!(t.get(0, 1), Some(&Value::String("Alice".to_string())));
assert_eq!(t.get(1, 0), Some(&Value::I32(2)));
assert_eq!(t.get(1, 1), Some(&Value::String("Bob".to_string())));
let row0 = t.row(0);
assert_eq!(row0.as_array().unwrap().len(), 2);
assert_eq!(row0.as_array().unwrap()[0], Value::I32(1));
assert_eq!(row0.as_array().unwrap()[1], Value::String("Alice".to_string()));
let row1 = t.row(1);
assert_eq!(row1.as_array().unwrap()[0], Value::I32(2));
assert_eq!(row1.as_array().unwrap()[1], Value::String("Bob".to_string()));
let row2 = t.row(2);
assert!(row2.is_null());
let col_id = t.column("id");
assert_eq!(col_id.as_array().unwrap().len(), 2);
assert_eq!(col_id.as_array().unwrap()[0], Value::I32(1));
assert_eq!(col_id.as_array().unwrap()[1], Value::I32(2));
let col_name = t.column("name");
assert_eq!(col_name.as_array().unwrap()[0], Value::String("Alice".to_string()));
assert_eq!(col_name.as_array().unwrap()[1], Value::String("Bob".to_string()));
let col_unknown = t.column("unknown");
assert!(col_unknown.is_null());
}
#[test]
fn test_table_serialize() {
let mut table = Table::new();
table.add_column(Value::String("id".to_string()));
table.add_column(Value::String("name".to_string()));
table.add_row(vec![Value::I32(1), Value::String("Alice".to_string())]);
table.add_row(vec![Value::I32(2), Value::String("Bob".to_string())]);
let value = Value::Table(table);
let serialized = serde_json::to_string(&value).unwrap();
assert!(!serialized.contains("__table__"));
assert!(serialized.contains("columns"));
assert!(serialized.contains("rows"));
assert!(serialized.contains("\"id\""));
assert!(serialized.contains("\"name\""));
assert!(serialized.contains("[1,\"Alice\"]"));
assert!(serialized.contains("[2,\"Bob\"]"));
}
#[test]
fn test_table_deserialize() {
let json = r#"{"columns":["id","name"],"rows":[[1,"Alice"],[2,"Bob"]]}"#;
let value: Value = serde_json::from_str(json).unwrap();
assert!(value.is_table());
let table = value.as_table().unwrap();
assert_eq!(table.columns.len(), 2);
assert_eq!(table.rows.len(), 2);
assert_eq!(table.rows[0], vec![Value::U64(1), Value::String("Alice".to_string())]);
assert_eq!(table.rows[1], vec![Value::U64(2), Value::String("Bob".to_string())]);
}
#[test]
fn test_table_roundtrip() {
let mut original = Table::new();
original.add_column(Value::String("id".to_string()));
original.add_column(Value::String("name".to_string()));
original.add_column(Value::String("status".to_string()));
original.add_row(vec![Value::U64(1), Value::String("Alice".to_string()), Value::U64(1)]);
original.add_row(vec![Value::U64(2), Value::String("Bob".to_string()), Value::U64(0)]);
original.add_row(vec![Value::U64(3), Value::String("Charlie".to_string()), Value::U64(1)]);
let value = Value::Table(original.clone());
let json = serde_json::to_string(&value).unwrap();
assert!(!json.contains("__table__"));
let recovered: Value = serde_json::from_str(&json).unwrap();
let recovered_table = recovered.as_table().unwrap();
assert_eq!(original.columns, recovered_table.columns);
assert_eq!(original.rows, recovered_table.rows);
}
#[test]
fn test_table_with_nulls() {
let mut table = Table::new();
table.add_column(Value::String("id".to_string()));
table.add_column(Value::String("name".to_string()));
table.add_row(vec![Value::I32(1), Value::Null]);
table.add_row(vec![Value::Null, Value::String("Bob".to_string())]);
let value = Value::Table(table);
let json = serde_json::to_string(&value).unwrap();
let recovered: Value = serde_json::from_str(&json).unwrap();
let t = recovered.as_table().unwrap();
assert_eq!(t.rows[0][1], Value::Null);
assert_eq!(t.rows[1][0], Value::Null);
}
#[test]
fn test_table_len_and_is_empty() {
let mut table = Table::new();
let value = Value::Table(table.clone());
assert!(value.is_empty());
assert_eq!(value.len(), 0);
table.add_column(Value::String("id".to_string()));
table.add_row(vec![Value::I32(1)]);
let value = Value::Table(table);
assert!(!value.is_empty());
assert_eq!(value.len(), 1);
}
#[test]
fn test_table_display() {
let mut table = Table::new();
table.add_column(Value::String("id".to_string()));
table.add_column(Value::String("name".to_string()));
table.add_row(vec![Value::I32(1), Value::String("Alice".to_string())]);
let value = Value::Table(table);
let display = format!("{}", value);
assert!(display.contains("columns"));
assert!(display.contains("rows"));
assert!(display.contains("id"));
assert!(display.contains("name"));
}
#[test]
fn test_table_into_table() {
let mut table = Table::new();
table.add_column(Value::String("x".to_string()));
table.add_row(vec![Value::I32(42)]);
let value = Value::Table(table.clone());
let recovered = value.into_table().unwrap();
assert_eq!(recovered.columns, table.columns);
assert_eq!(recovered.rows, table.rows);
let not_table = Value::String("test".to_string());
assert!(not_table.into_table().is_none());
}
#[test]
fn test_table_hash() {
let mut t1 = Table::new();
t1.add_column(Value::String("id".to_string()));
t1.add_row(vec![Value::I32(1)]);
let mut t2 = Table::new();
t2.add_column(Value::String("id".to_string()));
t2.add_row(vec![Value::I32(1)]);
let mut t3 = Table::new();
t3.add_column(Value::String("id".to_string()));
t3.add_row(vec![Value::I32(2)]);
let v1 = Value::Table(t1);
let v2 = Value::Table(t2);
let v3 = Value::Table(t3);
assert_eq!(v1, v2);
assert_ne!(v1, v3);
}
#[test]
fn test_table_with_complex_types() {
let mut table = Table::new();
table.add_column(Value::String("id".to_string()));
table.add_column(Value::String("data".to_string()));
table.add_row(vec![
Value::I32(1),
Value::Array(vec![Value::String("a".to_string()), Value::String("b".to_string())]),
]);
let value = Value::Table(table);
let json = serde_json::to_string(&value).unwrap();
let recovered: Value = serde_json::from_str(&json).unwrap();
let t = recovered.as_table().unwrap();
if let Value::Array(arr) = &t.rows[0][1] {
assert_eq!(arr.len(), 2);
assert_eq!(arr[0], Value::String("a".to_string()));
} else {
panic!("Expected array");
}
}
#[test]
fn test_table_deserialize_to_struct() {
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
struct User {
id: u64,
name: String,
email: String,
status: u32,
}
let json = r#"{
"columns": ["id", "name", "email", "status"],
"rows": [
[1, "Alice", "alice@example.com", 1],
[2, "Bob", "bob@example.com", 0]
]
}"#;
let value: Value = serde_json::from_str(json).unwrap();
let users: Vec<User> = rbs::from_value(value).unwrap();
assert_eq!(users.len(), 2);
assert_eq!(users[0], User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
status: 1,
});
assert_eq!(users[1], User {
id: 2,
name: "Bob".to_string(),
email: "bob@example.com".to_string(),
status: 0,
});
}
#[test]
fn test_table_from_struct_vec() {
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
struct Record {
id: u64,
name: String,
value: i32,
}
let records = vec![
Record { id: 1, name: "A".to_string(), value: 100 },
Record { id: 2, name: "B".to_string(), value: 200 },
Record { id: 3, name: "C".to_string(), value: 300 },
];
let mut table = Table::new();
table.columns = vec![
Value::String("id".to_string()),
Value::String("name".to_string()),
Value::String("value".to_string()),
];
for rec in &records {
table.rows.push(vec![
Value::U64(rec.id),
Value::String(rec.name.clone()),
Value::I32(rec.value),
]);
}
let value = Value::Table(table);
let json = serde_json::to_string(&value).unwrap();
assert!(json.contains("\"columns\":"));
assert!(json.contains("\"rows\":"));
assert!(json.contains("[1,\"A\",100]"));
}
#[test]
fn test_table_to_vec_struct() {
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
struct User {
id: u64,
name: String,
}
let mut table = Table::new();
table.columns = vec![Value::String("id".into()), Value::String("name".into())];
table.rows = vec![
vec![Value::U64(1), Value::String("Alice".into())],
vec![Value::U64(2), Value::String("Bob".into())],
];
let users: Vec<User> = table.to_vec().unwrap();
assert_eq!(users.len(), 2);
assert_eq!(users[0], User { id: 1, name: "Alice".to_string() });
assert_eq!(users[1], User { id: 2, name: "Bob".to_string() });
}
#[test]
fn test_table_with_different_types() {
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
struct Item {
flag: bool,
count: i32,
name: String,
}
let mut table = Table::new();
table.columns = vec![
Value::String("flag".into()),
Value::String("count".into()),
Value::String("name".into()),
];
table.rows = vec![
vec![Value::Bool(true), Value::I32(10), Value::String("item1".into())],
vec![Value::Bool(false), Value::I32(20), Value::String("item2".into())],
];
let items: Vec<Item> = table.to_vec().unwrap();
assert_eq!(items[0].flag, true);
assert_eq!(items[0].count, 10);
assert_eq!(items[0].name, "item1");
assert_eq!(items[1].flag, false);
}
#[test]
fn test_table_empty_columns_with_rows() {
let mut table = Table::new();
table.add_row(vec![Value::I32(1), Value::String("Alice".to_string())]);
let value = Value::Table(table);
let json = serde_json::to_string(&value).unwrap();
let recovered: Value = serde_json::from_str(&json).unwrap();
let t = recovered.as_table().unwrap();
assert_eq!(t.columns.len(), 0);
assert_eq!(t.rows.len(), 1);
assert_eq!(t.rows[0].len(), 2);
}
#[test]
fn test_table_zero_rows() {
let mut table = Table::new();
table.add_column(Value::String("id".to_string()));
table.add_column(Value::String("name".to_string()));
let value = Value::Table(table.clone());
assert!(value.is_empty());
assert_eq!(value.len(), 0);
assert_eq!(table.row_count(), 0);
assert_eq!(table.column_count(), 2);
let json = serde_json::to_string(&value).unwrap();
let recovered: Value = serde_json::from_str(&json).unwrap();
let t = recovered.as_table().unwrap();
assert_eq!(t.columns.len(), 2);
assert_eq!(t.rows.len(), 0);
}
#[test]
fn test_table_row_length_mismatch() {
#[derive(Debug, PartialEq, serde::Deserialize)]
struct Pair {
a: i32,
b: String,
}
let mut table = Table::new();
table.add_column(Value::String("a".to_string()));
table.add_column(Value::String("b".to_string()));
table.add_row(vec![Value::I32(1)]);
let value = Value::Table(table);
let result: Result<Vec<Pair>, _> = rbs::from_value(value);
assert!(result.is_err());
}
#[test]
fn test_table_from_value_empty_columns_with_rows() {
let mut table = Table::new();
table.add_row(vec![Value::I32(1), Value::String("Alice".to_string())]);
let value = Value::Table(table);
let vec: Vec<serde_json::Value> = rbs::from_value(value).unwrap();
assert_eq!(vec.len(), 1);
assert_eq!(vec[0].as_array().unwrap().len(), 2);
}
#[test]
fn test_table_from_value_zero_rows() {
let mut table = Table::new();
table.add_column(Value::String("id".to_string()));
table.add_column(Value::String("name".to_string()));
let value = Value::Table(table);
let vec: Vec<serde_json::Value> = rbs::from_value(value).unwrap();
assert_eq!(vec.len(), 0);
}
#[test]
fn test_table_from_value_with_nulls() {
#[derive(Debug, PartialEq, serde::Deserialize)]
struct Record {
a: String,
b: Option<String>,
c: String,
}
let mut table = Table::new();
table.add_column(Value::String("a".to_string()));
table.add_column(Value::String("b".to_string()));
table.add_column(Value::String("c".to_string()));
table.add_row(vec![
Value::String("first".to_string()),
Value::Null,
Value::String("third".to_string()),
]);
let value = Value::Table(table);
let records: Vec<Record> = rbs::from_value(value).unwrap();
assert_eq!(records[0].a, "first");
assert_eq!(records[0].b, None);
assert_eq!(records[0].c, "third");
}
#[test]
fn test_table_from_value_too_many_fields() {
#[derive(Debug, PartialEq, serde::Deserialize)]
struct Triple {
a: i32,
b: String,
}
let mut table = Table::new();
table.add_column(Value::String("a".to_string()));
table.add_column(Value::String("b".to_string()));
table.add_row(vec![Value::I32(1), Value::String("x".to_string()), Value::I32(99)]);
let value = Value::Table(table);
let result: Result<Vec<Triple>, _> = rbs::from_value(value);
let vec = result.unwrap();
assert_eq!(vec.len(), 1);
assert_eq!(vec[0].a, 1);
assert_eq!(vec[0].b, "x");
}
#[test]
fn test_table_deserialize_invalid_json_no_columns() {
let json = r#"{"rows":[[1,"Alice"]]}"#;
let value: Value = serde_json::from_str(json).unwrap();
assert!(value.is_map());
assert!(!value.is_table());
}
#[test]
fn test_table_deserialize_invalid_json_no_rows() {
let json = r#"{"columns":["id","name"]}"#;
let value: Value = serde_json::from_str(json).unwrap();
assert!(value.is_map());
assert!(!value.is_table());
}
#[test]
fn test_table_deserialize_invalid_json_extra_fields() {
let json = r#"{"columns":["id"],"rows":[[1]],"extra":"value"}"#;
let value: Value = serde_json::from_str(json).unwrap();
assert!(value.is_map());
let map = value.as_map().unwrap();
assert_eq!(map.len(), 3);
}
#[test]
fn test_table_to_vec_empty() {
let table = Table::new();
let result: Vec<serde_json::Value> = table.to_vec().unwrap();
assert_eq!(result.len(), 0);
}
#[test]
fn test_table_from_value_empty_table() {
let table = Table::new();
let value = Value::Table(table);
let vec: Vec<serde_json::Value> = rbs::from_value(value).unwrap();
assert_eq!(vec.len(), 0);
}
#[test]
fn test_table_to_maps() {
let mut table = Table::new();
table.add_column(Value::String("id".to_string()));
table.add_column(Value::String("name".to_string()));
table.add_column(Value::String("age".to_string()));
table.add_row(vec![
Value::I32(1),
Value::String("Alice".to_string()),
Value::I32(25),
]);
table.add_row(vec![
Value::I32(2),
Value::String("Bob".to_string()),
Value::I32(30),
]);
let maps = table.to_maps();
assert_eq!(maps.len(), 2);
let map0 = &maps[0];
assert_eq!(map0.get(&Value::String("id".to_string())), &Value::I32(1));
assert_eq!(map0.get(&Value::String("name".to_string())), &Value::String("Alice".to_string()));
assert_eq!(map0.get(&Value::String("age".to_string())), &Value::I32(25));
let map1 = &maps[1];
assert_eq!(map1.get(&Value::String("id".to_string())), &Value::I32(2));
assert_eq!(map1.get(&Value::String("name".to_string())), &Value::String("Bob".to_string()));
assert_eq!(map1.get(&Value::String("age".to_string())), &Value::I32(30));
}
#[test]
fn test_table_to_maps_empty() {
let table = Table::new();
let maps = table.to_maps();
assert_eq!(maps.len(), 0);
}
#[test]
fn test_table_to_maps_with_null() {
let mut table = Table::new();
table.add_column(Value::String("a".to_string()));
table.add_column(Value::String("b".to_string()));
table.add_row(vec![Value::String("x".to_string()), Value::Null]);
let maps = table.to_maps();
assert_eq!(maps[0].get(&Value::String("a".to_string())), &Value::String("x".to_string()));
assert_eq!(maps[0].get(&Value::String("b".to_string())), &Value::Null);
}
#[test]
fn test_table_from_maps() {
let mut m1 = ValueMap::new();
m1.insert(Value::String("id".to_string()), Value::I32(1));
m1.insert(Value::String("name".to_string()), Value::String("Alice".to_string()));
let mut m2 = ValueMap::new();
m2.insert(Value::String("id".to_string()), Value::I32(2));
m2.insert(Value::String("name".to_string()), Value::String("Bob".to_string()));
let table = Table::from_maps(&[m1, m2]);
assert_eq!(table.column_count(), 2);
assert_eq!(table.row_count(), 2);
assert_eq!(table.columns[0], Value::String("id".to_string()));
assert_eq!(table.columns[1], Value::String("name".to_string()));
assert_eq!(table.get(0, 0), Some(&Value::I32(1)));
assert_eq!(table.get(0, 1), Some(&Value::String("Alice".to_string())));
assert_eq!(table.get(1, 0), Some(&Value::I32(2)));
assert_eq!(table.get(1, 1), Some(&Value::String("Bob".to_string())));
}
#[test]
fn test_table_from_maps_empty() {
let table = Table::from_maps(&[]);
assert_eq!(table.column_count(), 0);
assert_eq!(table.row_count(), 0);
}
#[test]
fn test_table_from_maps_with_missing_keys() {
let mut m1 = ValueMap::new();
m1.insert(Value::String("a".to_string()), Value::I32(1));
m1.insert(Value::String("b".to_string()), Value::I32(2));
let mut m2 = ValueMap::new();
m2.insert(Value::String("a".to_string()), Value::I32(3));
let table = Table::from_maps(&[m1, m2]);
assert_eq!(table.column_count(), 2);
assert_eq!(table.row_count(), 2);
assert_eq!(table.get(0, 1), Some(&Value::I32(2))); assert_eq!(table.get(1, 1), Some(&Value::Null)); }
#[test]
fn test_table_from_maps_roundtrip() {
let mut original = Table::new();
original.add_column(Value::String("x".to_string()));
original.add_column(Value::String("y".to_string()));
original.add_row(vec![Value::I32(10), Value::String("ten".to_string())]);
original.add_row(vec![Value::I32(20), Value::String("twenty".to_string())]);
let maps = original.to_maps();
let recovered = Table::from_maps(&maps);
assert_eq!(original.columns, recovered.columns);
assert_eq!(original.rows, recovered.rows);
}