1use std::sync::{Arc, RwLock};
2
3use sim_kernel::{Cx, Error, Object, ObjectCompat, Result, Value};
4
5use crate::standard_mutate_capability;
6
7#[sim_citizen_derive::non_citizen(
33 reason = "mutable cell handle; reconstruct from the current value plus mutation policy",
34 kind = "handle",
35 descriptor = "core/Expr"
36)]
37#[derive(Clone)]
38pub struct Cell {
39 value: Arc<RwLock<Value>>,
40}
41
42impl Cell {
43 pub fn new(value: Value) -> Self {
45 Self {
46 value: Arc::new(RwLock::new(value)),
47 }
48 }
49
50 pub fn get(&self) -> Result<Value> {
52 Ok(self
53 .value
54 .read()
55 .map_err(|_| Error::PoisonedLock("mutation cell"))?
56 .clone())
57 }
58
59 pub fn set(&self, cx: &mut Cx, value: Value) -> Result<()> {
61 cx.require(&standard_mutate_capability())?;
62 *self
63 .value
64 .write()
65 .map_err(|_| Error::PoisonedLock("mutation cell"))? = value;
66 Ok(())
67 }
68}
69
70impl Object for Cell {
71 fn display(&self, _cx: &mut Cx) -> Result<String> {
72 Ok("#<mutation-cell>".to_owned())
73 }
74
75 fn as_any(&self) -> &dyn std::any::Any {
76 self
77 }
78}
79
80impl ObjectCompat for Cell {}
81
82#[sim_citizen_derive::non_citizen(
87 reason = "mutable box handle; reconstruct from the current value plus mutation policy",
88 kind = "handle",
89 descriptor = "core/Expr"
90)]
91#[derive(Clone)]
92pub struct MutableBox {
93 cell: Cell,
94}
95
96impl MutableBox {
97 pub fn new(value: Value) -> Self {
99 Self {
100 cell: Cell::new(value),
101 }
102 }
103
104 pub fn get(&self) -> Result<Value> {
106 self.cell.get()
107 }
108
109 pub fn set(&self, cx: &mut Cx, value: Value) -> Result<()> {
111 self.cell.set(cx, value)
112 }
113}
114
115impl Object for MutableBox {
116 fn display(&self, _cx: &mut Cx) -> Result<String> {
117 Ok("#<mutation-box>".to_owned())
118 }
119
120 fn as_any(&self) -> &dyn std::any::Any {
121 self
122 }
123}
124
125impl ObjectCompat for MutableBox {}
126
127pub fn cell_value(cx: &mut Cx, value: Value) -> Result<Value> {
129 cx.factory().opaque(Arc::new(Cell::new(value)))
130}
131
132pub fn mutable_box_value(cx: &mut Cx, value: Value) -> Result<Value> {
134 cx.factory().opaque(Arc::new(MutableBox::new(value)))
135}