Last active
August 5, 2023 00:45
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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