a bit of reorganization
This commit is contained in:
parent
5979337cb8
commit
c3a185fe8b
5 changed files with 99 additions and 44 deletions
54
src/atoms.rs
54
src/atoms.rs
|
@ -8,7 +8,22 @@ pub struct RoomId(String);
|
|||
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct EventId(String);
|
||||
|
||||
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct ActorId(String);
|
||||
|
||||
impl RoomId {
|
||||
// maybe use the initial create event hash/id as the room id?
|
||||
pub fn random() -> Self {
|
||||
let rng = rand::thread_rng()
|
||||
.sample_iter(Alphanumeric)
|
||||
.map(char::from)
|
||||
.take(12)
|
||||
.collect();
|
||||
Self(rng)
|
||||
}
|
||||
}
|
||||
|
||||
impl ActorId {
|
||||
pub fn random() -> Self {
|
||||
let rng = rand::thread_rng()
|
||||
.sample_iter(Alphanumeric)
|
||||
|
@ -20,6 +35,7 @@ impl RoomId {
|
|||
}
|
||||
|
||||
impl EventId {
|
||||
// TEMP: will use hashes
|
||||
pub fn random() -> Self {
|
||||
let rng = rand::thread_rng()
|
||||
.sample_iter(Alphanumeric)
|
||||
|
@ -30,26 +46,22 @@ impl EventId {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for RoomId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "!{}", self.0)
|
||||
}
|
||||
macro_rules! impl_display {
|
||||
($Thing:ty, $fmt:expr) => {
|
||||
impl Display for $Thing {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, $fmt, self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for $Thing {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl Display for EventId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "${}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for RoomId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for EventId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
impl_display!(ActorId, "^{}");
|
||||
impl_display!(EventId, "${}");
|
||||
impl_display!(RoomId, "!{}");
|
||||
|
|
46
src/event.rs
46
src/event.rs
|
@ -1,8 +1,52 @@
|
|||
use crate::atoms::EventId;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// An event, is the basic building block/envolope containing all data.
|
||||
pub struct Event<T> {
|
||||
pub id: EventId,
|
||||
pub content: T,
|
||||
pub content: CoreContent<T>,
|
||||
pub references: Vec<EventId>,
|
||||
// pub author: ActorId,
|
||||
// pub signature: ActorSignature,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// This defines content of an event as either a builtin event or application-specific event.
|
||||
pub enum CoreContent<T> {
|
||||
Create(CreateContent),
|
||||
Custom(T),
|
||||
|
||||
/*
|
||||
custom events from other places, for inspiration
|
||||
|
||||
ufh (my failed project):
|
||||
- x.tag{.local} to add tags to events
|
||||
- x.annotate{.local} to add custom data to events
|
||||
- x.acl to define access control
|
||||
- x.update to update/edit events
|
||||
- x.redact to remove events
|
||||
- x.file to create new files
|
||||
|
||||
matrix:
|
||||
- m.room.create to create rooms
|
||||
- m.room.join_rules to define who can join/leave
|
||||
- m.room.member to define room members
|
||||
- m.room.power_levels to define basic access control
|
||||
- m.room.canonical_alias to add human-readable aliases to rooms
|
||||
- m.room.redaction to remove events
|
||||
- m.room.tombstone to replace rooms
|
||||
- m.space.* for many:many room hierarchies
|
||||
*/
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Every room has exactly one immutable create event as the single root of the event dag.
|
||||
pub struct CreateContent {
|
||||
// TODO: move resolver stuff here
|
||||
}
|
||||
|
||||
impl CreateContent {
|
||||
pub fn new() -> Self {
|
||||
Self { }
|
||||
}
|
||||
}
|
||||
|
|
21
src/main.rs
21
src/main.rs
|
@ -1,5 +1,7 @@
|
|||
#![allow(dead_code)] // TODO: remove this later!
|
||||
|
||||
use std::collections::HashMap;
|
||||
use crate::{resolver::Resolver, room::Room};
|
||||
use crate::{event::CoreContent, resolver::Resolver, room::Room};
|
||||
|
||||
mod atoms;
|
||||
mod event;
|
||||
|
@ -8,32 +10,31 @@ mod resolver;
|
|||
|
||||
#[derive(Debug)]
|
||||
enum EventContent {
|
||||
Create,
|
||||
Set(String, String),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let resolver = Resolver::new(Box::new(|events| {
|
||||
// resolve/reduce state from a sorted list of events, "full resolution"
|
||||
dbg!(events);
|
||||
let mut kv = HashMap::new();
|
||||
for event in events {
|
||||
match &event.content {
|
||||
EventContent::Create => {},
|
||||
EventContent::Set(k, v) => {
|
||||
CoreContent::Create(_) => {},
|
||||
CoreContent::Custom(EventContent::Set(k, v)) => {
|
||||
kv.insert(k.clone(), v.clone());
|
||||
},
|
||||
}
|
||||
}
|
||||
kv
|
||||
}), Box::new(|_a, _b| {
|
||||
// tiebreak two events
|
||||
todo!()
|
||||
}));
|
||||
let mut room = Room::new(resolver, EventContent::Create);
|
||||
room.create_event(EventContent::Set("foo".into(), "apple".into()));
|
||||
room.create_event(EventContent::Set("bar".into(), "banana".into()));
|
||||
room.create_event(EventContent::Set("baz".into(), "carrot".into()));
|
||||
let mut room = Room::new(resolver);
|
||||
room.create_event(CoreContent::Custom(EventContent::Set("foo".into(), "apple".into())));
|
||||
room.create_event(CoreContent::Custom(EventContent::Set("bar".into(), "banana".into())));
|
||||
room.create_event(CoreContent::Custom(EventContent::Set("baz".into(), "carrot".into())));
|
||||
dbg!(&room);
|
||||
dbg!(&room.get_root());
|
||||
dbg!(&room.get_state());
|
||||
println!("Hello, world!");
|
||||
}
|
||||
|
|
|
@ -24,26 +24,24 @@ impl<T: Debug, S> Resolver<T, S> {
|
|||
pub fn sort<'a>(&'a self, events: &'a [Event<T>]) -> Vec<&Event<T>> {
|
||||
let mut references: HashSet<(EventId, EventId)> = events
|
||||
.iter()
|
||||
.map(|event| {
|
||||
.flat_map(|event| {
|
||||
event
|
||||
.references
|
||||
.iter()
|
||||
.map(|r| (r.clone(), event.id.clone()))
|
||||
.map(|parent_id| (parent_id.clone(), event.id.clone()))
|
||||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
let mut sorted = vec![];
|
||||
let (mut heads, mut unsorted): (Vec<_>, Vec<_>) =
|
||||
events.iter().partition(|event| event.references.is_empty());
|
||||
assert!(heads.len() == 1);
|
||||
while let Some(ev) = heads.pop() {
|
||||
references.retain(|(parent, _)| parent != &ev.id);
|
||||
references.retain(|(parent_id, _)| parent_id != &ev.id);
|
||||
sorted.push(ev);
|
||||
let (mut children, new_unsorted) = unsorted.into_iter().partition(|candidate| {
|
||||
let (new_unsorted, mut children) = unsorted.into_iter().partition(|candidate| {
|
||||
references
|
||||
.iter()
|
||||
.position(|(_, child)| child == &candidate.id)
|
||||
.is_none()
|
||||
.any(|(_, child)| child == &candidate.id)
|
||||
});
|
||||
unsorted = new_unsorted;
|
||||
children.sort_by(|a, b| (self.tiebreak_fn)(a, b).then_with(|| a.id.cmp(&b.id)));
|
||||
|
|
10
src/room.rs
10
src/room.rs
|
@ -1,6 +1,6 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use crate::{atoms::EventId, event::Event, resolver::Resolver};
|
||||
use crate::{atoms::EventId, event::{CoreContent, CreateContent, Event}, resolver::Resolver};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Room<E, S> {
|
||||
|
@ -10,11 +10,11 @@ pub struct Room<E, S> {
|
|||
}
|
||||
|
||||
impl<T: Debug, S> Room<T, S> {
|
||||
pub fn new(resolver: Resolver<T, S>, base_content: T) -> Self {
|
||||
pub fn new(resolver: Resolver<T, S>) -> Self {
|
||||
let event_id = EventId::random();
|
||||
let base_event = Event {
|
||||
id: event_id.clone(),
|
||||
content: base_content,
|
||||
content: CoreContent::Create(CreateContent::new()),
|
||||
references: vec![],
|
||||
};
|
||||
Self {
|
||||
|
@ -25,7 +25,7 @@ impl<T: Debug, S> Room<T, S> {
|
|||
}
|
||||
|
||||
pub fn get_root(&self) -> &Event<T> {
|
||||
self.events.get(0).as_ref().unwrap()
|
||||
self.events.first().as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_state(&mut self) -> S {
|
||||
|
@ -34,7 +34,7 @@ impl<T: Debug, S> Room<T, S> {
|
|||
self.resolver.resolve(&self.events)
|
||||
}
|
||||
|
||||
pub fn create_event(&mut self, event_content: T) {
|
||||
pub fn create_event(&mut self, event_content: CoreContent<T>) {
|
||||
let event = Event {
|
||||
id: EventId::random(),
|
||||
content: event_content,
|
||||
|
|
Loading…
Reference in a new issue