|
1 | | -use tucana::shared::{Struct, Value}; |
2 | | -use tucana::shared::value::Kind; |
3 | 1 | use crate::context::Context; |
4 | 2 | use crate::context::signal::Signal; |
5 | 3 | use crate::error::RuntimeError; |
6 | 4 | use crate::registry::HandlerFn; |
| 5 | +use tucana::shared::value::Kind; |
| 6 | +use tucana::shared::{Struct, Value}; |
7 | 7 |
|
8 | 8 | pub fn collect_http_functions() -> Vec<(&'static str, HandlerFn)> { |
9 | 9 | vec![ |
10 | 10 | ("http::request::create", create_request), |
11 | 11 | ("http::response::create", create_response), |
| 12 | + ("http::control::respond", respond), |
12 | 13 | ] |
13 | 14 | } |
14 | 15 |
|
| 16 | +fn respond(values: &[Value], _ctx: &mut Context) -> Signal { |
| 17 | + let [ |
| 18 | + Value { |
| 19 | + kind: Some(Kind::StructValue(struct_val)), |
| 20 | + }, |
| 21 | + ] = values |
| 22 | + else { |
| 23 | + return Signal::Failure(RuntimeError::simple( |
| 24 | + "InvalidArgumentRuntimeError", |
| 25 | + format!("Expected exactly one response struct, got {:?}", values), |
| 26 | + )); |
| 27 | + }; |
| 28 | + |
| 29 | + let fields = &struct_val.fields; |
| 30 | + |
| 31 | + let Some(headers_val) = fields.get("headers") else { |
| 32 | + return Signal::Failure(RuntimeError::simple( |
| 33 | + "InvalidArgumentRuntimeError", |
| 34 | + "Missing 'headers' field".to_string(), |
| 35 | + )); |
| 36 | + }; |
| 37 | + |
| 38 | + let Some(status_code_val) = fields.get("status_code") else { |
| 39 | + return Signal::Failure(RuntimeError::simple( |
| 40 | + "InvalidArgumentRuntimeError", |
| 41 | + "Missing 'status_code' field".to_string(), |
| 42 | + )); |
| 43 | + }; |
| 44 | + |
| 45 | + let Some(payload_val) = fields.get("payload") else { |
| 46 | + return Signal::Failure(RuntimeError::simple( |
| 47 | + "InvalidArgumentRuntimeError", |
| 48 | + "Missing 'payload' field".to_string(), |
| 49 | + )); |
| 50 | + }; |
| 51 | + |
| 52 | + let Some(Kind::StructValue(_headers_struct)) = &headers_val.kind else { |
| 53 | + return Signal::Failure(RuntimeError::simple( |
| 54 | + "InvalidArgumentRuntimeError", |
| 55 | + "Expected 'headers' to be StructValue".to_string(), |
| 56 | + )); |
| 57 | + }; |
| 58 | + |
| 59 | + let Some(Kind::StringValue(_status_code_str)) = &status_code_val.kind else { |
| 60 | + return Signal::Failure(RuntimeError::simple( |
| 61 | + "InvalidArgumentRuntimeError", |
| 62 | + "Expected 'status_code' to be StringValue".to_string(), |
| 63 | + )); |
| 64 | + }; |
| 65 | + |
| 66 | + let Some(_payload_kind) = &payload_val.kind else { |
| 67 | + return Signal::Failure(RuntimeError::simple( |
| 68 | + "InvalidArgumentRuntimeError", |
| 69 | + "Expected 'payload' to have a value".to_string(), |
| 70 | + )); |
| 71 | + }; |
| 72 | + |
| 73 | + Signal::Respond(Value { |
| 74 | + kind: Some(Kind::StructValue(struct_val.clone())), |
| 75 | + }) |
| 76 | +} |
| 77 | + |
15 | 78 | fn create_request(values: &[Value], _ctx: &mut Context) -> Signal { |
16 | | - let [Value { |
17 | | - kind: Some(Kind::StringValue(http_method)), |
18 | | - }, |
19 | | - Value { |
20 | | - kind: Some(Kind::StructValue(headers)), |
21 | | - }, |
22 | | - Value { |
23 | | - kind: Some(Kind::StringValue(http_url)), |
24 | | - }, |
25 | | - payload |
| 79 | + let [ |
| 80 | + Value { |
| 81 | + kind: Some(Kind::StringValue(http_method)), |
| 82 | + }, |
| 83 | + Value { |
| 84 | + kind: Some(Kind::StructValue(headers)), |
| 85 | + }, |
| 86 | + Value { |
| 87 | + kind: Some(Kind::StringValue(http_url)), |
| 88 | + }, |
| 89 | + payload, |
26 | 90 | ] = values |
27 | 91 | else { |
28 | 92 | return Signal::Failure(RuntimeError::simple( |
29 | 93 | "InvalidArgumentRuntimeError", |
30 | | - format!("Expected [method, headers, url, payload] but received {:?}", values), |
| 94 | + format!( |
| 95 | + "Expected [method, headers, url, payload] but received {:?}", |
| 96 | + values |
| 97 | + ), |
31 | 98 | )); |
32 | 99 | }; |
33 | 100 |
|
34 | 101 | let mut fields = std::collections::HashMap::new(); |
35 | 102 |
|
36 | | - fields.insert("method".to_string(), Value { |
37 | | - kind: Some(Kind::StringValue(http_method.clone())), |
38 | | - }); |
| 103 | + fields.insert( |
| 104 | + "method".to_string(), |
| 105 | + Value { |
| 106 | + kind: Some(Kind::StringValue(http_method.clone())), |
| 107 | + }, |
| 108 | + ); |
39 | 109 |
|
40 | | - fields.insert("url".to_string(), Value { |
41 | | - kind: Some(Kind::StringValue(http_url.clone())), |
42 | | - }); |
| 110 | + fields.insert( |
| 111 | + "url".to_string(), |
| 112 | + Value { |
| 113 | + kind: Some(Kind::StringValue(http_url.clone())), |
| 114 | + }, |
| 115 | + ); |
43 | 116 |
|
44 | | - fields.insert("headers".to_string(),Value { |
45 | | - kind: Some(Kind::StructValue(headers.clone())), |
46 | | - }); |
| 117 | + fields.insert( |
| 118 | + "headers".to_string(), |
| 119 | + Value { |
| 120 | + kind: Some(Kind::StructValue(headers.clone())), |
| 121 | + }, |
| 122 | + ); |
47 | 123 | fields.insert("body".to_string(), payload.clone()); |
48 | 124 |
|
49 | | - Signal::Success(Value { |
| 125 | + Signal::Success(Value { |
50 | 126 | kind: Some(Kind::StructValue(Struct { fields })), |
51 | 127 | }) |
52 | 128 | } |
53 | 129 |
|
54 | 130 | fn create_response(values: &[Value], _ctx: &mut Context) -> Signal { |
55 | | - let [Value { |
56 | | - kind: Some(Kind::NumberValue(http_status_code)), |
57 | | - }, |
58 | | - Value { |
59 | | - kind: Some(Kind::StructValue(headers)), |
60 | | - }, |
61 | | - payload |
| 131 | + let [ |
| 132 | + Value { |
| 133 | + kind: Some(Kind::NumberValue(http_status_code)), |
| 134 | + }, |
| 135 | + Value { |
| 136 | + kind: Some(Kind::StructValue(headers)), |
| 137 | + }, |
| 138 | + payload, |
62 | 139 | ] = values |
63 | 140 | else { |
64 | 141 | return Signal::Failure(RuntimeError::simple( |
65 | 142 | "InvalidArgumentRuntimeError", |
66 | | - format!("Expected [http_status_code, headers, payload] but received {:?}", values), |
| 143 | + format!( |
| 144 | + "Expected [http_status_code, headers, payload] but received {:?}", |
| 145 | + values |
| 146 | + ), |
67 | 147 | )); |
68 | 148 | }; |
69 | 149 |
|
70 | 150 | let mut fields = std::collections::HashMap::new(); |
71 | 151 |
|
72 | | - fields.insert("method".to_string(), Value { |
73 | | - kind: Some(Kind::NumberValue(http_status_code.clone())), |
74 | | - }); |
| 152 | + fields.insert( |
| 153 | + "status_code".to_string(), |
| 154 | + Value { |
| 155 | + kind: Some(Kind::NumberValue(http_status_code.clone())), |
| 156 | + }, |
| 157 | + ); |
75 | 158 |
|
76 | | - fields.insert("headers".to_string(),Value { |
77 | | - kind: Some(Kind::StructValue(headers.clone())), |
78 | | - }); |
| 159 | + fields.insert( |
| 160 | + "headers".to_string(), |
| 161 | + Value { |
| 162 | + kind: Some(Kind::StructValue(headers.clone())), |
| 163 | + }, |
| 164 | + ); |
79 | 165 | fields.insert("body".to_string(), payload.clone()); |
80 | 166 |
|
81 | 167 | Signal::Success(Value { |
82 | 168 | kind: Some(Kind::StructValue(Struct { fields })), |
83 | 169 | }) |
84 | 170 | } |
| 171 | + |
0 commit comments