cat_dev/net/server/requestable/
state.rs1use crate::{
6 errors::CatBridgeError,
7 net::{
8 models::{FromRef, FromRequest, FromRequestParts, Request},
9 server::models::{FromResponseStreamEvent, ResponseStreamEvent},
10 },
11};
12use std::{
13 fmt::{Debug, Formatter, Result as FmtResult},
14 ops::{Deref, DerefMut},
15};
16use valuable::{Fields, NamedField, NamedValues, StructDef, Structable, Valuable, Value, Visit};
17
18pub struct State<Ty: Clone + Send + Sync + 'static>(pub Ty);
20
21impl<
22 OuterState: Clone + Send + Sync + 'static,
23 InnerState: FromRef<OuterState> + Clone + Send + Sync + 'static,
24> FromRequestParts<OuterState> for State<InnerState>
25{
26 async fn from_request_parts(req: &mut Request<OuterState>) -> Result<Self, CatBridgeError> {
27 Ok(Self(InnerState::from_ref(req.state())))
28 }
29}
30
31impl<
32 OuterState: Clone + Send + Sync + 'static,
33 InnerState: FromRef<OuterState> + Clone + Send + Sync + 'static,
34> FromRequest<OuterState> for State<InnerState>
35{
36 async fn from_request(req: Request<OuterState>) -> Result<Self, CatBridgeError> {
37 Ok(Self(InnerState::from_ref(req.state())))
38 }
39}
40
41impl<
42 OuterState: Clone + Send + Sync + 'static,
43 InnerState: FromRef<OuterState> + Clone + Send + Sync + 'static,
44> FromResponseStreamEvent<OuterState> for State<InnerState>
45{
46 async fn from_stream_event(
47 evt: &mut ResponseStreamEvent<OuterState>,
48 ) -> Result<Self, CatBridgeError> {
49 Ok(Self(InnerState::from_ref(evt.state())))
50 }
51}
52
53impl<Ty: Clone + Send + Sync + 'static> Deref for State<Ty> {
54 type Target = Ty;
55
56 fn deref(&self) -> &Self::Target {
57 &self.0
58 }
59}
60
61impl<Ty: Clone + Send + Sync + 'static> DerefMut for State<Ty> {
62 fn deref_mut(&mut self) -> &mut Self::Target {
63 &mut self.0
64 }
65}
66
67impl<Ty: Clone + Send + Sync + 'static> Debug for State<Ty>
68where
69 Ty: Debug,
70{
71 fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
72 fmt.debug_struct("State").field("inner", &self.0).finish()
73 }
74}
75
76const STATE_FIELDS: &[NamedField<'static>] = &[NamedField::new("inner")];
77
78impl<Ty: Clone + Send + Sync + 'static> Structable for State<Ty>
79where
80 Ty: Valuable,
81{
82 fn definition(&self) -> StructDef<'_> {
83 StructDef::new_static("State", Fields::Named(STATE_FIELDS))
84 }
85}
86
87impl<Ty: Clone + Send + Sync + 'static> Valuable for State<Ty>
88where
89 Ty: Valuable,
90{
91 fn as_value(&self) -> Value<'_> {
92 Value::Structable(self)
93 }
94
95 fn visit(&self, visitor: &mut dyn Visit) {
96 visitor.visit_named_fields(&NamedValues::new(STATE_FIELDS, &[self.0.as_value()]));
97 }
98}
99
100#[cfg(test)]
101mod unit_tests {
102 use super::*;
103 use crate::net::server::router::{Router, test_helpers::router_body_no_close_with_state};
104
105 #[tokio::test]
106 pub async fn test_state() {
107 async fn echo_state(State(data): State<String>) -> String {
108 data
109 }
110
111 let mut router = Router::<String>::new();
112 router
113 .add_route(&[0x1], echo_state)
114 .expect("Failed to add route!");
115 assert_eq!(
116 router_body_no_close_with_state(
117 &mut router,
118 &[0x1, 0x2, 0x3, 0x4],
119 "Hey from state!".to_owned(),
120 )
121 .await,
122 b"Hey from state!",
123 );
124 }
125}