From fc1ada97c14febeabe965d8e9488ddd91fc743f2 Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 26 Sep 2021 15:20:18 +0200 Subject: [PATCH] Extract types into separate files Also make tables more nice to work with and fix debug printing for cyclic references. --- src/main.rs | 98 +++++++--------------------------------- src/table.rs | 70 +++++++++++++++++++++++++++++ src/values.rs | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 81 deletions(-) create mode 100644 src/table.rs create mode 100644 src/values.rs diff --git a/src/main.rs b/src/main.rs index 8dce083..ebfde17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,88 +1,24 @@ -use std::cell::RefCell; -use std::collections::HashMap; -use std::fmt::{self, Debug}; -use std::hash::{Hash, Hasher}; -use std::rc::{Rc, Weak}; +use crate::table::{Table, TableOwner}; -struct Table(Weak>>); - -impl Debug for Table { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0.upgrade() { - None => write!(f, ""), - Some(rc) => { - // This may panic if we're not careful? - let hash_map = &*rc.borrow(); - hash_map.fmt(f) - } - } - } -} - -impl PartialEq for Table { - fn eq(&self, other: &Self) -> bool { - self.0.ptr_eq(&other.0) - } -} - -impl Eq for Table {} - -impl Hash for Table { - fn hash(&self, state: &mut H) { - self.0.as_ptr().hash(state); - } -} - -#[derive(PartialEq, Eq, Hash)] -enum Key { - String(Box), - Bool(bool), - Int(i64), - Table(Table), -} - -impl Debug for Key { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::String(s) => s.fmt(f), - Self::Bool(b) => b.fmt(f), - Self::Int(i) => i.fmt(f), - Self::Table(t) => t.fmt(f), - } - } -} - -#[derive(PartialEq)] -enum Value { - String(Box), - Bool(bool), - Int(i64), - Table(Table), - Float(f64), -} - -impl Debug for Value { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::String(s) => s.fmt(f), - Self::Bool(b) => b.fmt(f), - Self::Int(i) => i.fmt(f), - Self::Table(t) => t.fmt(f), - Self::Float(d) => d.fmt(f), - } - } -} +mod table; +mod values; fn main() { println!("Hello, world!"); - let mut table = HashMap::new(); - table.insert( - Key::String(Box::new("Hello".into())), - Value::String(Box::new("World".into())), - ); - let table = Rc::new(RefCell::new(table)); + let table_owner = TableOwner::new(); - let table_value = Value::Table(Table(Rc::downgrade(&table))); - dbg!(table_value); + let table = Table::new(&table_owner); + + table.insert("Hello".into(), "World".into()); + table.insert(1.into(), "Goodbye".into()); + dbg!(&table); + + table.remove(&0.into()); + table.remove(&1.into()); + table.remove(&2.into()); + dbg!(&table); + + table.insert(true.into(), table.clone().into()); + dbg!(&table); } diff --git a/src/table.rs b/src/table.rs new file mode 100644 index 0000000..8801550 --- /dev/null +++ b/src/table.rs @@ -0,0 +1,70 @@ +use std::cell::RefCell; +use std::collections::HashMap; +use std::fmt::{self, Debug}; +use std::hash::{Hash, Hasher}; +use std::rc::{Rc, Weak}; + +use crate::values::{Key, Value}; + +pub struct TableOwner(Rc>>); + +impl TableOwner { + pub fn new() -> Self { + Self(Rc::new(RefCell::new(HashMap::new()))) + } +} + +#[derive(Clone)] +pub struct Table(Weak>>); + +impl Debug for Table { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let rc = match self.0.upgrade() { + Some(rc) => rc, + None => return write!(f, ""), + }; + + let hash_map = match rc.try_borrow_mut() { + Ok(hash_map) => hash_map, + Err(_) => return write!(f, ""), + }; + + hash_map.fmt(f) + } +} + +impl PartialEq for Table { + fn eq(&self, other: &Self) -> bool { + self.0.ptr_eq(&other.0) + } +} + +impl Eq for Table {} + +impl Hash for Table { + fn hash(&self, state: &mut H) { + self.0.as_ptr().hash(state); + } +} + +impl Table { + pub fn new(owner: &TableOwner) -> Self { + Self(Rc::downgrade(&owner.0)) + } + + pub fn insert(&self, key: Key, value: Value) { + self.0 + .upgrade() + .expect("table owner was deallocated") + .borrow_mut() + .insert(key, value); + } + + pub fn remove(&self, key: &Key) { + self.0 + .upgrade() + .expect("table owner was deallocated") + .borrow_mut() + .remove(key); + } +} diff --git a/src/values.rs b/src/values.rs new file mode 100644 index 0000000..7b27c9b --- /dev/null +++ b/src/values.rs @@ -0,0 +1,121 @@ +use std::fmt::{self, Debug}; + +use crate::table::Table; + +#[derive(Clone, PartialEq, Eq, Hash)] +pub enum Key { + String(Box), + Bool(bool), + Int(i64), + Table(Table), +} + +impl Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::String(s) => s.fmt(f), + Self::Bool(b) => b.fmt(f), + Self::Int(i) => i.fmt(f), + Self::Table(t) => t.fmt(f), + } + } +} + +impl From> for Key { + fn from(s: Box) -> Self { + Self::String(s) + } +} + +impl From for Key { + fn from(s: String) -> Self { + Self::String(Box::new(s)) + } +} + +impl From<&str> for Key { + fn from(s: &str) -> Self { + Self::String(Box::new(s.to_string())) + } +} + +impl From for Key { + fn from(b: bool) -> Self { + Self::Bool(b) + } +} + +impl From for Key { + fn from(i: i64) -> Self { + Self::Int(i) + } +} + +impl From for Key { + fn from(t: Table) -> Self { + Self::Table(t) + } +} + +#[derive(Clone, PartialEq)] +pub enum Value { + String(Box), + Bool(bool), + Int(i64), + Float(f64), + Table(Table), +} + +impl Debug for Value { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::String(s) => s.fmt(f), + Self::Bool(b) => b.fmt(f), + Self::Int(i) => i.fmt(f), + Self::Table(t) => t.fmt(f), + Self::Float(d) => d.fmt(f), + } + } +} + +impl From> for Value { + fn from(s: Box) -> Self { + Self::String(s) + } +} + +impl From for Value { + fn from(s: String) -> Self { + Self::String(Box::new(s)) + } +} + +impl From<&str> for Value { + fn from(s: &str) -> Self { + Self::String(Box::new(s.to_string())) + } +} + +impl From for Value { + fn from(b: bool) -> Self { + Self::Bool(b) + } +} + +impl From for Value { + fn from(i: i64) -> Self { + Self::Int(i) + } +} + +impl From for Value { + fn from(f: f64) -> Self { + Self::Float(f) + } +} + +impl From
for Value { + fn from(t: Table) -> Self { + Self::Table(t) + } +}