a bit of reorganization

This commit is contained in:
tezlm 2024-02-03 19:58:00 -08:00
parent 5979337cb8
commit c3a185fe8b
Signed by: tezlm
GPG key ID: 649733FCD94AFBBA
5 changed files with 99 additions and 44 deletions

View file

@ -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, "!{}");

View file

@ -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 { }
}
}

View file

@ -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!");
}

View file

@ -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)));

View file

@ -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,