sim_lib_mutation/
vector.rs1use std::sync::{Arc, RwLock};
2
3use sim_kernel::{Cx, Error, Expr, Object, ObjectCompat, Result, Value};
4
5use crate::standard_mutate_capability;
6
7#[sim_citizen_derive::non_citizen(
14 reason = "mutable vector handle; reconstruct from vector entries plus mutation policy",
15 kind = "handle",
16 descriptor = "core/Expr"
17)]
18pub struct MutableVector {
19 items: RwLock<Vec<Value>>,
20}
21
22impl MutableVector {
23 pub fn new(items: Vec<Value>) -> Self {
25 Self {
26 items: RwLock::new(items),
27 }
28 }
29
30 pub fn len(&self) -> Result<usize> {
32 Ok(self
33 .items
34 .read()
35 .map_err(|_| Error::PoisonedLock("mutation vector"))?
36 .len())
37 }
38
39 pub fn is_empty(&self) -> Result<bool> {
41 Ok(self.len()? == 0)
42 }
43
44 pub fn get(&self, index: usize) -> Result<Option<Value>> {
46 Ok(self
47 .items
48 .read()
49 .map_err(|_| Error::PoisonedLock("mutation vector"))?
50 .get(index)
51 .cloned())
52 }
53
54 pub fn set(&self, cx: &mut Cx, index: usize, value: Value) -> Result<()> {
58 cx.require(&standard_mutate_capability())?;
59 let mut items = self
60 .items
61 .write()
62 .map_err(|_| Error::PoisonedLock("mutation vector"))?;
63 let Some(slot) = items.get_mut(index) else {
64 return Err(Error::Eval(format!(
65 "mutable vector index {index} out of bounds"
66 )));
67 };
68 *slot = value;
69 Ok(())
70 }
71
72 pub fn push(&self, cx: &mut Cx, value: Value) -> Result<()> {
74 cx.require(&standard_mutate_capability())?;
75 self.items
76 .write()
77 .map_err(|_| Error::PoisonedLock("mutation vector"))?
78 .push(value);
79 Ok(())
80 }
81
82 pub fn to_vec(&self) -> Result<Vec<Value>> {
84 Ok(self
85 .items
86 .read()
87 .map_err(|_| Error::PoisonedLock("mutation vector"))?
88 .clone())
89 }
90}
91
92impl Object for MutableVector {
93 fn display(&self, _cx: &mut Cx) -> Result<String> {
94 Ok(format!("#<mutation-vector {}>", self.len()?))
95 }
96
97 fn as_any(&self) -> &dyn std::any::Any {
98 self
99 }
100}
101
102impl ObjectCompat for MutableVector {
103 fn as_expr(&self, cx: &mut Cx) -> Result<Expr> {
104 Ok(Expr::Vector(
105 self.to_vec()?
106 .iter()
107 .map(|value| value.object().as_expr(cx))
108 .collect::<Result<Vec<_>>>()?,
109 ))
110 }
111}
112
113pub fn mutable_vector(cx: &mut Cx, items: Vec<Value>) -> Result<Value> {
115 cx.factory().opaque(Arc::new(MutableVector::new(items)))
116}
117
118pub fn mutable_vector_from_value(cx: &mut Cx, value: &Value) -> Result<Value> {
123 let expr = value.object().as_expr(cx)?;
124 let Expr::Vector(items) = expr else {
125 return Err(Error::TypeMismatch {
126 expected: "vector expression",
127 found: "non-vector",
128 });
129 };
130 let mut values = Vec::with_capacity(items.len());
131 for item in items {
132 values.push(cx.factory().expr(item)?);
133 }
134 mutable_vector(cx, values)
135}
136
137pub fn mutable_vector_value(value: &Value) -> Result<&MutableVector> {
139 value
140 .object()
141 .downcast_ref::<MutableVector>()
142 .ok_or(Error::TypeMismatch {
143 expected: "mutable vector",
144 found: "non-vector",
145 })
146}