use futures::Future;
use serde::{Deserialize, Serialize};
use types::HttpMethod;
pub trait Procedure {
type Request: RpcRequest;
type Response: RpcResponse;
fn method() -> HttpMethod;
fn entry_point() -> EntryPoint;
}
pub trait HandleRpc<P>: Clone + Send + 'static
where
P: Procedure,
{
type Future: Future<Item = <P as Procedure>::Response, Error = NeverFail> + Send + 'static;
fn handle_rpc(self, request: <P as Procedure>::Request) -> Self::Future;
}
pub struct NeverFail {
_cannot_instantiate: (),
}
pub trait RpcRequest: Serialize + for<'a> Deserialize<'a> + Send + 'static {
fn body(&mut self) -> Vec<u8>;
fn read_body(self, body: ::BodyReader) -> ::ReadBody<Self>;
}
pub trait RpcResponse: Serialize + for<'a> Deserialize<'a> {
fn body(&mut self) -> Box<dyn AsRef<[u8]> + Send + 'static>;
fn set_body(&mut self, body: Vec<u8>);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EntryPoint {
segments: &'static [PathSegment],
}
impl EntryPoint {
pub fn new(segments: &'static [PathSegment]) -> Self {
EntryPoint { segments }
}
pub fn segments(&self) -> &'static [PathSegment] {
self.segments
}
pub fn var_count(&self) -> usize {
self.segments
.iter()
.filter(|s| s == &&PathSegment::Var)
.count()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PathSegment {
Val(&'static str),
Var,
}
impl PathSegment {
pub fn as_option(&self) -> Option<&'static str> {
if let PathSegment::Val(s) = *self {
Some(s)
} else {
None
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn it_works() {
use self::PathSegment::*;
static SEGMENTS: &[PathSegment] = &[Val("foo"), Var, Val("baz")];
let path0 = EntryPoint::new(SEGMENTS);
let path1 = htrpc_entry_point!["foo", _, "baz"];
assert_eq!(path0, path1);
}
}