tc_chain/
public.rs

1use std::fmt;
2use std::marker::PhantomData;
3
4use log::debug;
5use safecast::TryCastFrom;
6
7use tc_collection::Collection;
8use tc_scalar::Scalar;
9use tc_transact::fs;
10use tc_transact::public::*;
11use tc_transact::Transaction;
12use tcgeneric::{PathSegment, TCPath};
13
14use super::{BlockChain, CacheBlock, Chain, ChainInstance, ChainType};
15
16impl<State: StateInstance> Route<State> for ChainType {
17    fn route<'a>(&'a self, _path: &'a [PathSegment]) -> Option<Box<dyn Handler<'a, State> + 'a>> {
18        None
19    }
20}
21
22struct AppendHandler<'a, C, T> {
23    chain: &'a C,
24    phantom: PhantomData<T>,
25}
26
27impl<'a, C, T> AppendHandler<'a, C, T> {
28    fn new(chain: &'a C) -> Self {
29        Self {
30            chain,
31            phantom: PhantomData,
32        }
33    }
34}
35
36impl<'a, State, C, T> Handler<'a, State> for AppendHandler<'a, C, T>
37where
38    State: StateInstance,
39    C: ChainInstance<State, T> + Send + Sync + 'a,
40    T: Route<State> + fmt::Debug + 'a,
41    Chain<State, State::Txn, State::FE, T>: ChainInstance<State, T>,
42{
43    fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
44    where
45        'b: 'a,
46    {
47        let handler = self.chain.subject().route(&[])?;
48        handler.get()
49    }
50
51    fn put<'b>(self: Box<Self>) -> Option<PutHandler<'a, 'b, State::Txn, State>>
52    where
53        'b: 'a,
54    {
55        match self.chain.subject().route(&[]) {
56            Some(handler) => match handler.put() {
57                Some(put_handler) => Some(Box::new(|txn, key, value| {
58                    Box::pin(async move {
59                        debug!("Chain::put {} <- {:?}", key, value);
60
61                        self.chain
62                            .append_put(txn.clone(), key.clone(), value.clone())?;
63
64                        put_handler(txn, key, value).await
65                    })
66                })),
67                None => None,
68            },
69            None => None,
70        }
71    }
72
73    fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
74    where
75        'b: 'a,
76    {
77        let handler = self.chain.subject().route(&[])?;
78        handler.post()
79    }
80
81    fn delete<'b>(self: Box<Self>) -> Option<DeleteHandler<'a, 'b, State::Txn>>
82    where
83        'b: 'a,
84    {
85        match self.chain.subject().route(&[]) {
86            Some(handler) => match handler.delete() {
87                Some(delete_handler) => Some(Box::new(|txn, key| {
88                    Box::pin(async move {
89                        debug!("Chain::delete {}", key);
90                        self.chain.append_delete(*txn.id(), key.clone())?;
91                        delete_handler(txn, key).await
92                    })
93                })),
94                None => None,
95            },
96            None => None,
97        }
98    }
99}
100
101impl<State, T> Route<State> for Chain<State, State::Txn, State::FE, T>
102where
103    State: StateInstance,
104    T: fs::Persist<State::FE, Txn = State::Txn> + Route<State> + Clone + fmt::Debug,
105    Self: ChainInstance<State, T>,
106{
107    fn route<'a>(&'a self, path: &'a [PathSegment]) -> Option<Box<dyn Handler<'a, State> + 'a>> {
108        debug!("Chain::route {}", TCPath::from(path));
109
110        if path.is_empty() {
111            Some(Box::new(AppendHandler::new(self)))
112        } else {
113            self.subject().route(path)
114        }
115    }
116}
117
118impl<State, T> Route<State> for BlockChain<State, State::Txn, State::FE, T>
119where
120    State: StateInstance,
121    State::FE: CacheBlock + for<'a> fs::FileSave<'a>,
122    T: fs::Persist<State::FE, Txn = State::Txn> + Route<State> + Clone + fmt::Debug,
123    Collection<State::Txn, State::FE>: TryCastFrom<State>,
124    Scalar: TryCastFrom<State>,
125{
126    fn route<'a>(&'a self, path: &'a [PathSegment]) -> Option<Box<dyn Handler<'a, State> + 'a>> {
127        debug!("Chain::route {}", TCPath::from(path));
128
129        if path.is_empty() {
130            Some(Box::new(AppendHandler::new(self)))
131        } else {
132            self.subject().route(path)
133        }
134    }
135}