use super::{InterpreterError, Value};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[inline]
pub fn is_mutable_object(value: &Value) -> bool {
matches!(value, Value::ObjectMut(_))
}
#[inline]
pub fn is_object(value: &Value) -> bool {
matches!(value, Value::Object(_) | Value::ObjectMut(_))
}
pub fn get_object_field(value: &Value, field: &str) -> Option<Value> {
match value {
Value::Object(map) => map.get(field).cloned(),
Value::ObjectMut(cell) => cell
.lock()
.expect("Mutex poisoned in get_object_field - indicates panic in another thread")
.get(field)
.cloned(),
_ => None,
}
}
pub fn set_object_field(
value: &Value,
field: &str,
new_value: Value,
) -> Result<(), InterpreterError> {
match value {
Value::Object(_) => Err(InterpreterError::RuntimeError(format!(
"Cannot mutate immutable object field '{field}'"
))),
Value::ObjectMut(cell) => {
cell.lock()
.expect("Mutex poisoned in set_object_field - indicates panic in another thread")
.insert(field.to_string(), new_value);
Ok(())
}
_ => Err(InterpreterError::RuntimeError(format!(
"Cannot access field '{field}' on non-object"
))),
}
}
#[inline]
pub fn new_mutable_object(map: HashMap<String, Value>) -> Value {
Value::ObjectMut(Arc::new(Mutex::new(map)))
}
#[inline]
pub fn new_immutable_object(map: HashMap<String, Value>) -> Value {
Value::Object(Arc::new(map))
}
pub fn to_mutable(value: &Value) -> Value {
match value {
Value::Object(map) => Value::ObjectMut(Arc::new(Mutex::new((**map).clone()))),
Value::ObjectMut(_) => value.clone(),
_ => value.clone(),
}
}
pub fn to_immutable(value: &Value) -> Value {
match value {
Value::ObjectMut(cell) => Value::Object(Arc::new(
cell.lock()
.expect("Mutex poisoned in to_immutable - indicates panic in another thread")
.clone(),
)),
Value::Object(_) => value.clone(),
_ => value.clone(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_mutable_object() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let immutable = new_immutable_object(map.clone());
let mutable = new_mutable_object(map);
assert!(!is_mutable_object(&immutable));
assert!(is_mutable_object(&mutable));
}
#[test]
fn test_is_object() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let immutable = new_immutable_object(map.clone());
let mutable = new_mutable_object(map);
assert!(is_object(&immutable));
assert!(is_object(&mutable));
assert!(!is_object(&Value::Integer(42)));
}
#[test]
fn test_get_object_field() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let immutable = new_immutable_object(map.clone());
let mutable = new_mutable_object(map);
assert_eq!(
get_object_field(&immutable, "key"),
Some(Value::Integer(42))
);
assert_eq!(get_object_field(&mutable, "key"), Some(Value::Integer(42)));
assert_eq!(get_object_field(&immutable, "missing"), None);
}
#[test]
fn test_set_object_field() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let immutable = new_immutable_object(map.clone());
let mutable = new_mutable_object(map);
assert!(set_object_field(&immutable, "key", Value::Integer(99)).is_err());
assert!(set_object_field(&mutable, "key", Value::Integer(99)).is_ok());
assert_eq!(get_object_field(&mutable, "key"), Some(Value::Integer(99)));
}
#[test]
fn test_set_new_field() {
let map = HashMap::new();
let mutable = new_mutable_object(map);
assert!(set_object_field(&mutable, "new_key", Value::Integer(123)).is_ok());
assert_eq!(
get_object_field(&mutable, "new_key"),
Some(Value::Integer(123))
);
}
#[test]
fn test_to_mutable() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let immutable = new_immutable_object(map);
let mutable = to_mutable(&immutable);
assert!(is_mutable_object(&mutable));
assert_eq!(get_object_field(&mutable, "key"), Some(Value::Integer(42)));
assert!(set_object_field(&mutable, "key", Value::Integer(99)).is_ok());
assert_eq!(get_object_field(&mutable, "key"), Some(Value::Integer(99)));
}
#[test]
fn test_to_immutable() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let mutable = new_mutable_object(map);
let immutable = to_immutable(&mutable);
assert!(!is_mutable_object(&immutable));
assert_eq!(
get_object_field(&immutable, "key"),
Some(Value::Integer(42))
);
}
#[test]
fn test_to_mutable_idempotent() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let mutable1 = new_mutable_object(map);
let mutable2 = to_mutable(&mutable1);
assert!(is_mutable_object(&mutable2));
}
#[test]
fn test_non_object_type() {
let int_val = Value::Integer(42);
assert_eq!(get_object_field(&int_val, "key"), None);
assert!(set_object_field(&int_val, "key", Value::Integer(99)).is_err());
}
}
#[test]
fn test_to_immutable_object_match_arm() {
use std::sync::Arc;
let mut map = HashMap::new();
map.insert("test".to_string(), Value::Integer(42));
let immutable_obj = Value::Object(Arc::new(map));
let result = to_immutable(&immutable_obj);
if let Value::Object(obj) = result {
assert_eq!(obj.get("test"), Some(&Value::Integer(42)));
} else {
panic!("Should return Object variant");
}
}
#[test]
fn test_to_immutable_idempotent() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let immutable1 = new_immutable_object(map);
let immutable2 = to_immutable(&immutable1);
assert!(!is_mutable_object(&immutable2));
assert_eq!(
get_object_field(&immutable2, "key"),
Some(Value::Integer(42))
);
}
#[test]
fn test_to_mutable_non_object() {
let int_val = Value::Integer(42);
let result = to_mutable(&int_val);
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_to_immutable_non_object() {
let float_val = Value::Float(3.14);
let result = to_immutable(&float_val);
assert_eq!(result, Value::Float(3.14));
}
#[test]
fn test_set_object_field_immutable_error_message() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(42));
let immutable = new_immutable_object(map);
let err = set_object_field(&immutable, "field", Value::Integer(1)).unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("immutable"));
assert!(msg.contains("field"));
}
#[test]
fn test_set_object_field_non_object_error_message() {
let int_val = Value::Integer(42);
let err = set_object_field(&int_val, "foo", Value::Integer(1)).unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("non-object"));
assert!(msg.contains("foo"));
}
#[test]
fn test_empty_mutable_object() {
let mutable = new_mutable_object(HashMap::new());
assert!(is_mutable_object(&mutable));
assert!(is_object(&mutable));
assert_eq!(get_object_field(&mutable, "any"), None);
}
#[test]
fn test_empty_immutable_object() {
let immutable = new_immutable_object(HashMap::new());
assert!(!is_mutable_object(&immutable));
assert!(is_object(&immutable));
assert_eq!(get_object_field(&immutable, "any"), None);
}
#[test]
fn test_is_mutable_object_all_value_types() {
use std::sync::Arc;
assert!(!is_mutable_object(&Value::Integer(1)));
assert!(!is_mutable_object(&Value::Float(1.0)));
assert!(!is_mutable_object(&Value::Bool(true)));
assert!(!is_mutable_object(&Value::Nil));
assert!(!is_mutable_object(&Value::from_string("test".to_string())));
assert!(!is_mutable_object(&Value::Array(Arc::from(vec![]))));
assert!(!is_mutable_object(&Value::Tuple(Arc::from(vec![]))));
let mutable = new_mutable_object(HashMap::new());
assert!(is_mutable_object(&mutable));
}
#[test]
fn test_is_object_all_value_types() {
use std::sync::Arc;
assert!(!is_object(&Value::Integer(1)));
assert!(!is_object(&Value::Float(1.0)));
assert!(!is_object(&Value::Bool(true)));
assert!(!is_object(&Value::Nil));
assert!(!is_object(&Value::from_string("test".to_string())));
assert!(!is_object(&Value::Array(Arc::from(vec![]))));
assert!(!is_object(&Value::Tuple(Arc::from(vec![]))));
let immutable = new_immutable_object(HashMap::new());
let mutable = new_mutable_object(HashMap::new());
assert!(is_object(&immutable));
assert!(is_object(&mutable));
}
#[test]
fn test_get_object_field_multiple_fields() {
let mut map = HashMap::new();
map.insert("a".to_string(), Value::Integer(1));
map.insert("b".to_string(), Value::Integer(2));
map.insert("c".to_string(), Value::Integer(3));
let obj = new_immutable_object(map);
assert_eq!(get_object_field(&obj, "a"), Some(Value::Integer(1)));
assert_eq!(get_object_field(&obj, "b"), Some(Value::Integer(2)));
assert_eq!(get_object_field(&obj, "c"), Some(Value::Integer(3)));
assert_eq!(get_object_field(&obj, "d"), None);
}
#[test]
fn test_get_object_field_nested_values() {
use std::sync::Arc;
let mut inner = HashMap::new();
inner.insert("inner_key".to_string(), Value::Integer(42));
let mut outer = HashMap::new();
outer.insert("nested".to_string(), Value::Object(Arc::new(inner)));
let obj = new_mutable_object(outer);
if let Some(Value::Object(nested_obj)) = get_object_field(&obj, "nested") {
assert_eq!(nested_obj.get("inner_key"), Some(&Value::Integer(42)));
} else {
panic!("Expected nested object");
}
}
#[test]
fn test_set_object_field_overwrite_multiple() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(0));
let mutable = new_mutable_object(map);
for i in 1..=10 {
assert!(set_object_field(&mutable, "key", Value::Integer(i)).is_ok());
assert_eq!(get_object_field(&mutable, "key"), Some(Value::Integer(i)));
}
}
#[test]
fn test_set_object_field_different_types() {
let mutable = new_mutable_object(HashMap::new());
assert!(set_object_field(&mutable, "str", Value::from_string("hello".to_string())).is_ok());
assert!(set_object_field(&mutable, "bool", Value::Bool(true)).is_ok());
assert!(set_object_field(&mutable, "nil", Value::Nil).is_ok());
if let Some(Value::String(s)) = get_object_field(&mutable, "str") {
assert_eq!(s.as_ref(), "hello");
} else {
panic!("Expected string");
}
assert_eq!(get_object_field(&mutable, "bool"), Some(Value::Bool(true)));
assert_eq!(get_object_field(&mutable, "nil"), Some(Value::Nil));
}
#[test]
fn test_to_mutable_preserves_all_fields() {
let mut map = HashMap::new();
map.insert("a".to_string(), Value::Integer(1));
map.insert("b".to_string(), Value::Integer(2));
map.insert("c".to_string(), Value::Integer(3));
let immutable = new_immutable_object(map);
let mutable = to_mutable(&immutable);
assert_eq!(get_object_field(&mutable, "a"), Some(Value::Integer(1)));
assert_eq!(get_object_field(&mutable, "b"), Some(Value::Integer(2)));
assert_eq!(get_object_field(&mutable, "c"), Some(Value::Integer(3)));
}
#[test]
fn test_to_immutable_preserves_all_fields() {
let mut map = HashMap::new();
map.insert("x".to_string(), Value::Integer(10));
map.insert("y".to_string(), Value::Integer(20));
let mutable = new_mutable_object(map);
let immutable = to_immutable(&mutable);
assert_eq!(get_object_field(&immutable, "x"), Some(Value::Integer(10)));
assert_eq!(get_object_field(&immutable, "y"), Some(Value::Integer(20)));
}
#[test]
fn test_to_mutable_creates_independent_copy() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(1));
let immutable = new_immutable_object(map);
let mutable = to_mutable(&immutable);
assert!(set_object_field(&mutable, "key", Value::Integer(100)).is_ok());
assert_eq!(get_object_field(&immutable, "key"), Some(Value::Integer(1)));
assert_eq!(get_object_field(&mutable, "key"), Some(Value::Integer(100)));
}
#[test]
fn test_to_immutable_creates_independent_copy() {
let mut map = HashMap::new();
map.insert("key".to_string(), Value::Integer(1));
let mutable = new_mutable_object(map);
let immutable = to_immutable(&mutable);
assert!(set_object_field(&mutable, "key", Value::Integer(100)).is_ok());
assert_eq!(get_object_field(&immutable, "key"), Some(Value::Integer(1)));
assert_eq!(get_object_field(&mutable, "key"), Some(Value::Integer(100)));
}
#[test]
fn test_special_field_names() {
let mutable = new_mutable_object(HashMap::new());
assert!(set_object_field(&mutable, "", Value::Integer(1)).is_ok());
assert_eq!(get_object_field(&mutable, ""), Some(Value::Integer(1)));
assert!(set_object_field(&mutable, "field with spaces", Value::Integer(2)).is_ok());
assert_eq!(
get_object_field(&mutable, "field with spaces"),
Some(Value::Integer(2))
);
assert!(set_object_field(&mutable, "field_123", Value::Integer(3)).is_ok());
assert_eq!(
get_object_field(&mutable, "field_123"),
Some(Value::Integer(3))
);
}
#[test]
fn test_unicode_field_names_r162() {
let mutable = new_mutable_object(HashMap::new());
assert!(set_object_field(&mutable, "日本語", Value::Integer(1)).is_ok());
assert_eq!(
get_object_field(&mutable, "日本語"),
Some(Value::Integer(1))
);
assert!(set_object_field(&mutable, "🎉🚀", Value::Integer(2)).is_ok());
assert_eq!(get_object_field(&mutable, "🎉🚀"), Some(Value::Integer(2)));
assert!(set_object_field(&mutable, "Ù…Ø±ØØ¨Ø§", Value::Integer(3)).is_ok());
assert_eq!(get_object_field(&mutable, "Ù…Ø±ØØ¨Ø§"), Some(Value::Integer(3)));
assert!(set_object_field(&mutable, "hello世界", Value::Integer(4)).is_ok());
assert_eq!(
get_object_field(&mutable, "hello世界"),
Some(Value::Integer(4))
);
}
#[test]
fn test_large_object_50_fields_r162() {
let mut map = HashMap::new();
for i in 0..50 {
map.insert(format!("field_{i}"), Value::Integer(i));
}
let obj = new_mutable_object(map);
for i in 0..50 {
assert_eq!(
get_object_field(&obj, &format!("field_{i}")),
Some(Value::Integer(i))
);
}
}
#[test]
fn test_large_object_100_fields_r162() {
let mut map = HashMap::new();
for i in 0..100 {
map.insert(format!("key_{i}"), Value::Integer(i * 2));
}
let immutable = new_immutable_object(map);
for i in 0..100 {
assert_eq!(
get_object_field(&immutable, &format!("key_{i}")),
Some(Value::Integer(i * 2))
);
}
}
#[test]
fn test_nested_mutable_in_immutable_r162() {
let inner_mutable = new_mutable_object(HashMap::new());
set_object_field(&inner_mutable, "inner", Value::Integer(42)).unwrap();
let mut outer = HashMap::new();
outer.insert("nested".to_string(), inner_mutable);
let outer_immutable = new_immutable_object(outer);
if let Some(nested) = get_object_field(&outer_immutable, "nested") {
assert!(is_mutable_object(&nested));
assert_eq!(get_object_field(&nested, "inner"), Some(Value::Integer(42)));
} else {
panic!("Expected nested object");
}
}
#[test]
fn test_nested_immutable_in_mutable_r162() {
let inner = new_immutable_object(HashMap::from([
("x".to_string(), Value::Integer(10)),
("y".to_string(), Value::Integer(20)),
]));
let outer = new_mutable_object(HashMap::new());
set_object_field(&outer, "inner", inner).unwrap();
if let Some(nested) = get_object_field(&outer, "inner") {
assert!(!is_mutable_object(&nested));
assert_eq!(get_object_field(&nested, "x"), Some(Value::Integer(10)));
} else {
panic!("Expected nested object");
}
}
#[test]
fn test_value_array_in_object_r162() {
use std::sync::Arc;
let arr = Value::Array(Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]));
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "arr", arr.clone()).unwrap();
let retrieved = get_object_field(&obj, "arr").unwrap();
if let Value::Array(elems) = retrieved {
assert_eq!(elems.len(), 3);
assert_eq!(elems[0], Value::Integer(1));
assert_eq!(elems[2], Value::Integer(3));
} else {
panic!("Expected array");
}
}
#[test]
fn test_value_tuple_in_object_r162() {
use std::sync::Arc;
let tuple = Value::Tuple(Arc::from(vec![
Value::from_string("hello".to_string()),
Value::Integer(42),
]));
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "tup", tuple.clone()).unwrap();
let retrieved = get_object_field(&obj, "tup").unwrap();
if let Value::Tuple(elems) = retrieved {
assert_eq!(elems.len(), 2);
} else {
panic!("Expected tuple");
}
}
#[test]
fn test_nil_value_storage_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "nil_field", Value::Nil).unwrap();
assert_eq!(get_object_field(&obj, "nil_field"), Some(Value::Nil));
}
#[test]
fn test_bool_values_in_object_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "true_field", Value::Bool(true)).unwrap();
set_object_field(&obj, "false_field", Value::Bool(false)).unwrap();
assert_eq!(
get_object_field(&obj, "true_field"),
Some(Value::Bool(true))
);
assert_eq!(
get_object_field(&obj, "false_field"),
Some(Value::Bool(false))
);
}
#[test]
fn test_float_values_in_object_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "pi", Value::Float(3.14159)).unwrap();
set_object_field(&obj, "neg", Value::Float(-2.5)).unwrap();
set_object_field(&obj, "zero", Value::Float(0.0)).unwrap();
assert_eq!(get_object_field(&obj, "pi"), Some(Value::Float(3.14159)));
assert_eq!(get_object_field(&obj, "neg"), Some(Value::Float(-2.5)));
assert_eq!(get_object_field(&obj, "zero"), Some(Value::Float(0.0)));
}
#[test]
fn test_negative_integers_in_object_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "neg", Value::Integer(-100)).unwrap();
set_object_field(&obj, "min", Value::Integer(i64::MIN)).unwrap();
set_object_field(&obj, "max", Value::Integer(i64::MAX)).unwrap();
assert_eq!(get_object_field(&obj, "neg"), Some(Value::Integer(-100)));
assert_eq!(
get_object_field(&obj, "min"),
Some(Value::Integer(i64::MIN))
);
assert_eq!(
get_object_field(&obj, "max"),
Some(Value::Integer(i64::MAX))
);
}
#[test]
fn test_string_values_in_object_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "empty", Value::from_string("".to_string())).unwrap();
set_object_field(&obj, "short", Value::from_string("a".to_string())).unwrap();
set_object_field(&obj, "long", Value::from_string("a".repeat(1000))).unwrap();
if let Some(Value::String(s)) = get_object_field(&obj, "empty") {
assert_eq!(s.as_ref(), "");
}
if let Some(Value::String(s)) = get_object_field(&obj, "long") {
assert_eq!(s.len(), 1000);
}
}
#[test]
fn test_field_overwrite_with_different_type_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "field", Value::Integer(42)).unwrap();
assert_eq!(get_object_field(&obj, "field"), Some(Value::Integer(42)));
set_object_field(&obj, "field", Value::from_string("hello".to_string())).unwrap();
if let Some(Value::String(s)) = get_object_field(&obj, "field") {
assert_eq!(s.as_ref(), "hello");
} else {
panic!("Expected string");
}
set_object_field(&obj, "field", Value::Bool(true)).unwrap();
assert_eq!(get_object_field(&obj, "field"), Some(Value::Bool(true)));
set_object_field(&obj, "field", Value::Nil).unwrap();
assert_eq!(get_object_field(&obj, "field"), Some(Value::Nil));
}
#[test]
fn test_to_mutable_on_string_value_r162() {
let string_val = Value::from_string("test".to_string());
let result = to_mutable(&string_val);
if let Value::String(s) = result {
assert_eq!(s.as_ref(), "test");
} else {
panic!("Expected string");
}
}
#[test]
fn test_to_immutable_on_array_value_r162() {
use std::sync::Arc;
let arr = Value::Array(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let result = to_immutable(&arr);
if let Value::Array(elems) = result {
assert_eq!(elems.len(), 2);
} else {
panic!("Expected array");
}
}
#[test]
fn test_to_mutable_on_bool_value_r162() {
let bool_val = Value::Bool(false);
let result = to_mutable(&bool_val);
assert_eq!(result, Value::Bool(false));
}
#[test]
fn test_to_immutable_on_bool_value_r162() {
let bool_val = Value::Bool(true);
let result = to_immutable(&bool_val);
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_to_mutable_on_nil_value_r162() {
let nil_val = Value::Nil;
let result = to_mutable(&nil_val);
assert_eq!(result, Value::Nil);
}
#[test]
fn test_to_immutable_on_nil_value_r162() {
let nil_val = Value::Nil;
let result = to_immutable(&nil_val);
assert_eq!(result, Value::Nil);
}
#[test]
fn test_to_mutable_on_tuple_value_r162() {
use std::sync::Arc;
let tuple = Value::Tuple(Arc::from(vec![Value::Integer(1)]));
let result = to_mutable(&tuple);
if let Value::Tuple(elems) = result {
assert_eq!(elems.len(), 1);
} else {
panic!("Expected tuple");
}
}
#[test]
fn test_to_immutable_on_tuple_value_r162() {
use std::sync::Arc;
let tuple = Value::Tuple(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let result = to_immutable(&tuple);
if let Value::Tuple(elems) = result {
assert_eq!(elems.len(), 2);
} else {
panic!("Expected tuple");
}
}
#[test]
fn test_is_mutable_object_on_nil_r162() {
assert!(!is_mutable_object(&Value::Nil));
}
#[test]
fn test_is_object_on_nil_r162() {
assert!(!is_object(&Value::Nil));
}
#[test]
fn test_get_field_from_array_r162() {
use std::sync::Arc;
let arr = Value::Array(Arc::from(vec![Value::Integer(1)]));
assert_eq!(get_object_field(&arr, "0"), None);
}
#[test]
fn test_get_field_from_tuple_r162() {
use std::sync::Arc;
let tuple = Value::Tuple(Arc::from(vec![Value::Integer(1)]));
assert_eq!(get_object_field(&tuple, "0"), None);
}
#[test]
fn test_set_field_on_array_r162() {
use std::sync::Arc;
let arr = Value::Array(Arc::from(vec![Value::Integer(1)]));
let err = set_object_field(&arr, "0", Value::Integer(2)).unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("non-object"));
}
#[test]
fn test_set_field_on_tuple_r162() {
use std::sync::Arc;
let tuple = Value::Tuple(Arc::from(vec![Value::Integer(1)]));
let err = set_object_field(&tuple, "0", Value::Integer(2)).unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("non-object"));
}
#[test]
fn test_set_field_on_string_r162() {
let s = Value::from_string("test".to_string());
let err = set_object_field(&s, "len", Value::Integer(4)).unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("non-object"));
}
#[test]
fn test_set_field_on_float_r162() {
let f = Value::Float(3.14);
let err = set_object_field(&f, "int_part", Value::Integer(3)).unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("non-object"));
}
#[test]
fn test_set_field_on_bool_r162() {
let b = Value::Bool(true);
let err = set_object_field(&b, "value", Value::Integer(1)).unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("non-object"));
}
#[test]
fn test_multiple_sequential_mutations_r162() {
let obj = new_mutable_object(HashMap::new());
for i in 0..20 {
set_object_field(&obj, &format!("field_{i}"), Value::Integer(i)).unwrap();
}
for i in 0..20 {
assert_eq!(
get_object_field(&obj, &format!("field_{i}")),
Some(Value::Integer(i))
);
}
for i in 0..20 {
set_object_field(&obj, &format!("field_{i}"), Value::Integer(i * 10)).unwrap();
}
for i in 0..20 {
assert_eq!(
get_object_field(&obj, &format!("field_{i}")),
Some(Value::Integer(i * 10))
);
}
}
#[test]
fn test_delete_field_by_setting_nil_r162() {
let obj = new_mutable_object(HashMap::from([
("a".to_string(), Value::Integer(1)),
("b".to_string(), Value::Integer(2)),
]));
set_object_field(&obj, "a", Value::Nil).unwrap();
assert_eq!(get_object_field(&obj, "a"), Some(Value::Nil));
assert_eq!(get_object_field(&obj, "b"), Some(Value::Integer(2)));
}
#[test]
fn test_field_name_with_newlines_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "field\nwith\nnewlines", Value::Integer(1)).unwrap();
assert_eq!(
get_object_field(&obj, "field\nwith\nnewlines"),
Some(Value::Integer(1))
);
}
#[test]
fn test_field_name_with_tabs_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "field\twith\ttabs", Value::Integer(2)).unwrap();
assert_eq!(
get_object_field(&obj, "field\twith\ttabs"),
Some(Value::Integer(2))
);
}
#[test]
fn test_field_name_with_quotes_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "field\"with\"quotes", Value::Integer(3)).unwrap();
assert_eq!(
get_object_field(&obj, "field\"with\"quotes"),
Some(Value::Integer(3))
);
}
#[test]
fn test_field_name_with_backslash_r162() {
let obj = new_mutable_object(HashMap::new());
set_object_field(&obj, "field\\with\\backslash", Value::Integer(4)).unwrap();
assert_eq!(
get_object_field(&obj, "field\\with\\backslash"),
Some(Value::Integer(4))
);
}
#[test]
fn test_very_long_field_name_r162() {
let obj = new_mutable_object(HashMap::new());
let long_name = "a".repeat(1000);
set_object_field(&obj, &long_name, Value::Integer(999)).unwrap();
assert_eq!(
get_object_field(&obj, &long_name),
Some(Value::Integer(999))
);
}
#[test]
fn test_mutable_object_clone_behavior_r162() {
let obj = new_mutable_object(HashMap::from([("x".to_string(), Value::Integer(10))]));
let cloned = obj.clone();
set_object_field(&obj, "x", Value::Integer(20)).unwrap();
assert_eq!(get_object_field(&cloned, "x"), Some(Value::Integer(20)));
}
#[test]
fn test_immutable_object_clone_behavior_r162() {
let obj = new_immutable_object(HashMap::from([("x".to_string(), Value::Integer(10))]));
let cloned = obj.clone();
assert_eq!(get_object_field(&cloned, "x"), Some(Value::Integer(10)));
}
#[test]
fn test_deeply_nested_objects_r162() {
let mut level5 = HashMap::new();
level5.insert("value".to_string(), Value::Integer(42));
let obj5 = new_immutable_object(level5);
let mut level4 = HashMap::new();
level4.insert("nested".to_string(), obj5);
let obj4 = new_immutable_object(level4);
let mut level3 = HashMap::new();
level3.insert("nested".to_string(), obj4);
let obj3 = new_immutable_object(level3);
let mut level2 = HashMap::new();
level2.insert("nested".to_string(), obj3);
let obj2 = new_immutable_object(level2);
let mut level1 = HashMap::new();
level1.insert("nested".to_string(), obj2);
let obj1 = new_immutable_object(level1);
let n1 = get_object_field(&obj1, "nested").unwrap();
let n2 = get_object_field(&n1, "nested").unwrap();
let n3 = get_object_field(&n2, "nested").unwrap();
let n4 = get_object_field(&n3, "nested").unwrap();
let final_val = get_object_field(&n4, "value").unwrap();
assert_eq!(final_val, Value::Integer(42));
}