Skip to main content

scheme_rs/
vectors.rs

1//! Growable mutable vectors.
2
3#[cfg(target_endian = "little")]
4use crate::symbols::Symbol;
5use crate::{
6    exceptions::Exception,
7    gc::{Gc, Trace},
8    lists::{List, slice_to_list},
9    registry::bridge,
10    value::{Value, ValueType, write_value},
11};
12use indexmap::IndexMap;
13use parking_lot::{
14    MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
15};
16use std::{clone::Clone, fmt, hash::Hash, ops::Range, sync::Arc};
17
18#[derive(Trace)]
19#[repr(align(16))]
20pub(crate) struct VectorInner<T: Trace> {
21    /// Inner vector.
22    pub(crate) vec: RwLock<Vec<T>>,
23    /// Whether or not the vector is mutable
24    pub(crate) mutable: bool,
25}
26
27/// A vector of values
28#[derive(Clone, Trace)]
29pub struct Vector(pub(crate) Gc<VectorInner<Value>>);
30
31impl Vector {
32    pub fn immutable(vec: Vec<Value>) -> Self {
33        Self::from(vec)
34    }
35
36    pub fn mutable(vec: Vec<Value>) -> Self {
37        Self(Gc::new(VectorInner {
38            vec: RwLock::new(vec),
39            mutable: true,
40        }))
41    }
42
43    pub fn get(&self, index: usize) -> Option<Value> {
44        let handle = self.0.vec.read();
45        handle.get(index).cloned()
46    }
47
48    pub fn first(&self) -> Option<Value> {
49        let handle = self.0.vec.read();
50        handle.first().cloned()
51    }
52
53    pub fn last(&self) -> Option<Value> {
54        let handle = self.0.vec.read();
55        handle.last().cloned()
56    }
57
58    // TODO: Add more convenience functions here
59
60    pub fn to_list(&self) -> Value {
61        slice_to_list(&self.0.vec.read())
62    }
63
64    pub fn clone_inner_vec(&self) -> Vec<Value> {
65        self.0.vec.read().clone()
66    }
67
68    pub fn iter(&self) -> impl Iterator<Item = Value> {
69        self.0.vec.read().clone().into_iter()
70    }
71
72    pub fn is_empty(&self) -> bool {
73        self.0.vec.read().is_empty()
74    }
75}
76
77impl From<Vec<Value>> for Vector {
78    fn from(vec: Vec<Value>) -> Self {
79        Self(Gc::new(VectorInner {
80            vec: RwLock::new(vec),
81            mutable: false,
82        }))
83    }
84}
85
86/// A vector of bytes
87#[derive(Clone, Trace)]
88pub struct ByteVector(pub(crate) Arc<VectorInner<u8>>);
89
90impl ByteVector {
91    pub fn immutable(vec: Vec<u8>) -> Self {
92        Self::from(vec)
93    }
94
95    pub fn mutable(vec: Vec<u8>) -> Self {
96        Self(Arc::new(VectorInner {
97            vec: RwLock::new(vec),
98            mutable: true,
99        }))
100    }
101
102    pub fn as_slice(&self) -> MappedRwLockReadGuard<'_, [u8]> {
103        RwLockReadGuard::map(self.0.vec.read(), |vec| vec.as_slice())
104    }
105
106    pub fn as_mut_slice(&self) -> Result<MappedRwLockWriteGuard<'_, [u8]>, Exception> {
107        if self.0.mutable {
108            Ok(RwLockWriteGuard::map(self.0.vec.write(), |vec| {
109                vec.as_mut_slice()
110            }))
111        } else {
112            Err(Exception::error("bytevector is not mutable"))
113        }
114    }
115
116    pub fn as_mut_vec(&self) -> Result<RwLockWriteGuard<'_, Vec<u8>>, Exception> {
117        if self.0.mutable {
118            Ok(self.0.vec.write())
119        } else {
120            Err(Exception::error("bytevector is not mutable"))
121        }
122    }
123
124    pub fn is_empty(&self) -> bool {
125        self.len() == 0
126    }
127
128    pub fn len(&self) -> usize {
129        self.0.vec.read().len()
130    }
131
132    pub fn clear(&self) -> Result<(), Exception> {
133        if self.0.mutable {
134            self.0.vec.write().clear();
135            Ok(())
136        } else {
137            Err(Exception::error("bytevector is not mutable"))
138        }
139    }
140
141    pub fn get(&self, idx: usize) -> Option<u8> {
142        self.0.vec.read().get(idx).copied()
143    }
144}
145
146impl From<Vec<u8>> for ByteVector {
147    fn from(vec: Vec<u8>) -> Self {
148        Self(Arc::new(VectorInner {
149            vec: RwLock::new(vec),
150            mutable: false,
151        }))
152    }
153}
154
155impl Hash for ByteVector {
156    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
157        self.0.vec.read().hash(state)
158    }
159}
160
161impl PartialEq<[u8]> for ByteVector {
162    fn eq(&self, rhs: &[u8]) -> bool {
163        *self.0.vec.read() == rhs
164    }
165}
166
167impl PartialEq for ByteVector {
168    fn eq(&self, rhs: &Self) -> bool {
169        *self.0.vec.read() == *rhs.0.vec.read()
170    }
171}
172
173pub(crate) fn write_vec(
174    v: &Vector,
175    fmt: fn(&Value, &mut IndexMap<Value, bool>, &mut fmt::Formatter<'_>) -> fmt::Result,
176    circular_values: &mut IndexMap<Value, bool>,
177    f: &mut fmt::Formatter<'_>,
178) -> Result<(), fmt::Error> {
179    write!(f, "#(")?;
180
181    let values = v.0.vec.read();
182
183    for (i, value) in values.iter().enumerate() {
184        if i > 0 {
185            write!(f, " ")?;
186        }
187        write_value(value, fmt, circular_values, f)?;
188    }
189
190    write!(f, ")")
191}
192
193pub(crate) fn write_bytevec(v: &ByteVector, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
194    write!(f, "#vu8(")?;
195
196    let bytes = v.0.vec.read();
197    for (i, byte) in bytes.iter().enumerate() {
198        if i > 0 {
199            write!(f, " ")?;
200        }
201        write!(f, "{byte}")?;
202    }
203
204    write!(f, ")")
205}
206
207fn try_make_range(start: usize, end: usize) -> Result<Range<usize>, Exception> {
208    if end < start {
209        Err(Exception::error(format!(
210            "range end {end} is less than start {start}",
211        )))
212    } else {
213        Ok(start..end)
214    }
215}
216
217trait Indexer {
218    type Collection: TryFrom<Value, Error = Exception>;
219
220    fn get_len(_: &Self::Collection) -> usize;
221
222    fn get_range(_: &Self::Collection, _: Range<usize>) -> Self::Collection;
223
224    fn index(from: &Value, range: &[Value]) -> Result<Self::Collection, Exception> {
225        let collection = Self::Collection::try_from(from.clone())?;
226        let len = Self::get_len(&collection);
227
228        let start: usize = range
229            .first()
230            .cloned()
231            .map(Value::try_into)
232            .transpose()?
233            .unwrap_or(0);
234        let end: usize = range
235            .get(1)
236            .cloned()
237            .map(Value::try_into)
238            .transpose()?
239            .unwrap_or(len);
240
241        let range = try_make_range(start, end)?;
242        if range.end > len {
243            return Err(Exception::invalid_range(range, len));
244        }
245
246        Ok(Self::get_range(&collection, range))
247    }
248}
249
250struct VectorIndexer;
251
252impl Indexer for VectorIndexer {
253    // type Collection = Gc<RwLock<AlignedVector<Value>>>;
254    type Collection = Vector;
255
256    fn get_len(vec: &Self::Collection) -> usize {
257        vec.0.vec.read().len()
258    }
259
260    fn get_range(vec: &Self::Collection, range: Range<usize>) -> Self::Collection {
261        let subvec: Vec<Value> = vec
262            .0
263            .vec
264            .read()
265            .iter()
266            .skip(range.start)
267            .take(range.end - range.start)
268            .cloned()
269            .collect();
270        Vector(Gc::new(VectorInner {
271            vec: RwLock::new(subvec),
272            mutable: true,
273        }))
274    }
275}
276
277#[bridge(name = "make-vector", lib = "(rnrs base builtins (6))")]
278pub fn make_vector(n: &Value, with: &[Value]) -> Result<Vec<Value>, Exception> {
279    let n: usize = n.try_to_scheme_type()?;
280
281    Ok(vec![Value::from(Vector(Gc::new(VectorInner {
282        vec: RwLock::new(
283            (0..n)
284                .map(|_| with.first().cloned().unwrap_or_else(Value::null))
285                .collect::<Vec<_>>(),
286        ),
287        mutable: true,
288    })))])
289}
290
291#[bridge(name = "vector", lib = "(rnrs base builtins (6))")]
292pub fn vector(args: &[Value]) -> Result<Vec<Value>, Exception> {
293    Ok(vec![Value::from(Vector(Gc::new(VectorInner {
294        vec: RwLock::new(args.to_vec()),
295        mutable: true,
296    })))])
297}
298
299#[bridge(name = "vector-ref", lib = "(rnrs base builtins (6))")]
300pub fn vector_ref(vec: &Value, index: &Value) -> Result<Vec<Value>, Exception> {
301    let vec: Vector = vec.clone().try_into()?;
302    let index: usize = index.clone().try_into()?;
303    let vec_read = vec.0.vec.read();
304
305    Ok(vec![
306        vec_read
307            .get(index)
308            .ok_or_else(|| Exception::invalid_index(index, vec_read.len()))?
309            .clone(),
310    ])
311}
312
313#[bridge(name = "vector-length", lib = "(rnrs base builtins (6))")]
314pub fn vector_len(vec: &Value) -> Result<Vec<Value>, Exception> {
315    let vec: Vector = vec.clone().try_into()?;
316    let len = vec.0.vec.read().len();
317
318    Ok(vec![Value::from(len)])
319}
320
321#[bridge(name = "bytevector-length", lib = "(rnrs base builtins (6))")]
322pub fn bytevector_len(vec: &Value) -> Result<Vec<Value>, Exception> {
323    let vec: ByteVector = vec.clone().try_into()?;
324    let len = vec.0.vec.read().len();
325
326    Ok(vec![Value::from(len)])
327}
328
329#[bridge(name = "vector-set!", lib = "(rnrs base builtins (6))")]
330pub fn vector_set_bang(vec: &Value, index: &Value, with: &Value) -> Result<Vec<Value>, Exception> {
331    let vec: Vector = vec.clone().try_into()?;
332
333    if !vec.0.mutable {
334        return Err(Exception::error("vector is immutable"));
335    }
336
337    let mut vec_write = vec.0.vec.write();
338    let vec_len = vec_write.len();
339    let index: usize = index.clone().try_into()?;
340
341    *vec_write
342        .get_mut(index)
343        .ok_or_else(|| Exception::invalid_index(index, vec_len))? = with.clone();
344
345    Ok(vec![])
346}
347
348#[bridge(name = "vector->list", lib = "(rnrs base builtins (6))")]
349pub fn vector_to_list(from: &Value, range: &[Value]) -> Result<Vec<Value>, Exception> {
350    let vec = VectorIndexer::index(from, range)?;
351    let vec_read = vec.0.vec.read();
352    Ok(vec![slice_to_list(&vec_read)])
353}
354
355#[bridge(name = "vector->string", lib = "(rnrs base builtins (6))")]
356pub fn vector_to_string(from: &Value, range: &[Value]) -> Result<Vec<Value>, Exception> {
357    let vec = VectorIndexer::index(from, range)?;
358    let vec_read = vec.0.vec.read();
359    Ok(vec![Value::from(
360        vec_read
361            .iter()
362            .cloned()
363            .map(<Value as TryInto<char>>::try_into)
364            .collect::<Result<String, _>>()?,
365    )])
366}
367
368#[bridge(name = "vector-copy", lib = "(rnrs base builtins (6))")]
369pub fn vector_copy(from: &Value, range: &[Value]) -> Result<Vec<Value>, Exception> {
370    Ok(vec![Value::from(VectorIndexer::index(from, range)?)])
371}
372
373#[bridge(name = "vector-copy!", lib = "(rnrs base builtins (6))")]
374pub fn vector_copy_to(
375    to: &Value,
376    at: &Value,
377    from: &Value,
378    range: &[Value],
379) -> Result<Vec<Value>, Exception> {
380    let to: Vector = to.clone().try_into()?;
381    let mut to = to.0.vec.write();
382
383    let at: usize = at.clone().try_into()?;
384
385    if at >= to.len() {
386        return Err(Exception::invalid_index(at, to.len()));
387    }
388
389    let copies = VectorIndexer::index(from, range)?;
390    let copies = copies.0.vec.read();
391    if copies.len() + at >= to.len() {
392        return Err(Exception::invalid_range(at..at + copies.len(), to.len()));
393    }
394
395    copies
396        .iter()
397        .enumerate()
398        .map(|(i, copy)| (i + at, copy))
399        .for_each(|(i, copy)| {
400            if let Some(i) = to.get_mut(i) {
401                *i = copy.clone();
402            }
403        });
404
405    Ok(Vec::new())
406}
407
408#[bridge(name = "vector-append", lib = "(rnrs base builtins (6))")]
409pub fn vector_append(args: &[Value]) -> Result<Vec<Value>, Exception> {
410    if args.is_empty() {
411        return Err(Exception::wrong_num_of_var_args(1..usize::MAX, 0));
412    }
413
414    Ok(vec![Value::from(
415        args.iter()
416            .map(|arg| {
417                let vec: Vector = arg.clone().try_into()?;
418                let vec_read = vec.0.vec.read();
419                Ok(vec_read.clone())
420            })
421            .collect::<Result<Vec<_>, Exception>>()?
422            .into_iter()
423            .flatten()
424            .collect::<Vec<_>>(),
425    )])
426}
427
428#[bridge(name = "vector-fill!", lib = "(rnrs base builtins (6))")]
429pub fn vector_fill(
430    vector: &Value,
431    with: &Value,
432    start: &Value,
433    end: &[Value],
434) -> Result<Vec<Value>, Exception> {
435    let vector: Vector = vector.clone().try_into()?;
436    let mut vector = vector.0.vec.write();
437
438    let start: usize = start.clone().try_into()?;
439    let end = match end.first() {
440        Some(end) => end.clone().try_into()?,
441        None => vector.len(),
442    };
443
444    let range = try_make_range(start, end)?;
445    if range.end > vector.len() {
446        return Err(Exception::invalid_range(range, vector.len()));
447    }
448
449    range.for_each(|i| {
450        if let Some(slot) = vector.get_mut(i) {
451            *slot = with.clone()
452        }
453    });
454
455    Ok(vec![])
456}
457
458#[bridge(name = "native-endianness", lib = "(rnrs bytevectors (6))")]
459pub fn native_endianness() -> Result<Vec<Value>, Exception> {
460    #[cfg(target_endian = "little")]
461    {
462        Ok(vec![Value::from(Symbol::intern("little"))])
463    }
464    #[cfg(target_endian = "big")]
465    {
466        Ok(vec![Value::from(Symbol::intern("big"))])
467    }
468}
469
470#[bridge(name = "bytevector?", lib = "(rnrs bytevectors (6))")]
471pub fn bytevector_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
472    Ok(vec![Value::from(arg.type_of() == ValueType::ByteVector)])
473}
474
475#[bridge(name = "make-bytevector", lib = "(rnrs bytevectors (6))")]
476pub fn make_bytevector(k: usize, fill: &[Value]) -> Result<Vec<Value>, Exception> {
477    let fill: u8 = match fill {
478        [] => 0u8,
479        [fill] => fill.try_into()?,
480        _ => return Err(Exception::wrong_num_of_var_args(1..2, 1 + fill.len())),
481    };
482    Ok(vec![Value::from(ByteVector::mutable(vec![fill; k]))])
483}
484
485#[bridge(name = "bytevector-length", lib = "(rnrs bytevectors (6))")]
486pub fn bytevector_length(bytevector: ByteVector) -> Result<Vec<Value>, Exception> {
487    Ok(vec![Value::from(bytevector.len())])
488}
489
490#[bridge(name = "bytevector=?", lib = "(rnrs bytevectors (6))")]
491pub fn bytevector_equal_pred(lhs: ByteVector, rhs: ByteVector) -> Result<Vec<Value>, Exception> {
492    Ok(vec![Value::from(lhs == rhs)])
493}
494
495#[bridge(name = "bytevector-u8-ref", lib = "(rnrs bytevectors (6))")]
496pub fn bytevector_u8_ref(bytevector: ByteVector, k: usize) -> Result<Vec<Value>, Exception> {
497    Ok(vec![Value::from(bytevector.get(k).ok_or_else(|| {
498        Exception::invalid_index(k, bytevector.len())
499    })?)])
500}
501
502#[bridge(name = "bytevector-u8-set!", lib = "(rnrs bytevectors (6))")]
503pub fn bytevector_u8_set(
504    bytevector: ByteVector,
505    k: usize,
506    octet: u8,
507) -> Result<Vec<Value>, Exception> {
508    let mut slice = bytevector.as_mut_slice()?;
509    let len = slice.len();
510    *slice
511        .get_mut(k)
512        .ok_or_else(|| Exception::invalid_index(k, len))? = octet;
513    Ok(Vec::new())
514}
515
516#[bridge(name = "u8-list->bytevector", lib = "(rnrs bytevectors (6))")]
517pub fn u8_list_to_bytevector(list: List) -> Result<Vec<Value>, Exception> {
518    Ok(vec![Value::from(ByteVector::mutable(
519        list.into_iter()
520            .map(u8::try_from)
521            .collect::<Result<Vec<_>, _>>()?,
522    ))])
523}
524
525#[bridge(name = "bytevector-push!", lib = "(rnrs bytevectors (6))")]
526pub fn bytevector_push(bytevector: ByteVector, byte: u8) -> Result<Vec<Value>, Exception> {
527    bytevector.as_mut_vec()?.push(byte);
528    Ok(vec![])
529}
530
531#[bridge(name = "bytevector-insert!", lib = "(rnrs bytevectors (6))")]
532pub fn bytevector_insert(
533    bytevector: ByteVector,
534    idx: usize,
535    byte: u8,
536) -> Result<Vec<Value>, Exception> {
537    let mut bv = bytevector.as_mut_vec()?;
538    if idx > bv.len() {
539        return Err(Exception::invalid_index(idx, bv.len()));
540    } else {
541        bv.insert(idx, byte);
542    }
543    Ok(vec![])
544}
545
546#[bridge(name = "bytevector-take!", lib = "(rnrs bytevectors (6))")]
547pub fn bytevector_take(bytevector: ByteVector) -> Result<Vec<Value>, Exception> {
548    Ok(vec![Value::from(ByteVector::mutable(std::mem::take(
549        &mut *bytevector.as_mut_vec()?,
550    )))])
551}