use std::any::Any;
use std::fmt::Debug;
use bytes::{Bytes, BytesMut};
use dce_util::result::{DceError, DceResult};
use log::{error, warn};
use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
use crate::api::{Api};
#[cfg(feature = "async")]
use async_trait::async_trait;
pub const CTX_KEY_SESSION: &str = "$#session#";
pub const CTX_KEY_RESP_SID: &str = "$#response-sid#";
#[derive(Debug)]
pub struct RpMeta<Req> {
req: Req,
resp_buffer: BytesMut,
ctx_data: HashMap<String, Box<dyn Any + Send>>,
}
impl<Req> RpMeta<Req> {
pub fn new(req: Req, ctx_data: Option<HashMap<String, Box<dyn Any + Send>>>) -> Self {
Self { req, resp_buffer: Default::default(), ctx_data: ctx_data.unwrap_or_default() }
}
pub fn raw(&self) -> &Req {
&self.req
}
pub fn raw_mut(&mut self) -> &mut Req {
&mut self.req
}
pub fn clear_buffer(&mut self) -> Vec<u8> {
self.resp_buffer.split().to_vec()
}
pub fn is_resp_empty(&self) -> bool {
self.resp_buffer.is_empty()
}
pub fn write(&mut self, bytes: Bytes) {
self.resp_buffer.extend(bytes);
}
pub fn write_string(&mut self, str: String) {
self.resp_buffer.extend(str.as_bytes());
}
pub fn set_ctx_data(&mut self, key: String, value: Box<dyn Any + Send>) {
self.ctx_data.insert(key, value);
}
pub fn ctx_data(&self, key: &str) -> Option<&Box<dyn Any + Send>> {
return self.ctx_data.get(key)
}
pub fn ctx_data_remove(&mut self, key: &str) -> Option<Box<dyn Any + Send>> {
return self.ctx_data.remove(key)
}
pub fn sid(&self) -> Option<&str> {
None
}
pub fn set_session(&mut self) {
}
pub fn session(&self) {
}
pub fn set_resp_sid(&mut self, sid: String) {
self.ctx_data.insert(CTX_KEY_RESP_SID.to_string(), Box::new(sid));
}
pub fn resp_sid(&self) -> Option<&str> {
self.ctx_data.get(CTX_KEY_RESP_SID).map(
| boxed | boxed.downcast_ref::<String>().map(
| resp_sid | resp_sid.as_str())
).flatten()
}
}
#[cfg_attr(feature = "async", async_trait)]
pub trait RoutableProtocol: Sized + Deref<Target = RpMeta<Self::Req>> + DerefMut + Send {
type Req;
fn id(&self) -> isize { 0 }
fn path(&self) -> &str;
fn sync_body(&mut self) -> DceResult<Bytes> {
unreachable!("Not implemented yet")
}
fn sync_body_string(&mut self) -> DceResult<String> {
self.sync_body().map(|bts| String::from_utf8_lossy(&bts).into_owned())
}
#[cfg(feature = "async")]
async fn body(&mut self) -> DceResult<Bytes> {
unreachable!("Not implemented yet")
}
#[cfg(feature = "async")]
async fn body_string(&mut self) -> DceResult<String> {
self.body().await.map(|bts| String::from_utf8_lossy(&bts).into_owned())
}
fn match_api(&self, apis: &Vec<&'static Api<Self>>) -> Option<&'static Api<Self>> {
apis.last().map(|a| *a)
}
fn try_print_err(&self, err: &Option<DceError>) {
if let Some(err) = err {
if err.public {
warn!("{}", err);
} else {
error!("{}", err);
}
}
}
}