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}