Extract types into separate files
Also make tables more nice to work with and fix debug printing for cyclic references.
This commit is contained in:
parent
c1bea626b1
commit
fc1ada97c1
3 changed files with 208 additions and 81 deletions
98
src/main.rs
98
src/main.rs
|
|
@ -1,88 +1,24 @@
|
||||||
use std::cell::RefCell;
|
use crate::table::{Table, TableOwner};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt::{self, Debug};
|
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
use std::rc::{Rc, Weak};
|
|
||||||
|
|
||||||
struct Table(Weak<RefCell<HashMap<Key, Value>>>);
|
mod table;
|
||||||
|
mod values;
|
||||||
impl Debug for Table {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self.0.upgrade() {
|
|
||||||
None => write!(f, "<broken table>"),
|
|
||||||
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<H: Hasher>(&self, state: &mut H) {
|
|
||||||
self.0.as_ptr().hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash)]
|
|
||||||
enum Key {
|
|
||||||
String(Box<String>),
|
|
||||||
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<String>),
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
|
|
||||||
let mut table = HashMap::new();
|
let table_owner = TableOwner::new();
|
||||||
table.insert(
|
|
||||||
Key::String(Box::new("Hello".into())),
|
|
||||||
Value::String(Box::new("World".into())),
|
|
||||||
);
|
|
||||||
let table = Rc::new(RefCell::new(table));
|
|
||||||
|
|
||||||
let table_value = Value::Table(Table(Rc::downgrade(&table)));
|
let table = Table::new(&table_owner);
|
||||||
dbg!(table_value);
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
70
src/table.rs
Normal file
70
src/table.rs
Normal file
|
|
@ -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<RefCell<HashMap<Key, Value>>>);
|
||||||
|
|
||||||
|
impl TableOwner {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Rc::new(RefCell::new(HashMap::new())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Table(Weak<RefCell<HashMap<Key, Value>>>);
|
||||||
|
|
||||||
|
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, "<broken table>"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let hash_map = match rc.try_borrow_mut() {
|
||||||
|
Ok(hash_map) => hash_map,
|
||||||
|
Err(_) => return write!(f, "<cyclic ref>"),
|
||||||
|
};
|
||||||
|
|
||||||
|
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<H: Hasher>(&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);
|
||||||
|
}
|
||||||
|
}
|
||||||
121
src/values.rs
Normal file
121
src/values.rs
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
use std::fmt::{self, Debug};
|
||||||
|
|
||||||
|
use crate::table::Table;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Key {
|
||||||
|
String(Box<String>),
|
||||||
|
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<Box<String>> for Key {
|
||||||
|
fn from(s: Box<String>) -> Self {
|
||||||
|
Self::String(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> 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<bool> for Key {
|
||||||
|
fn from(b: bool) -> Self {
|
||||||
|
Self::Bool(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for Key {
|
||||||
|
fn from(i: i64) -> Self {
|
||||||
|
Self::Int(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Table> for Key {
|
||||||
|
fn from(t: Table) -> Self {
|
||||||
|
Self::Table(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub enum Value {
|
||||||
|
String(Box<String>),
|
||||||
|
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<Box<String>> for Value {
|
||||||
|
fn from(s: Box<String>) -> Self {
|
||||||
|
Self::String(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> 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<bool> for Value {
|
||||||
|
fn from(b: bool) -> Self {
|
||||||
|
Self::Bool(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for Value {
|
||||||
|
fn from(i: i64) -> Self {
|
||||||
|
Self::Int(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<f64> for Value {
|
||||||
|
fn from(f: f64) -> Self {
|
||||||
|
Self::Float(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Table> for Value {
|
||||||
|
fn from(t: Table) -> Self {
|
||||||
|
Self::Table(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue