Add server op dispatcher
This commit is contained in:
parent
488a57d5cb
commit
8cb4425c83
10 changed files with 328 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
/*/target
|
||||||
|
|
100
server/Cargo.lock
generated
Normal file
100
server/Cargo.lock
generated
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "array-init"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "binrw"
|
||||||
|
version = "0.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d4bca59c20d6f40c2cc0802afbe1e788b89096f61bdf7aeea6bf00f10c2909b"
|
||||||
|
dependencies = [
|
||||||
|
"array-init",
|
||||||
|
"binrw_derive",
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "binrw_derive"
|
||||||
|
version = "0.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8ba42866ce5bced2645bfa15e97eef2c62d2bdb530510538de8dd3d04efff3c"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"owo-colors",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owo-colors"
|
||||||
|
version = "3.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polariton"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"binrw",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polariton_server"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"polariton",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
7
server/Cargo.toml
Normal file
7
server/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "polariton_server"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
polariton = { version = "0.1.0", path = "../" }
|
0
server/src/events/mod.rs
Normal file
0
server/src/events/mod.rs
Normal file
2
server/src/lib.rs
Normal file
2
server/src/lib.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod events;
|
||||||
|
pub mod operations;
|
24
server/src/operations/ack.rs
Normal file
24
server/src/operations/ack.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Ack<const CODE: u8, U: Send + Sync> {
|
||||||
|
_user_ty: std::marker::PhantomData<U>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <const CODE: u8, U: Send + Sync> super::Operation for Ack<CODE, U> {
|
||||||
|
type State = ();
|
||||||
|
type User = U;
|
||||||
|
|
||||||
|
fn handle(&self, _: polariton::operation::ParameterTable, _: &mut Self::State, _: &Self::User) -> polariton::operation::OperationResponse {
|
||||||
|
polariton::operation::OperationResponse {
|
||||||
|
code: CODE,
|
||||||
|
return_code: 0,
|
||||||
|
message: polariton::operation::Typed::Null,
|
||||||
|
params: std::collections::HashMap::default().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <const CODE: u8, U: Send + Sync> super::OperationCode for Ack<CODE, U> {
|
||||||
|
fn op_code() -> u8 {
|
||||||
|
CODE
|
||||||
|
}
|
||||||
|
}
|
79
server/src/operations/functional.rs
Normal file
79
server/src/operations/functional.rs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
use polariton::operation::{ParameterTable, OperationResponse};
|
||||||
|
|
||||||
|
pub struct Func<const CODE: u8, S: Send + Sync, U: Send + Sync, F: (Fn(ParameterTable, &mut S, &U) -> OperationResponse) + Send + Sync> {
|
||||||
|
_state_ty: std::marker::PhantomData<S>,
|
||||||
|
_user_ty: std::marker::PhantomData<U>,
|
||||||
|
func: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <const CODE: u8, S: Send + Sync, U: Send + Sync, F: (Fn(ParameterTable, &mut S, &U) -> OperationResponse) + Send + Sync> Func<CODE, S, U, F> {
|
||||||
|
pub fn new(f: F) -> Self {
|
||||||
|
Self {
|
||||||
|
_state_ty: std::marker::PhantomData::default(),
|
||||||
|
_user_ty: std::marker::PhantomData::default(),
|
||||||
|
func: f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <const CODE: u8, S: Send + Sync, U: Send + Sync, F: (Fn(ParameterTable, &mut S, &U) -> OperationResponse) + Send + Sync> super::Operation for Func<CODE, S, U, F> {
|
||||||
|
type State = S;
|
||||||
|
type User = U;
|
||||||
|
|
||||||
|
fn handle(&self, p: polariton::operation::ParameterTable, s: &mut Self::State, u: &Self::User) -> OperationResponse {
|
||||||
|
(self.func)(p, s, u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <const CODE: u8, S: Send + Sync, U: Send + Sync, F: (Fn(ParameterTable, &mut S, &U) -> OperationResponse) + Send + Sync> super::OperationCode for Func<CODE, S, U, F> {
|
||||||
|
fn op_code() -> u8 {
|
||||||
|
CODE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SimpleFunc<const CODE: u8, U: Send + Sync, F: (Fn(ParameterTable, &U) -> Result<ParameterTable, i16>) + Send + Sync> {
|
||||||
|
_user_ty: std::marker::PhantomData<U>,
|
||||||
|
func: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <const CODE: u8, U: Send + Sync, F: (Fn(ParameterTable, &U) -> Result<ParameterTable, i16>) + Send + Sync> SimpleFunc<CODE, U, F> {
|
||||||
|
pub fn new(f: F) -> Self {
|
||||||
|
Self {
|
||||||
|
_user_ty: std::marker::PhantomData::default(),
|
||||||
|
func: f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <const CODE: u8, U: Send + Sync, F: (Fn(ParameterTable, &U) -> Result<ParameterTable, i16>) + Send + Sync> super::Operation for SimpleFunc<CODE, U, F> {
|
||||||
|
type State = ();
|
||||||
|
type User = U;
|
||||||
|
|
||||||
|
fn handle(&self, p: polariton::operation::ParameterTable, _: &mut Self::State, u: &Self::User) -> OperationResponse {
|
||||||
|
match (self.func)(p, u) {
|
||||||
|
Ok(p_out) => {
|
||||||
|
OperationResponse {
|
||||||
|
code: CODE,
|
||||||
|
return_code: 0,
|
||||||
|
message: polariton::operation::Typed::Null,
|
||||||
|
params: p_out,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e_code) => {
|
||||||
|
OperationResponse {
|
||||||
|
code: CODE,
|
||||||
|
return_code: e_code,
|
||||||
|
message: polariton::operation::Typed::Null,
|
||||||
|
params: std::collections::HashMap::new().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <const CODE: u8, U: Send + Sync, F: (Fn(ParameterTable, &U) -> Result<ParameterTable, i16>) + Send + Sync> super::OperationCode for SimpleFunc<CODE, U, F> {
|
||||||
|
fn op_code() -> u8 {
|
||||||
|
CODE
|
||||||
|
}
|
||||||
|
}
|
92
server/src/operations/handler.rs
Normal file
92
server/src/operations/handler.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use polariton::operation::{OperationResponse, ParameterTable, OperationRequest};
|
||||||
|
|
||||||
|
use super::{Operation, OperationCode};
|
||||||
|
|
||||||
|
trait WrappedOperation<U: Send + Sync>: Send + Sync {
|
||||||
|
fn handle(&self, params: ParameterTable, user: &U) -> OperationResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SyncedOpWrapper<S: Send + Sync, O: Operation<State=S>> {
|
||||||
|
state: Mutex<S>,
|
||||||
|
handler: O,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl <S: Send + Sync, U: Send + Sync, O: Operation<State=S, User=U>> WrappedOperation<U> for SyncedOpWrapper<S, O> {
|
||||||
|
fn handle(&self, params: ParameterTable, user: &U) -> OperationResponse {
|
||||||
|
self.handler.handle(params, &mut *self.state.lock().unwrap(), user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StatelessOpWrapper<O: Operation<State=()>> {
|
||||||
|
handler: O,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl <U: Send + Sync, O: Operation<State=(), User=U>> WrappedOperation<U> for StatelessOpWrapper<O> {
|
||||||
|
fn handle(&self, params: ParameterTable, user: &U) -> OperationResponse {
|
||||||
|
self.handler.handle(params, &mut (), user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OperationsHandler<U: Send + Sync> {
|
||||||
|
op_map: HashMap<u8, Box<dyn WrappedOperation<U>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <U: Send + Sync> OperationsHandler<U> {
|
||||||
|
const SERVICE_MAPPING_KEY: u8 = 0;
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
op_map: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_state<S: Send + Sync + 'static, O: Operation<State=S, User=U> + OperationCode + 'static>(mut self, op: O, state: S) -> Self {
|
||||||
|
self.op_map.insert(O::op_code(), Box::new(SyncedOpWrapper {
|
||||||
|
state: Mutex::new(state),
|
||||||
|
handler: op,
|
||||||
|
}));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn without_state<O: Operation<State=(), User=U> + OperationCode + 'static>(mut self, op: O) -> Self {
|
||||||
|
self.op_map.insert(O::op_code(), Box::new(StatelessOpWrapper {
|
||||||
|
handler: op,
|
||||||
|
}));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_pass_to_handler(&self, code: u8, params: ParameterTable, user:&U) -> OperationResponse {
|
||||||
|
if let Some(handler) = self.op_map.get(&code) {
|
||||||
|
handler.handle(params, user)
|
||||||
|
} else {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
panic!("No handler for op code {}, pls fix!! params: {:?}", code, params.clone().to_dict());
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
{
|
||||||
|
log::debug!("No handler for op code {}, echoing params {:?}", code, params.clone().to_dict());
|
||||||
|
OperationResponse {
|
||||||
|
code,
|
||||||
|
return_code: 0,
|
||||||
|
message: polariton::operation::Typed::Null,
|
||||||
|
params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_op(&self, user: &U, req: OperationRequest) -> OperationResponse {
|
||||||
|
let mut op_resp = self.try_pass_to_handler(req.code, req.params.clone(), user);
|
||||||
|
if let Some(svelto_service_id) = req.params.clone().to_dict().remove(&Self::SERVICE_MAPPING_KEY) {
|
||||||
|
// make sure to do GUID passthrough
|
||||||
|
let mut dict_params = op_resp.params.to_dict();
|
||||||
|
dict_params.insert(Self::SERVICE_MAPPING_KEY, svelto_service_id);
|
||||||
|
op_resp.params = dict_params.into();
|
||||||
|
}
|
||||||
|
op_resp
|
||||||
|
}
|
||||||
|
}
|
11
server/src/operations/mod.rs
Normal file
11
server/src/operations/mod.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
mod handler;
|
||||||
|
pub use handler::OperationsHandler;
|
||||||
|
|
||||||
|
mod traits;
|
||||||
|
pub use traits::{Operation, OperationCode};
|
||||||
|
|
||||||
|
mod ack;
|
||||||
|
pub use ack::Ack;
|
||||||
|
|
||||||
|
mod functional;
|
||||||
|
pub use functional::{Func, SimpleFunc};
|
12
server/src/operations/traits.rs
Normal file
12
server/src/operations/traits.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
use polariton::operation::{OperationResponse, ParameterTable};
|
||||||
|
|
||||||
|
pub trait Operation: Send + Sync {
|
||||||
|
type State;
|
||||||
|
type User;
|
||||||
|
|
||||||
|
fn handle(&self, params: ParameterTable, state: &mut Self::State, user: &Self::User) -> OperationResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait OperationCode {
|
||||||
|
fn op_code() -> u8;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue