From c4eb3b4753dbcc76292673cd349254f0171f058a Mon Sep 17 00:00:00 2001 From: Andrey Pilipenko Date: Wed, 19 Mar 2025 20:46:15 +0300 Subject: [PATCH] first --- .vscode/launch.json | 45 +++++++++++++++++++++ Cargo.toml | 8 ++++ src/dispatcher.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++ src/listener.rs | 15 +++++++ src/main.rs | 35 ++++++++++++++++ src/store.rs | 29 +++++++++++++ src/traits.rs | 26 ++++++++++++ 7 files changed, 257 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 Cargo.toml create mode 100644 src/dispatcher.rs create mode 100644 src/listener.rs create mode 100644 src/main.rs create mode 100644 src/store.rs create mode 100644 src/traits.rs diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..8c96d58 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,45 @@ +{ + // Используйте IntelliSense, чтобы узнать о возможных атрибутах. + // Наведите указатель мыши, чтобы просмотреть описания существующих атрибутов. + // Для получения дополнительной информации посетите: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'Manager'", + "cargo": { + "args": [ + "build", + "--bin=Manager", + "--package=Manager" + ], + "filter": { + "name": "Manager", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'Manager'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=Manager", + "--package=Manager" + ], + "filter": { + "name": "Manager", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f32a424 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "Manager" +version = "0.1.0" +edition = "2021" + +[dependencies] +postgres = "*" +lazy_static = "*" \ No newline at end of file diff --git a/src/dispatcher.rs b/src/dispatcher.rs new file mode 100644 index 0000000..ad65916 --- /dev/null +++ b/src/dispatcher.rs @@ -0,0 +1,99 @@ +use std::collections::HashMap; +use std::sync::Mutex; +use lazy_static::lazy_static; + +use crate::traits::{Action, ActionType}; + +type RecieverID = i32; + +// Трейт IReciever (аналог интерфейса в C++) +pub trait IReciever { + fn id(&self) -> RecieverID; + fn recieve(&self, action: Action); +} + +// Реализация Reciever +pub struct Reciever { + id: RecieverID, +} + +impl Reciever { + pub fn new(id: RecieverID) -> Self { + Reciever { id } + } +} + +impl IReciever for Reciever { + fn id(&self) -> RecieverID { + self.id + } + + fn recieve(&self, action: Action) { + println!("Reciever: action id={} action data={}", action.typ, action.payload); + } +} + +// Глобальные статические переменные для subscriptions и actions +lazy_static! { + static ref SUBSCRIPTIONS: Mutex>>> = + Mutex::new(HashMap::new()); + static ref ACTIONS: Mutex> = Mutex::new(HashMap::new()); +} + +// Трейт IDispatcher +pub trait IDispatcher { + fn subscribe(&self, action_id: ActionType, reciever: Box); + fn unsubscribe(&self, action_id: ActionType, reciever_id: RecieverID); + fn proccess(&self); + fn send(&self, action: Action); + fn erase(&self, action_id: ActionType); +} + +// Реализация Dispatcher +pub struct Dispatcher; + +impl Dispatcher { + pub fn new() -> Self { + Dispatcher + } +} + +impl IDispatcher for Dispatcher { + fn subscribe(&self, action_id: ActionType, reciever: Box) { + SUBSCRIPTIONS + .lock() + .unwrap() + .entry(action_id) + .or_insert_with(HashMap::new) + .insert(reciever.id(), reciever); + } + + fn unsubscribe(&self, action_id: ActionType, reciever_id: RecieverID) { + if let Some(recievers) = SUBSCRIPTIONS.lock().unwrap().get_mut(&action_id) { + recievers.remove(&reciever_id); + } + } + + fn proccess(&self) { + let mut actions = ACTIONS.lock().unwrap(); + let subscriptions = SUBSCRIPTIONS.lock().unwrap(); + + let actions_clone = actions.clone(); // Клонируем actions для итерации + for (action_id, action) in actions_clone { + if let Some(recievers) = subscriptions.get(&action_id) { + for reciever in recievers.values() { + reciever.recieve(action.clone()); + } + actions.remove(&action_id); // Удаляем обработанное действие + } + } + } + + fn send(&self, action: Action) { + ACTIONS.lock().unwrap().insert(action.typ, action); + } + + fn erase(&self, action_id: ActionType) { + ACTIONS.lock().unwrap().remove(&action_id); + } +} diff --git a/src/listener.rs b/src/listener.rs new file mode 100644 index 0000000..f06c69a --- /dev/null +++ b/src/listener.rs @@ -0,0 +1,15 @@ +use crate::traits; + +pub struct Listener { + id: ListenerID, +} + +impl IListener for Listener { + fn id(&self) -> ListenerID { + self.id + } + + fn listen(&self, store: IStore) { + println!("listen getState: ", store.getState()); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2abf974 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,35 @@ + +mod traits; +mod dispatcher; +mod store; + +use dispatcher::{Dispatcher, IDispatcher, Reciever, IReciever}; +use traits::Action; +use store::Store; + +fn main() { + let s = Store::new(); + + let d1 = Dispatcher::new(); + + let r1 = Box::new(Reciever::new(1)) as Box; + let r2 = Box::new(Reciever::new(2)) as Box; + + let a1 = Action { + typ: 1, + payload: "11111".to_string(), + }; + let a2 = Action { + typ: 2, + payload: "22222".to_string(), + }; + + d1.subscribe(a1.typ, r1); + d1.subscribe(a2.typ, r2); + + d1.send(a1); + d1.send(a2); + + let d2 = Dispatcher::new(); + d2.proccess(); // Теперь d2 работает с общими данными +} \ No newline at end of file diff --git a/src/store.rs b/src/store.rs new file mode 100644 index 0000000..619ee1a --- /dev/null +++ b/src/store.rs @@ -0,0 +1,29 @@ +use crate::traits::{Action, IListener, State, IStore}; +use crate::dispatcher::{IDispatcher,Dispatcher}; + +pub struct Store { + state: State, + dispatcher: Box +} + +impl Store { + pub fn new() -> Self { + Store{ + state: State {}, + dispatcher:Box::new(Dispatcher::new()) + } + } +} + +impl IStore for Store { + fn getState(&self) -> State { + return self.state.clone(); + } + fn dispatch(&self, action: Action) { + + } + fn subscribe(&self, listener: Box){ + } + fn unsubscribe(&self, listener: Box){ + } +} \ No newline at end of file diff --git a/src/traits.rs b/src/traits.rs new file mode 100644 index 0000000..cceeccc --- /dev/null +++ b/src/traits.rs @@ -0,0 +1,26 @@ +pub type ListenerID = i32; +pub type ActionType = i32; +pub type Payload = String; + +#[derive(Clone)] +pub struct Action { + pub typ: ActionType, + pub payload: Payload, +} + +#[derive(Clone)] +pub struct State { +} + + +pub trait IListener { + fn id(&self) -> ListenerID; + fn listen(&self, store: Box); +} + +pub trait IStore { + fn getState(&self) -> State; + fn dispatch(&self, action: Action); + fn subscribe(&self, listener: Box); + fn unsubscribe(&self, listener: Box); +}