mica_language/value/
lists.rs

1use std::cell::UnsafeCell;
2use std::cmp::Ordering;
3
4use crate::common::ErrorKind;
5
6use super::RawValue;
7
8/// A Mica list.
9pub struct List {
10   elements: UnsafeCell<Vec<RawValue>>,
11}
12
13impl List {
14   /// Creates a new, empty list.
15   pub fn new(elements: Vec<RawValue>) -> List {
16      List {
17         elements: UnsafeCell::new(elements),
18      }
19   }
20
21   /// Returns a mutable reference to the vector inside.
22   ///
23   /// # Safety
24   /// No references (mutable or not) to the vector must exist at the time of calling this.
25   pub unsafe fn get_mut(&self) -> *mut Vec<RawValue> {
26      self.elements.get()
27   }
28
29   /// Returns the items of the list as a slice.
30   ///
31   /// # Safety
32   /// There must be no mutable references to the list inside at the time of calling this.
33   pub(crate) unsafe fn as_slice(&self) -> &[RawValue] {
34      &*self.elements.get()
35   }
36
37   /// Attempts to compare two lists to each other lexicographically.
38   pub(crate) unsafe fn try_partial_cmp(
39      &self,
40      other: &List,
41   ) -> Result<Option<Ordering>, ErrorKind> {
42      let (left, right) = (self.as_slice(), other.as_slice());
43      let len = left.len().min(right.len());
44      let a = &left[..len];
45      let b = &right[..len];
46
47      for i in 0..len {
48         match a[i].try_partial_cmp(&b[i])? {
49            Some(Ordering::Equal) => (),
50            non_eq => return Ok(non_eq),
51         }
52      }
53
54      Ok(left.len().partial_cmp(&right.len()))
55   }
56}
57
58impl PartialEq for List {
59   fn eq(&self, other: &Self) -> bool {
60      (unsafe { &*self.elements.get() } == unsafe { &*other.elements.get() })
61   }
62}