use std::cell::RefCell;
use std::hash::Hash;
use std::rc::Rc;
pub type Nat = u64;
pub type Int = i64;
pub type Real = f64;
pub type Text = String;
pub type Bool = bool;
pub type Unit = ();
pub type Char = char;
pub type Byte = u8;
#[derive(Debug)]
pub struct LogosSeq<T>(pub Rc<RefCell<Vec<T>>>);
impl<T> LogosSeq<T> {
pub fn new() -> Self {
Self(Rc::new(RefCell::new(Vec::new())))
}
pub fn from_vec(v: Vec<T>) -> Self {
Self(Rc::new(RefCell::new(v)))
}
pub fn with_capacity(cap: usize) -> Self {
Self(Rc::new(RefCell::new(Vec::with_capacity(cap))))
}
pub fn push(&self, value: T) {
self.0.borrow_mut().push(value);
}
pub fn pop(&self) -> Option<T> {
self.0.borrow_mut().pop()
}
pub fn len(&self) -> usize {
self.0.borrow().len()
}
pub fn is_empty(&self) -> bool {
self.0.borrow().is_empty()
}
pub fn remove(&self, index: usize) -> T {
self.0.borrow_mut().remove(index)
}
pub fn borrow(&self) -> std::cell::Ref<'_, Vec<T>> {
self.0.borrow()
}
pub fn borrow_mut(&self) -> std::cell::RefMut<'_, Vec<T>> {
self.0.borrow_mut()
}
}
impl<T: Clone> LogosSeq<T> {
pub fn deep_clone(&self) -> Self {
Self(Rc::new(RefCell::new(self.0.borrow().clone())))
}
pub fn to_vec(&self) -> Vec<T> {
self.0.borrow().clone()
}
pub fn extend_from_slice(&self, other: &[T]) {
self.0.borrow_mut().extend_from_slice(other);
}
pub fn iter(&self) -> LogosSeqIter<T> {
LogosSeqIter {
data: self.to_vec(),
pos: 0,
}
}
}
pub struct LogosSeqIter<T> {
data: Vec<T>,
pos: usize,
}
impl<T: Clone> Iterator for LogosSeqIter<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.pos < self.data.len() {
let val = self.data[self.pos].clone();
self.pos += 1;
Some(val)
} else {
None
}
}
}
impl<T: Ord> LogosSeq<T> {
pub fn sort(&self) {
self.0.borrow_mut().sort();
}
}
impl<T> LogosSeq<T> {
pub fn reverse(&self) {
self.0.borrow_mut().reverse();
}
}
impl<T> Clone for LogosSeq<T> {
fn clone(&self) -> Self {
Self(Rc::clone(&self.0))
}
}
impl<T> Default for LogosSeq<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: PartialEq> PartialEq for LogosSeq<T> {
fn eq(&self, other: &Self) -> bool {
*self.0.borrow() == *other.0.borrow()
}
}
impl<T: std::fmt::Display> std::fmt::Display for LogosSeq<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let inner = self.0.borrow();
write!(f, "[")?;
for (i, item) in inner.iter().enumerate() {
if i > 0 { write!(f, ", ")?; }
write!(f, "{}", item)?;
}
write!(f, "]")
}
}
impl<T> From<Vec<T>> for LogosSeq<T> {
fn from(v: Vec<T>) -> Self {
Self::from_vec(v)
}
}
impl<T: serde::Serialize> serde::Serialize for LogosSeq<T> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.borrow().serialize(serializer)
}
}
impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for LogosSeq<T> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let vec = Vec::<T>::deserialize(deserializer)?;
Ok(Self::from_vec(vec))
}
}
impl<T: PartialEq> LogosContains<T> for LogosSeq<T> {
#[inline(always)]
fn logos_contains(&self, value: &T) -> bool {
self.0.borrow().contains(value)
}
}
impl<T: Clone> IntoIterator for LogosSeq<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.to_vec().into_iter()
}
}
#[derive(Debug)]
pub struct LogosMap<K, V>(pub Rc<RefCell<rustc_hash::FxHashMap<K, V>>>);
impl<K: Eq + Hash, V> LogosMap<K, V> {
pub fn new() -> Self {
Self(Rc::new(RefCell::new(rustc_hash::FxHashMap::default())))
}
pub fn with_capacity(cap: usize) -> Self {
Self(Rc::new(RefCell::new(
rustc_hash::FxHashMap::with_capacity_and_hasher(cap, Default::default()),
)))
}
pub fn from_map(m: rustc_hash::FxHashMap<K, V>) -> Self {
Self(Rc::new(RefCell::new(m)))
}
pub fn insert(&self, key: K, value: V) -> Option<V> {
self.0.borrow_mut().insert(key, value)
}
pub fn remove(&self, key: &K) -> Option<V> {
self.0.borrow_mut().remove(key)
}
pub fn len(&self) -> usize {
self.0.borrow().len()
}
pub fn is_empty(&self) -> bool {
self.0.borrow().is_empty()
}
pub fn contains_key(&self, key: &K) -> bool {
self.0.borrow().contains_key(key)
}
pub fn borrow(&self) -> std::cell::Ref<'_, rustc_hash::FxHashMap<K, V>> {
self.0.borrow()
}
pub fn borrow_mut(&self) -> std::cell::RefMut<'_, rustc_hash::FxHashMap<K, V>> {
self.0.borrow_mut()
}
}
impl<K: Eq + Hash + Clone, V: Clone> LogosMap<K, V> {
pub fn deep_clone(&self) -> Self {
Self(Rc::new(RefCell::new(self.0.borrow().clone())))
}
pub fn get(&self, key: &K) -> Option<V> {
self.0.borrow().get(key).cloned()
}
pub fn values(&self) -> Vec<V> {
self.0.borrow().values().cloned().collect()
}
pub fn keys(&self) -> Vec<K> {
self.0.borrow().keys().cloned().collect()
}
}
impl<K, V> Clone for LogosMap<K, V> {
fn clone(&self) -> Self {
Self(Rc::clone(&self.0))
}
}
impl<K: Eq + Hash, V> Default for LogosMap<K, V> {
fn default() -> Self {
Self::new()
}
}
impl<K: PartialEq + Eq + Hash, V: PartialEq> PartialEq for LogosMap<K, V> {
fn eq(&self, other: &Self) -> bool {
*self.0.borrow() == *other.0.borrow()
}
}
impl<K: std::fmt::Display + Eq + Hash, V: std::fmt::Display> std::fmt::Display for LogosMap<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let inner = self.0.borrow();
write!(f, "{{")?;
for (i, (k, v)) in inner.iter().enumerate() {
if i > 0 { write!(f, ", ")?; }
write!(f, "{}: {}", k, v)?;
}
write!(f, "}}")
}
}
impl<K: serde::Serialize + Eq + Hash, V: serde::Serialize> serde::Serialize for LogosMap<K, V> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.borrow().serialize(serializer)
}
}
impl<'de, K: serde::Deserialize<'de> + Eq + Hash, V: serde::Deserialize<'de>> serde::Deserialize<'de> for LogosMap<K, V> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let map = rustc_hash::FxHashMap::<K, V>::deserialize(deserializer)?;
Ok(Self::from_map(map))
}
}
impl<K: Eq + Hash, V> LogosContains<K> for LogosMap<K, V> {
#[inline(always)]
fn logos_contains(&self, key: &K) -> bool {
self.0.borrow().contains_key(key)
}
}
pub type Seq<T> = LogosSeq<T>;
pub type Map<K, V> = LogosMap<K, V>;
pub type Set<T> = rustc_hash::FxHashSet<T>;
pub trait LogosContains<T> {
fn logos_contains(&self, value: &T) -> bool;
}
impl<T: PartialEq> LogosContains<T> for Vec<T> {
#[inline(always)]
fn logos_contains(&self, value: &T) -> bool {
self.contains(value)
}
}
impl<T: PartialEq> LogosContains<T> for [T] {
#[inline(always)]
fn logos_contains(&self, value: &T) -> bool {
self.contains(value)
}
}
impl<T: Eq + Hash> LogosContains<T> for rustc_hash::FxHashSet<T> {
#[inline(always)]
fn logos_contains(&self, value: &T) -> bool {
self.contains(value)
}
}
impl<K: Eq + Hash, V> LogosContains<K> for rustc_hash::FxHashMap<K, V> {
#[inline(always)]
fn logos_contains(&self, key: &K) -> bool {
self.contains_key(key)
}
}
impl LogosContains<&str> for String {
#[inline(always)]
fn logos_contains(&self, value: &&str) -> bool {
self.contains(*value)
}
}
impl LogosContains<String> for String {
#[inline(always)]
fn logos_contains(&self, value: &String) -> bool {
self.contains(value.as_str())
}
}
impl LogosContains<char> for String {
#[inline(always)]
fn logos_contains(&self, value: &char) -> bool {
self.contains(*value)
}
}
impl<T: Eq + Hash + Clone, B: crate::crdt::SetBias> LogosContains<T>
for crate::crdt::ORSet<T, B>
{
#[inline(always)]
fn logos_contains(&self, value: &T) -> bool {
self.contains(value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Int(i64),
Float(f64),
Bool(bool),
Text(String),
Char(char),
Nothing,
}
impl std::fmt::Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::Int(n) => write!(f, "{}", n),
Value::Float(n) => write!(f, "{}", n),
Value::Bool(b) => write!(f, "{}", b),
Value::Text(s) => write!(f, "{}", s),
Value::Char(c) => write!(f, "{}", c),
Value::Nothing => write!(f, "nothing"),
}
}
}
impl From<i64> for Value {
fn from(n: i64) -> Self { Value::Int(n) }
}
impl From<f64> for Value {
fn from(n: f64) -> Self { Value::Float(n) }
}
impl From<bool> for Value {
fn from(b: bool) -> Self { Value::Bool(b) }
}
impl From<String> for Value {
fn from(s: String) -> Self { Value::Text(s) }
}
impl From<&str> for Value {
fn from(s: &str) -> Self { Value::Text(s.to_string()) }
}
impl From<char> for Value {
fn from(c: char) -> Self { Value::Char(c) }
}
pub type Tuple = Vec<Value>;
impl std::ops::Add for Value {
type Output = Value;
#[inline]
fn add(self, other: Value) -> Value {
match (self, other) {
(Value::Int(a), Value::Int(b)) => Value::Int(a + b),
(Value::Float(a), Value::Float(b)) => Value::Float(a + b),
(Value::Int(a), Value::Float(b)) => Value::Float(a as f64 + b),
(Value::Float(a), Value::Int(b)) => Value::Float(a + b as f64),
(Value::Text(a), Value::Text(b)) => Value::Text(format!("{}{}", a, b)),
_ => panic!("Cannot add these value types"),
}
}
}
impl std::ops::Sub for Value {
type Output = Value;
#[inline]
fn sub(self, other: Value) -> Value {
match (self, other) {
(Value::Int(a), Value::Int(b)) => Value::Int(a - b),
(Value::Float(a), Value::Float(b)) => Value::Float(a - b),
(Value::Int(a), Value::Float(b)) => Value::Float(a as f64 - b),
(Value::Float(a), Value::Int(b)) => Value::Float(a - b as f64),
_ => panic!("Cannot subtract these value types"),
}
}
}
impl std::ops::Mul for Value {
type Output = Value;
#[inline]
fn mul(self, other: Value) -> Value {
match (self, other) {
(Value::Int(a), Value::Int(b)) => Value::Int(a * b),
(Value::Float(a), Value::Float(b)) => Value::Float(a * b),
(Value::Int(a), Value::Float(b)) => Value::Float(a as f64 * b),
(Value::Float(a), Value::Int(b)) => Value::Float(a * b as f64),
_ => panic!("Cannot multiply these value types"),
}
}
}
impl std::ops::Div for Value {
type Output = Value;
#[inline]
fn div(self, other: Value) -> Value {
match (self, other) {
(Value::Int(a), Value::Int(b)) => Value::Int(a / b),
(Value::Float(a), Value::Float(b)) => Value::Float(a / b),
(Value::Int(a), Value::Float(b)) => Value::Float(a as f64 / b),
(Value::Float(a), Value::Int(b)) => Value::Float(a / b as f64),
_ => panic!("Cannot divide these value types"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn value_int_arithmetic() {
assert_eq!(Value::Int(10) + Value::Int(3), Value::Int(13));
assert_eq!(Value::Int(10) - Value::Int(3), Value::Int(7));
assert_eq!(Value::Int(10) * Value::Int(3), Value::Int(30));
assert_eq!(Value::Int(10) / Value::Int(3), Value::Int(3));
}
#[test]
fn value_float_arithmetic() {
assert_eq!(Value::Float(2.5) + Value::Float(1.5), Value::Float(4.0));
assert_eq!(Value::Float(5.0) - Value::Float(1.5), Value::Float(3.5));
assert_eq!(Value::Float(2.0) * Value::Float(3.0), Value::Float(6.0));
assert_eq!(Value::Float(7.0) / Value::Float(2.0), Value::Float(3.5));
}
#[test]
fn value_cross_type_promotion() {
assert_eq!(Value::Int(2) + Value::Float(1.5), Value::Float(3.5));
assert_eq!(Value::Float(2.5) + Value::Int(2), Value::Float(4.5));
assert_eq!(Value::Int(3) * Value::Float(2.0), Value::Float(6.0));
assert_eq!(Value::Float(6.0) / Value::Int(2), Value::Float(3.0));
}
#[test]
fn value_text_concat() {
assert_eq!(
Value::Text("hello".to_string()) + Value::Text(" world".to_string()),
Value::Text("hello world".to_string())
);
}
#[test]
#[should_panic(expected = "divide by zero")]
fn value_div_by_zero_panics() {
let _ = Value::Int(1) / Value::Int(0);
}
#[test]
#[should_panic(expected = "Cannot add")]
fn value_incompatible_types_panic() {
let _ = Value::Bool(true) + Value::Int(1);
}
#[test]
fn value_display() {
assert_eq!(format!("{}", Value::Int(42)), "42");
assert_eq!(format!("{}", Value::Float(3.14)), "3.14");
assert_eq!(format!("{}", Value::Bool(true)), "true");
assert_eq!(format!("{}", Value::Text("hi".to_string())), "hi");
assert_eq!(format!("{}", Value::Char('a')), "a");
assert_eq!(format!("{}", Value::Nothing), "nothing");
}
#[test]
fn value_from_conversions() {
assert_eq!(Value::from(42i64), Value::Int(42));
assert_eq!(Value::from(3.14f64), Value::Float(3.14));
assert_eq!(Value::from(true), Value::Bool(true));
assert_eq!(Value::from("hello"), Value::Text("hello".to_string()));
assert_eq!(Value::from("hello".to_string()), Value::Text("hello".to_string()));
assert_eq!(Value::from('x'), Value::Char('x'));
}
}