Skip to content

Instantly share code, notes, and snippets.

@kiyov09
Last active August 5, 2023 00:45
Show Gist options
  • Save kiyov09/34c5c4885c7f3be24c3dd7f76b0839ae to your computer and use it in GitHub Desktop.
Save kiyov09/34c5c4885c7f3be24c3dd7f76b0839ae to your computer and use it in GitHub Desktop.
My sync solution to the challenge presented by Dax (@thdxr) here: https://twitter.com/thdxr/status/1687449674934812672\?s\=20
use std::cell::RefCell;
type UserId = usize;
#[derive(Clone, Debug)]
struct User(UserId);
impl User {
fn new(id: UserId) -> Self {
Self(id)
}
}
#[derive(Clone, Debug)]
struct Todo;
impl Todo {
fn new() -> Self {
Self {}
}
}
#[derive(Clone, Debug)]
enum Events {
UserCreated(UserId),
TodoCreated((Todo, UserId)),
}
enum UserError {}
enum TodoError {}
trait SystemA {
fn recv_next(&self) -> Result<Events, ()>;
}
trait SystemB {
fn get_user(&self, id: UserId) -> Option<User>;
fn create_user(&self, id: UserId) -> Result<(), UserError>;
fn create_todo(&self, todo: Todo) -> Result<(), TodoError>;
}
struct MySystem;
impl MySystem {
fn start_processing(sys_a: &impl SystemA, sys_b: &impl SystemB) {
while let Ok(event) = sys_a.recv_next() {
println!(">>> Received message: {:?}", event);
match event {
Events::UserCreated(user_id) => {
let _ = Self::get_or_create_user(user_id, sys_b)
.map_err(|_| todo!("Handle error properly"));
}
Events::TodoCreated((todo, user_id)) => {
let _ = Self::get_or_create_user(user_id, sys_b)
.map(|_| sys_b.create_todo(todo))
.map_err(|_| todo!("Handle error properly"));
}
};
}
}
fn get_or_create_user(user_id: usize, sys_b: &impl SystemB) -> Result<User, UserError> {
match sys_b.get_user(user_id) {
Some(u) => Ok(u),
None => {
let user = User::new(user_id);
sys_b.create_user(user_id).map(|_| user)
}
}
}
}
//// -----------
struct IntA {
ptr: usize,
events: Vec<Events>,
}
impl IntA {
fn new() -> Self {
Self {
ptr: 0,
events: vec![
Events::UserCreated(1),
Events::TodoCreated((Todo::new(), 1)),
Events::TodoCreated((Todo::new(), 1)),
Events::UserCreated(2),
Events::TodoCreated((Todo::new(), 2)),
Events::TodoCreated((Todo::new(), 3)),
],
}
}
fn next(&mut self) -> Option<Events> {
if self.ptr < self.events.len() {
let e = self.events[self.ptr].clone();
self.ptr += 1;
Some(e)
} else {
None
}
}
}
struct MySystemA {
internal: RefCell<IntA>,
}
impl MySystemA {
fn new() -> Self {
Self {
internal: RefCell::new(IntA::new()),
}
}
}
impl SystemA for MySystemA {
fn recv_next(&self) -> Result<Events, ()> {
// self.internal.next().ok_or(())
self.internal.borrow_mut().next().ok_or(())
}
}
//// -----------
//// -----------
struct IntB {
users: RefCell<Vec<User>>,
todos: RefCell<Vec<Todo>>,
}
impl IntB {
fn new() -> Self {
Self {
users: RefCell::new(vec![]),
todos: RefCell::new(vec![]),
}
}
fn get_user(&self, id: UserId) -> Option<User> {
self.users.borrow().iter().find(|u| u.0 == id).cloned()
}
fn create_user(&self, id: UserId) -> Result<(), UserError> {
self.users.borrow_mut().push(User::new(id));
Ok(())
}
fn create_todo(&self, todo: Todo) -> Result<(), TodoError> {
self.todos.borrow_mut().push(todo);
Ok(())
}
}
struct MySystemB {
internal: RefCell<IntB>,
}
impl MySystemB {
fn new() -> Self {
Self {
internal: RefCell::new(IntB::new()),
}
}
}
impl SystemB for MySystemB {
fn get_user(&self, id: UserId) -> Option<User> {
let internal = self.internal.borrow();
internal.get_user(id)
}
fn create_user(&self, id: UserId) -> Result<(), UserError> {
let internal = self.internal.borrow_mut();
internal.create_user(id)
}
fn create_todo(&self, todo: Todo) -> Result<(), TodoError> {
let internal = self.internal.borrow_mut();
internal.create_todo(todo)
}
}
//// -----------
fn main() {
let sys_a = MySystemA::new();
let sys_b = MySystemB::new();
MySystem::start_processing(&sys_a, &sys_b);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment