tc_state/object/public/
instance.rs1use std::fmt;
2
3use futures::future;
4use log::{debug, info};
5
6use tc_error::*;
7use tc_transact::public::generic::COPY;
8use tc_transact::public::{GetHandler, Handler, Route, ToState};
9use tc_transact::{Gateway, Transaction};
10use tcgeneric::{Instance, PathSegment, TCPath};
11
12use crate::object::InstanceExt;
13use crate::{CacheBlock, State};
14
15use super::method::route_attr;
16
17struct CopyHandler<'a, T> {
18 instance: &'a T,
19}
20
21impl<'a, Txn, T> Handler<'a, State<Txn>> for CopyHandler<'a, T>
22where
23 Txn: Transaction<CacheBlock> + Gateway<State<Txn>>,
24 T: Instance + fmt::Debug + 'a,
25{
26 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, Txn, State<Txn>>>
27 where
28 'b: 'a,
29 {
30 Some(Box::new(move |_txn, _key| {
31 Box::pin(future::ready(Err(not_implemented!(
32 "{:?} has no /copy method",
33 self.instance
34 ))))
35 }))
36 }
37}
38
39impl<'a, T> From<&'a T> for CopyHandler<'a, T> {
40 fn from(instance: &'a T) -> Self {
41 Self { instance }
42 }
43}
44
45impl<Txn, T> Route<State<Txn>> for InstanceExt<Txn, T>
46where
47 Txn: Transaction<CacheBlock> + Gateway<State<Txn>>,
48 T: ToState<State<Txn>> + Instance + Route<State<Txn>> + fmt::Debug,
49 Self: ToState<State<Txn>>,
50{
51 fn route<'a>(
52 &'a self,
53 path: &'a [PathSegment],
54 ) -> Option<Box<dyn Handler<'a, State<Txn>> + 'a>> {
55 debug!(
56 "{:?} with members {:?} route {} (parent is {} {:?})",
57 self,
58 self.members(),
59 TCPath::from(path),
60 std::any::type_name::<T>(),
61 self.parent()
62 );
63
64 if path.is_empty() {
65 debug!("routing to parent: {:?}", self.parent());
66
67 if let Some(handler) = self.parent().route(path) {
68 Some(handler)
69 } else if path == ©[..] {
70 info!("tried to copy an public with no /copy method implemented");
71 Some(Box::new(CopyHandler::from(self)))
72 } else {
73 debug!("{:?} has no handler for {}", self, TCPath::from(path));
74 None
75 }
76 } else if let Some(attr) = self.members().get(&path[0]) {
77 debug!("{} found in {:?} members: {:?}", &path[0], self, attr);
78
79 if let State::Scalar(attr) = attr {
80 route_attr(self, &path[0], attr, &path[1..])
81 } else {
82 attr.route(&path[1..])
83 }
84 } else if let Some(attr) = self.proto().get(&path[0]) {
85 debug!("{} found in instance proto", &path[0]);
86 route_attr(self, &path[0], attr, &path[1..])
87 } else if let Some(handler) = self.parent().route(path) {
88 debug!("{} found in parent", TCPath::from(path));
89 Some(handler)
90 } else if let Some(attr) = self.proto().get(&path[0]) {
91 debug!("{} found in class proto", path[0]);
92 attr.route(&path[1..])
93 } else {
94 debug!(
95 "not found in {:?}: {} (while resolving {})",
96 self,
97 &path[0],
98 TCPath::from(path)
99 );
100
101 None
102 }
103 }
104}