cjc_runtime/buffer.rs
1use std::cell::{Ref, RefCell};
2use std::rc::Rc;
3
4use crate::error::RuntimeError;
5
6// ---------------------------------------------------------------------------
7// 1. Buffer<T> — Deterministic memory allocation with COW semantics
8// ---------------------------------------------------------------------------
9
10/// A reference-counted buffer with copy-on-write semantics.
11///
12/// Internally backed by `Rc<RefCell<Vec<T>>>`. When multiple `Buffer`s share
13/// the same underlying storage, a mutation via [`Buffer::set`] or
14/// [`Buffer::make_unique`] triggers a deep copy so that other holders are
15/// unaffected.
16#[derive(Debug)]
17pub struct Buffer<T: Clone> {
18 inner: Rc<RefCell<Vec<T>>>,
19}
20
21impl<T: Clone> Buffer<T> {
22 /// Allocate a buffer of `len` elements, each initialized to `default`.
23 pub fn alloc(len: usize, default: T) -> Self {
24 Buffer {
25 inner: Rc::new(RefCell::new(vec![default; len])),
26 }
27 }
28
29 /// Create a buffer from an existing `Vec<T>`.
30 pub fn from_vec(data: Vec<T>) -> Self {
31 Buffer {
32 inner: Rc::new(RefCell::new(data)),
33 }
34 }
35
36 /// Number of elements in the buffer.
37 pub fn len(&self) -> usize {
38 self.inner.borrow().len()
39 }
40
41 /// Whether the buffer is empty.
42 pub fn is_empty(&self) -> bool {
43 self.inner.borrow().is_empty()
44 }
45
46 /// Read the value at `idx`. Returns `None` if out of bounds.
47 pub fn get(&self, idx: usize) -> Option<T> {
48 self.inner.borrow().get(idx).cloned()
49 }
50
51 /// Write `val` at `idx`. If the buffer is shared (refcount > 1), a deep
52 /// copy is performed first (COW). Returns `Err` if `idx` is out of bounds.
53 pub fn set(&mut self, idx: usize, val: T) -> Result<(), RuntimeError> {
54 self.make_unique();
55 let mut vec = self.inner.borrow_mut();
56 if idx >= vec.len() {
57 return Err(RuntimeError::IndexOutOfBounds {
58 index: idx,
59 length: vec.len(),
60 });
61 }
62 vec[idx] = val;
63 Ok(())
64 }
65
66 /// Return a snapshot of the data as a `Vec<T>`.
67 pub fn as_slice(&self) -> Vec<T> {
68 self.inner.borrow().clone()
69 }
70
71 /// Borrow the underlying Vec without cloning.
72 /// The returned `Ref` guard keeps the borrow alive.
73 pub fn borrow_data(&self) -> Ref<Vec<T>> {
74 self.inner.borrow()
75 }
76
77 /// Force a deep copy, returning a new `Buffer` that does not share
78 /// storage with `self`.
79 pub fn clone_buffer(&self) -> Buffer<T> {
80 Buffer {
81 inner: Rc::new(RefCell::new(self.inner.borrow().clone())),
82 }
83 }
84
85 /// Ensure this `Buffer` has exclusive ownership of the underlying data.
86 /// If the refcount is > 1, the data is deep-copied and this `Buffer` is
87 /// re-pointed to the fresh copy.
88 pub fn make_unique(&mut self) {
89 if Rc::strong_count(&self.inner) > 1 {
90 let data = self.inner.borrow().clone();
91 self.inner = Rc::new(RefCell::new(data));
92 }
93 }
94
95 /// Number of live references to the underlying storage.
96 pub fn refcount(&self) -> usize {
97 Rc::strong_count(&self.inner)
98 }
99}
100
101impl<T: Clone> Clone for Buffer<T> {
102 /// Cloning a `Buffer` increments the refcount — it does NOT copy data.
103 fn clone(&self) -> Self {
104 Buffer {
105 inner: Rc::clone(&self.inner),
106 }
107 }
108}
109