1use std::cell::RefCell;
23use std::hash::Hash;
24use std::rc::Rc;
25
26pub type Nat = u64;
28pub type Int = i64;
30pub type Real = f64;
32pub type Text = String;
34pub type Bool = bool;
36pub type Unit = ();
38pub type Char = char;
40pub type Byte = u8;
42
43#[derive(Debug)]
49pub struct LogosSeq<T>(pub Rc<RefCell<Vec<T>>>);
50
51impl<T> LogosSeq<T> {
52 pub fn new() -> Self {
53 Self(Rc::new(RefCell::new(Vec::new())))
54 }
55
56 pub fn from_vec(v: Vec<T>) -> Self {
57 Self(Rc::new(RefCell::new(v)))
58 }
59
60 pub fn with_capacity(cap: usize) -> Self {
61 Self(Rc::new(RefCell::new(Vec::with_capacity(cap))))
62 }
63
64 pub fn push(&self, value: T) {
65 self.0.borrow_mut().push(value);
66 }
67
68 pub fn pop(&self) -> Option<T> {
69 self.0.borrow_mut().pop()
70 }
71
72 pub fn len(&self) -> usize {
73 self.0.borrow().len()
74 }
75
76 pub fn is_empty(&self) -> bool {
77 self.0.borrow().is_empty()
78 }
79
80 pub fn remove(&self, index: usize) -> T {
81 self.0.borrow_mut().remove(index)
82 }
83
84 pub fn borrow(&self) -> std::cell::Ref<'_, Vec<T>> {
85 self.0.borrow()
86 }
87
88 pub fn borrow_mut(&self) -> std::cell::RefMut<'_, Vec<T>> {
89 self.0.borrow_mut()
90 }
91}
92
93impl<T: Clone> LogosSeq<T> {
94 pub fn deep_clone(&self) -> Self {
95 Self(Rc::new(RefCell::new(self.0.borrow().clone())))
96 }
97
98 pub fn to_vec(&self) -> Vec<T> {
99 self.0.borrow().clone()
100 }
101
102 pub fn extend_from_slice(&self, other: &[T]) {
103 self.0.borrow_mut().extend_from_slice(other);
104 }
105
106 pub fn iter(&self) -> LogosSeqIter<T> {
107 LogosSeqIter {
108 data: self.to_vec(),
109 pos: 0,
110 }
111 }
112}
113
114pub struct LogosSeqIter<T> {
115 data: Vec<T>,
116 pos: usize,
117}
118
119impl<T: Clone> Iterator for LogosSeqIter<T> {
120 type Item = T;
121 fn next(&mut self) -> Option<T> {
122 if self.pos < self.data.len() {
123 let val = self.data[self.pos].clone();
124 self.pos += 1;
125 Some(val)
126 } else {
127 None
128 }
129 }
130}
131
132impl<T: Ord> LogosSeq<T> {
133 pub fn sort(&self) {
134 self.0.borrow_mut().sort();
135 }
136}
137
138impl<T> LogosSeq<T> {
139 pub fn reverse(&self) {
140 self.0.borrow_mut().reverse();
141 }
142}
143
144impl<T> Clone for LogosSeq<T> {
145 fn clone(&self) -> Self {
146 Self(Rc::clone(&self.0))
147 }
148}
149
150impl<T> Default for LogosSeq<T> {
151 fn default() -> Self {
152 Self::new()
153 }
154}
155
156impl<T: PartialEq> PartialEq for LogosSeq<T> {
157 fn eq(&self, other: &Self) -> bool {
158 *self.0.borrow() == *other.0.borrow()
159 }
160}
161
162impl<T: std::fmt::Display> std::fmt::Display for LogosSeq<T> {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 let inner = self.0.borrow();
165 write!(f, "[")?;
166 for (i, item) in inner.iter().enumerate() {
167 if i > 0 { write!(f, ", ")?; }
168 write!(f, "{}", item)?;
169 }
170 write!(f, "]")
171 }
172}
173
174impl<T: PartialEq> LogosContains<T> for LogosSeq<T> {
175 #[inline(always)]
176 fn logos_contains(&self, value: &T) -> bool {
177 self.0.borrow().contains(value)
178 }
179}
180
181impl<T: Clone> IntoIterator for LogosSeq<T> {
182 type Item = T;
183 type IntoIter = std::vec::IntoIter<T>;
184
185 fn into_iter(self) -> Self::IntoIter {
186 self.to_vec().into_iter()
187 }
188}
189
190#[derive(Debug)]
196pub struct LogosMap<K, V>(pub Rc<RefCell<rustc_hash::FxHashMap<K, V>>>);
197
198impl<K: Eq + Hash, V> LogosMap<K, V> {
199 pub fn new() -> Self {
200 Self(Rc::new(RefCell::new(rustc_hash::FxHashMap::default())))
201 }
202
203 pub fn with_capacity(cap: usize) -> Self {
204 Self(Rc::new(RefCell::new(
205 rustc_hash::FxHashMap::with_capacity_and_hasher(cap, Default::default()),
206 )))
207 }
208
209 pub fn from_map(m: rustc_hash::FxHashMap<K, V>) -> Self {
210 Self(Rc::new(RefCell::new(m)))
211 }
212
213 pub fn insert(&self, key: K, value: V) -> Option<V> {
214 self.0.borrow_mut().insert(key, value)
215 }
216
217 pub fn remove(&self, key: &K) -> Option<V> {
218 self.0.borrow_mut().remove(key)
219 }
220
221 pub fn len(&self) -> usize {
222 self.0.borrow().len()
223 }
224
225 pub fn is_empty(&self) -> bool {
226 self.0.borrow().is_empty()
227 }
228
229 pub fn contains_key(&self, key: &K) -> bool {
230 self.0.borrow().contains_key(key)
231 }
232
233 pub fn borrow(&self) -> std::cell::Ref<'_, rustc_hash::FxHashMap<K, V>> {
234 self.0.borrow()
235 }
236
237 pub fn borrow_mut(&self) -> std::cell::RefMut<'_, rustc_hash::FxHashMap<K, V>> {
238 self.0.borrow_mut()
239 }
240}
241
242impl<K: Eq + Hash + Clone, V: Clone> LogosMap<K, V> {
243 pub fn deep_clone(&self) -> Self {
244 Self(Rc::new(RefCell::new(self.0.borrow().clone())))
245 }
246
247 pub fn get(&self, key: &K) -> Option<V> {
248 self.0.borrow().get(key).cloned()
249 }
250}
251
252impl<K, V> Clone for LogosMap<K, V> {
253 fn clone(&self) -> Self {
254 Self(Rc::clone(&self.0))
255 }
256}
257
258impl<K: Eq + Hash, V> Default for LogosMap<K, V> {
259 fn default() -> Self {
260 Self::new()
261 }
262}
263
264impl<K: PartialEq + Eq + Hash, V: PartialEq> PartialEq for LogosMap<K, V> {
265 fn eq(&self, other: &Self) -> bool {
266 *self.0.borrow() == *other.0.borrow()
267 }
268}
269
270impl<K: std::fmt::Display + Eq + Hash, V: std::fmt::Display> std::fmt::Display for LogosMap<K, V> {
271 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
272 let inner = self.0.borrow();
273 write!(f, "{{")?;
274 for (i, (k, v)) in inner.iter().enumerate() {
275 if i > 0 { write!(f, ", ")?; }
276 write!(f, "{}: {}", k, v)?;
277 }
278 write!(f, "}}")
279 }
280}
281
282impl<K: Eq + Hash, V> LogosContains<K> for LogosMap<K, V> {
283 #[inline(always)]
284 fn logos_contains(&self, key: &K) -> bool {
285 self.0.borrow().contains_key(key)
286 }
287}
288
289pub type Seq<T> = LogosSeq<T>;
291
292pub type Map<K, V> = LogosMap<K, V>;
294
295pub type Set<T> = rustc_hash::FxHashSet<T>;
297
298pub trait LogosContains<T> {
331 fn logos_contains(&self, value: &T) -> bool;
333}
334
335impl<T: PartialEq> LogosContains<T> for Vec<T> {
336 #[inline(always)]
337 fn logos_contains(&self, value: &T) -> bool {
338 self.contains(value)
339 }
340}
341
342impl<T: PartialEq> LogosContains<T> for [T] {
343 #[inline(always)]
344 fn logos_contains(&self, value: &T) -> bool {
345 self.contains(value)
346 }
347}
348
349impl<T: Eq + Hash> LogosContains<T> for rustc_hash::FxHashSet<T> {
350 #[inline(always)]
351 fn logos_contains(&self, value: &T) -> bool {
352 self.contains(value)
353 }
354}
355
356impl<K: Eq + Hash, V> LogosContains<K> for rustc_hash::FxHashMap<K, V> {
357 #[inline(always)]
358 fn logos_contains(&self, key: &K) -> bool {
359 self.contains_key(key)
360 }
361}
362
363impl LogosContains<&str> for String {
364 #[inline(always)]
365 fn logos_contains(&self, value: &&str) -> bool {
366 self.contains(*value)
367 }
368}
369
370impl LogosContains<String> for String {
371 #[inline(always)]
372 fn logos_contains(&self, value: &String) -> bool {
373 self.contains(value.as_str())
374 }
375}
376
377impl LogosContains<char> for String {
378 #[inline(always)]
379 fn logos_contains(&self, value: &char) -> bool {
380 self.contains(*value)
381 }
382}
383
384impl<T: Eq + Hash + Clone, B: crate::crdt::SetBias> LogosContains<T>
385 for crate::crdt::ORSet<T, B>
386{
387 #[inline(always)]
388 fn logos_contains(&self, value: &T) -> bool {
389 self.contains(value)
390 }
391}
392
393#[derive(Clone, Debug, PartialEq)]
434pub enum Value {
435 Int(i64),
437 Float(f64),
439 Bool(bool),
441 Text(String),
443 Char(char),
445 Nothing,
447}
448
449impl std::fmt::Display for Value {
450 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
451 match self {
452 Value::Int(n) => write!(f, "{}", n),
453 Value::Float(n) => write!(f, "{}", n),
454 Value::Bool(b) => write!(f, "{}", b),
455 Value::Text(s) => write!(f, "{}", s),
456 Value::Char(c) => write!(f, "{}", c),
457 Value::Nothing => write!(f, "nothing"),
458 }
459 }
460}
461
462impl From<i64> for Value {
464 fn from(n: i64) -> Self { Value::Int(n) }
465}
466
467impl From<f64> for Value {
468 fn from(n: f64) -> Self { Value::Float(n) }
469}
470
471impl From<bool> for Value {
472 fn from(b: bool) -> Self { Value::Bool(b) }
473}
474
475impl From<String> for Value {
476 fn from(s: String) -> Self { Value::Text(s) }
477}
478
479impl From<&str> for Value {
480 fn from(s: &str) -> Self { Value::Text(s.to_string()) }
481}
482
483impl From<char> for Value {
484 fn from(c: char) -> Self { Value::Char(c) }
485}
486
487pub type Tuple = Vec<Value>;
489
490impl std::ops::Add for Value {
495 type Output = Value;
496
497 #[inline]
498 fn add(self, other: Value) -> Value {
499 match (self, other) {
500 (Value::Int(a), Value::Int(b)) => Value::Int(a + b),
501 (Value::Float(a), Value::Float(b)) => Value::Float(a + b),
502 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 + b),
503 (Value::Float(a), Value::Int(b)) => Value::Float(a + b as f64),
504 (Value::Text(a), Value::Text(b)) => Value::Text(format!("{}{}", a, b)),
505 _ => panic!("Cannot add these value types"),
506 }
507 }
508}
509
510impl std::ops::Sub for Value {
511 type Output = Value;
512
513 #[inline]
514 fn sub(self, other: Value) -> Value {
515 match (self, other) {
516 (Value::Int(a), Value::Int(b)) => Value::Int(a - b),
517 (Value::Float(a), Value::Float(b)) => Value::Float(a - b),
518 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 - b),
519 (Value::Float(a), Value::Int(b)) => Value::Float(a - b as f64),
520 _ => panic!("Cannot subtract these value types"),
521 }
522 }
523}
524
525impl std::ops::Mul for Value {
526 type Output = Value;
527
528 #[inline]
529 fn mul(self, other: Value) -> Value {
530 match (self, other) {
531 (Value::Int(a), Value::Int(b)) => Value::Int(a * b),
532 (Value::Float(a), Value::Float(b)) => Value::Float(a * b),
533 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 * b),
534 (Value::Float(a), Value::Int(b)) => Value::Float(a * b as f64),
535 _ => panic!("Cannot multiply these value types"),
536 }
537 }
538}
539
540impl std::ops::Div for Value {
541 type Output = Value;
542
543 #[inline]
544 fn div(self, other: Value) -> Value {
545 match (self, other) {
546 (Value::Int(a), Value::Int(b)) => Value::Int(a / b),
547 (Value::Float(a), Value::Float(b)) => Value::Float(a / b),
548 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 / b),
549 (Value::Float(a), Value::Int(b)) => Value::Float(a / b as f64),
550 _ => panic!("Cannot divide these value types"),
551 }
552 }
553}
554
555#[cfg(test)]
556mod tests {
557 use super::*;
558
559 #[test]
560 fn value_int_arithmetic() {
561 assert_eq!(Value::Int(10) + Value::Int(3), Value::Int(13));
562 assert_eq!(Value::Int(10) - Value::Int(3), Value::Int(7));
563 assert_eq!(Value::Int(10) * Value::Int(3), Value::Int(30));
564 assert_eq!(Value::Int(10) / Value::Int(3), Value::Int(3));
565 }
566
567 #[test]
568 fn value_float_arithmetic() {
569 assert_eq!(Value::Float(2.5) + Value::Float(1.5), Value::Float(4.0));
570 assert_eq!(Value::Float(5.0) - Value::Float(1.5), Value::Float(3.5));
571 assert_eq!(Value::Float(2.0) * Value::Float(3.0), Value::Float(6.0));
572 assert_eq!(Value::Float(7.0) / Value::Float(2.0), Value::Float(3.5));
573 }
574
575 #[test]
576 fn value_cross_type_promotion() {
577 assert_eq!(Value::Int(2) + Value::Float(1.5), Value::Float(3.5));
578 assert_eq!(Value::Float(2.5) + Value::Int(2), Value::Float(4.5));
579 assert_eq!(Value::Int(3) * Value::Float(2.0), Value::Float(6.0));
580 assert_eq!(Value::Float(6.0) / Value::Int(2), Value::Float(3.0));
581 }
582
583 #[test]
584 fn value_text_concat() {
585 assert_eq!(
586 Value::Text("hello".to_string()) + Value::Text(" world".to_string()),
587 Value::Text("hello world".to_string())
588 );
589 }
590
591 #[test]
592 #[should_panic(expected = "divide by zero")]
593 fn value_div_by_zero_panics() {
594 let _ = Value::Int(1) / Value::Int(0);
595 }
596
597 #[test]
598 #[should_panic(expected = "Cannot add")]
599 fn value_incompatible_types_panic() {
600 let _ = Value::Bool(true) + Value::Int(1);
601 }
602
603 #[test]
604 fn value_display() {
605 assert_eq!(format!("{}", Value::Int(42)), "42");
606 assert_eq!(format!("{}", Value::Float(3.14)), "3.14");
607 assert_eq!(format!("{}", Value::Bool(true)), "true");
608 assert_eq!(format!("{}", Value::Text("hi".to_string())), "hi");
609 assert_eq!(format!("{}", Value::Char('a')), "a");
610 assert_eq!(format!("{}", Value::Nothing), "nothing");
611 }
612
613 #[test]
614 fn value_from_conversions() {
615 assert_eq!(Value::from(42i64), Value::Int(42));
616 assert_eq!(Value::from(3.14f64), Value::Float(3.14));
617 assert_eq!(Value::from(true), Value::Bool(true));
618 assert_eq!(Value::from("hello"), Value::Text("hello".to_string()));
619 assert_eq!(Value::from("hello".to_string()), Value::Text("hello".to_string()));
620 assert_eq!(Value::from('x'), Value::Char('x'));
621 }
622}