tc_transact/public/
mod.rs

1use std::fmt;
2use std::pin::Pin;
3
4use async_trait::async_trait;
5use futures::Future;
6
7use tc_error::*;
8use tc_value::{Number, Value};
9use tcgeneric::{Instance, Map, PathSegment, TCPath, ThreadSafe, Tuple};
10
11use super::{Gateway, Transaction};
12
13pub mod generic;
14pub mod helpers;
15pub mod number;
16pub mod string;
17pub mod value;
18
19pub type GetFuture<'a, State> = Pin<Box<dyn Future<Output = TCResult<State>> + Send + 'a>>;
20pub type GetHandler<'a, 'b, Txn, State> =
21    Box<dyn FnOnce(&'b Txn, Value) -> GetFuture<'a, State> + Send + 'a>;
22
23pub type PutFuture<'a> = Pin<Box<dyn Future<Output = TCResult<()>> + Send + 'a>>;
24pub type PutHandler<'a, 'b, Txn, State> =
25    Box<dyn FnOnce(&'b Txn, Value, State) -> PutFuture<'a> + Send + 'a>;
26
27pub type PostFuture<'a, State> = Pin<Box<dyn Future<Output = TCResult<State>> + Send + 'a>>;
28pub type PostHandler<'a, 'b, Txn, State> =
29    Box<dyn FnOnce(&'b Txn, Map<State>) -> PostFuture<'a, State> + Send + 'a>;
30
31pub type DeleteFuture<'a> = Pin<Box<dyn Future<Output = TCResult<()>> + Send + 'a>>;
32pub type DeleteHandler<'a, 'b, Txn> =
33    Box<dyn FnOnce(&'b Txn, Value) -> DeleteFuture<'a> + Send + 'a>;
34
35#[derive(Debug)]
36pub enum HandlerType {
37    Get,
38    Put,
39    Post,
40    Delete,
41}
42
43#[async_trait]
44pub trait ClosureInstance<State: StateInstance>: Send + Sync {
45    /// Execute this `ClosureInstance` with the given `args`
46    async fn call(self: Box<Self>, txn: State::Txn, args: State) -> TCResult<State>;
47}
48
49pub trait StateInstance:
50    Default
51    + Instance
52    + Route<Self>
53    + ToState<Self>
54    + From<bool>
55    + From<Number>
56    + From<Value>
57    + From<Map<Self>>
58    + From<Tuple<Self>>
59    + From<Self::Class>
60    + From<Self::Closure>
61    + Clone
62    + fmt::Debug
63    + 'static
64{
65    type FE: ThreadSafe + Clone;
66    type Txn: Transaction<Self::FE> + Gateway<Self>;
67    type Closure: ClosureInstance<Self>;
68
69    /// Return `true` if this is a `Map` of states.
70    fn is_map(&self) -> bool;
71
72    /// Return `true` if this is a `Tuple` of states.
73    fn is_tuple(&self) -> bool;
74}
75
76/// Trait to define a [`StateInstance`] representation of a (possibly non-[`StateInstance`]) value
77pub trait ToState<State: StateInstance> {
78    fn to_state(&self) -> State;
79}
80
81impl<State: StateInstance, T: Clone + Into<State>> ToState<State> for T {
82    fn to_state(&self) -> State {
83        self.clone().into()
84    }
85}
86
87#[async_trait]
88pub trait Handler<'a, State: StateInstance>: Send {
89    fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
90    where
91        'b: 'a,
92    {
93        None
94    }
95
96    fn put<'b>(self: Box<Self>) -> Option<PutHandler<'a, 'b, State::Txn, State>>
97    where
98        'b: 'a,
99    {
100        None
101    }
102
103    fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
104    where
105        'b: 'a,
106    {
107        None
108    }
109
110    fn delete<'b>(self: Box<Self>) -> Option<DeleteHandler<'a, 'b, State::Txn>>
111    where
112        'b: 'a,
113    {
114        None
115    }
116}
117
118pub trait Route<State>: Send + Sync {
119    fn route<'a>(&'a self, path: &'a [PathSegment]) -> Option<Box<dyn Handler<'a, State> + 'a>>;
120}
121
122#[async_trait]
123pub trait Public<State: StateInstance> {
124    async fn get(&self, txn: &State::Txn, path: &[PathSegment], key: Value) -> TCResult<State>;
125
126    async fn put(
127        &self,
128        txn: &State::Txn,
129        path: &[PathSegment],
130        key: Value,
131        value: State,
132    ) -> TCResult<()>;
133
134    async fn post(
135        &self,
136        txn: &State::Txn,
137        path: &[PathSegment],
138        params: Map<State>,
139    ) -> TCResult<State>;
140
141    async fn delete(&self, txn: &State::Txn, path: &[PathSegment], key: Value) -> TCResult<()>;
142}
143
144#[async_trait]
145impl<State: StateInstance, T: Route<State> + fmt::Debug> Public<State> for T {
146    async fn get(&self, txn: &State::Txn, path: &[PathSegment], key: Value) -> TCResult<State> {
147        let handler = self
148            .route(path)
149            .ok_or_else(|| TCError::not_found(TCPath::from(path)))?;
150
151        if let Some(get_handler) = handler.get() {
152            get_handler(txn, key).await
153        } else {
154            Err(TCError::method_not_allowed(
155                HandlerType::Get,
156                TCPath::from(path),
157            ))
158        }
159    }
160
161    async fn put(
162        &self,
163        txn: &State::Txn,
164        path: &[PathSegment],
165        key: Value,
166        value: State,
167    ) -> TCResult<()> {
168        let handler = self
169            .route(path)
170            .ok_or_else(|| not_found!("{} in {:?}", TCPath::from(path), self))?;
171
172        if let Some(put_handler) = handler.put() {
173            put_handler(txn, key, value).await
174        } else {
175            Err(TCError::method_not_allowed(
176                HandlerType::Put,
177                TCPath::from(path),
178            ))
179        }
180    }
181
182    async fn post(
183        &self,
184        txn: &State::Txn,
185        path: &[PathSegment],
186        params: Map<State>,
187    ) -> TCResult<State> {
188        let handler = self
189            .route(path)
190            .ok_or_else(|| TCError::not_found(TCPath::from(path)))?;
191
192        if let Some(post_handler) = handler.post() {
193            post_handler(txn, params).await
194        } else {
195            Err(TCError::method_not_allowed(
196                HandlerType::Post,
197                TCPath::from(path),
198            ))
199        }
200    }
201
202    async fn delete(&self, txn: &State::Txn, path: &[PathSegment], key: Value) -> TCResult<()> {
203        let handler = self
204            .route(path)
205            .ok_or_else(|| TCError::not_found(TCPath::from(path)))?;
206
207        if let Some(delete_handler) = handler.delete() {
208            delete_handler(txn, key).await
209        } else {
210            Err(TCError::method_not_allowed(
211                HandlerType::Delete,
212                TCPath::from(path),
213            ))
214        }
215    }
216}