Skip to main content

lenso_capability_http_client/
generated.rs

1// @generated by lenso-contract-codegen; do not edit.
2use std::{fmt, rc::Rc};
3use futures::future::LocalBoxFuture;
4use lenso_kernel::{InvocationContext, ModuleDependencies, NativeRequestEndpoint, NativeRequestFuture, NativeRequestHandle, RequestCapability, RuntimeFailure};
5
6pub const CAPABILITY_ID: &str = "lenso.http.client@1";
7pub const DESCRIPTOR_VERSION: &str = "1.0.1";
8pub const PORTABLE: bool = true;
9pub const CROSS_LANE_TRANSFER: bool = true;
10pub const CLIENT_CAPABILITY_ID: &str = CAPABILITY_ID;
11pub const CLIENT_DESCRIPTOR_VERSION: &str = DESCRIPTOR_VERSION;
12
13pub const SEND_OPERATION: &str = "send";
14
15pub use lenso_contract_runtime::{Bytes, UnknownDomainError};
16use lenso_contract_runtime::{decode_portable_json, encode_portable_json};
17
18#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
19pub struct SendRequest {
20    #[serde(rename = "body")]
21    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
22    pub body: Bytes,
23    #[serde(rename = "headers")]
24    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
25    pub headers: Vec<SendRequestHeadersItem>,
26    #[serde(rename = "method")]
27    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
28    pub method: String,
29    #[serde(rename = "url")]
30    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
31    pub url: String,
32}
33
34#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
35pub struct SendRequestHeadersItem {
36    #[serde(rename = "name")]
37    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
38    pub name: String,
39    #[serde(rename = "value")]
40    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
41    pub value: String,
42}
43
44#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
45pub struct SendResponse {
46    #[serde(rename = "body")]
47    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
48    pub body: Bytes,
49    #[serde(rename = "headers")]
50    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
51    pub headers: Vec<SendResponseHeadersItem>,
52    #[serde(rename = "status")]
53    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
54    pub status: i64,
55}
56
57#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
58pub struct SendResponseHeadersItem {
59    #[serde(rename = "name")]
60    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
61    pub name: String,
62    #[serde(rename = "value")]
63    #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
64    pub value: String,
65}
66
67#[derive(Clone, Debug, PartialEq)]
68pub enum SendError {
69    DestinationNotAllowed,
70    InvalidRequest,
71    RequestTooLarge,
72    ResponseTooLarge,
73    Timeout,
74    TransportFailure,
75    Unknown(UnknownDomainError),
76}
77
78#[derive(Debug)]
79pub struct Client;
80impl RequestCapability for Client {
81    type Request = SendRequest;
82    type Response = SendResponse;
83    type DomainError = SendError;
84    const ID: &'static str = CAPABILITY_ID;
85    const DESCRIPTOR_VERSION: &'static str = DESCRIPTOR_VERSION;
86
87    fn invoke_native(endpoint: &dyn NativeRequestEndpoint, operation: &str, request: Self::Request, context: InvocationContext) -> NativeRequestFuture<Self> {
88        if operation != SEND_OPERATION {
89            return lenso_kernel::invoke_typed_or_erased_native_request::<Self>(endpoint, operation, request, context);
90        }
91        let Some(typed_endpoint) = endpoint
92            .typed_endpoint()
93            .and_then(|endpoint| endpoint.downcast_ref::<ClientRequestEndpoint>())
94        else {
95            return lenso_kernel::invoke_typed_or_erased_native_request::<Self>(endpoint, operation, request, context);
96        };
97        Rc::clone(&typed_endpoint.provider).send(context, request)
98    }
99}
100
101impl serde::Serialize for SendError {
102    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103    where
104        S: serde::Serializer,
105    {
106        use serde::ser::SerializeMap;
107        match self {
108            Self::DestinationNotAllowed => serializer.serialize_str("destination_not_allowed"),
109            Self::InvalidRequest => serializer.serialize_str("invalid_request"),
110            Self::RequestTooLarge => serializer.serialize_str("request_too_large"),
111            Self::ResponseTooLarge => serializer.serialize_str("response_too_large"),
112            Self::Timeout => serializer.serialize_str("timeout"),
113            Self::TransportFailure => serializer.serialize_str("transport_failure"),
114            Self::Unknown(value) => {
115                let mut map = serializer.serialize_map(Some(1 + usize::from(value.payload.is_some()) + value.extra.len()))?;
116                map.serialize_entry("code", &value.code)?;
117                if let Some(payload) = &value.payload {
118                    map.serialize_entry("payload", payload)?;
119                }
120                for (key, extra) in &value.extra {
121                    map.serialize_entry(key, extra)?;
122                }
123                map.end()
124            },
125        }
126    }
127}
128
129impl<'de> serde::Deserialize<'de> for SendError {
130    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
131    where
132        D: serde::Deserializer<'de>,
133    {
134        let value = <serde_json::Value as serde::Deserialize>::deserialize(deserializer)?;
135        match value {
136            serde_json::Value::String(code) => match code.as_str() {
137                "destination_not_allowed" => Ok(Self::DestinationNotAllowed),
138                "invalid_request" => Ok(Self::InvalidRequest),
139                "request_too_large" => Ok(Self::RequestTooLarge),
140                "response_too_large" => Ok(Self::ResponseTooLarge),
141                "timeout" => Ok(Self::Timeout),
142                "transport_failure" => Ok(Self::TransportFailure),
143                _ => Ok(Self::Unknown(UnknownDomainError { code, payload: None, extra: std::collections::BTreeMap::new() })),
144            },
145            serde_json::Value::Object(mut object) => {
146                let Some(code) = object.remove("code").and_then(|value| value.as_str().map(ToOwned::to_owned)) else {
147                    return Err(serde::de::Error::custom("Domain Error object is missing a string code"));
148                };
149                let payload = object.remove("payload");
150                let extra = object.into_iter().collect::<std::collections::BTreeMap<_, _>>();
151                Ok(Self::Unknown(UnknownDomainError { code, payload, extra }))
152            }
153            other => Err(serde::de::Error::custom(format!("Domain Error must be a string or object, got {other}"))),
154        }
155    }
156}
157
158pub fn encode_send_request(value: &SendRequest) -> Result<String, serde_json::Error> { encode_portable_json(value) }
159pub fn decode_send_request(wire: &str) -> Result<SendRequest, serde_json::Error> { decode_portable_json(wire) }
160pub fn encode_send_response(value: &SendResponse) -> Result<String, serde_json::Error> { encode_portable_json(value) }
161pub fn decode_send_response(wire: &str) -> Result<SendResponse, serde_json::Error> { decode_portable_json(wire) }
162pub fn encode_send_error(value: &SendError) -> Result<String, serde_json::Error> { encode_portable_json(value) }
163pub fn decode_send_error(wire: &str) -> Result<SendError, serde_json::Error> { decode_portable_json(wire) }
164
165pub trait ClientProvider: fmt::Debug + 'static {
166    fn send(&self, context: InvocationContext, request: SendRequest) -> NativeRequestFuture<Client>;
167}
168
169#[derive(Debug)]
170struct ClientRequestEndpoint { provider: Rc<dyn ClientProvider> }
171
172#[derive(Debug)]
173pub struct ClientEndpoint<P: ClientProvider> { provider: Rc<P>, request_endpoint: ClientRequestEndpoint }
174impl<P: ClientProvider> ClientEndpoint<P> {
175    pub fn new(provider: P) -> Self {
176        let provider = Rc::new(provider);
177        let request_provider: Rc<dyn ClientProvider> = provider.clone();
178        Self { provider, request_endpoint: ClientRequestEndpoint { provider: request_provider } }
179    }
180}
181
182impl<P: ClientProvider> NativeRequestEndpoint for ClientEndpoint<P> {
183    fn capability_id(&self) -> &'static str { CAPABILITY_ID }
184    fn descriptor_version(&self) -> &'static str { DESCRIPTOR_VERSION }
185    fn operations(&self) -> &'static [&'static str] { &[
186        SEND_OPERATION,
187    ] }
188    fn typed_endpoint(&self) -> Option<&dyn std::any::Any> { Some(&self.request_endpoint) }
189    fn invoke(&self, operation: &str, request: Box<dyn std::any::Any>, context: InvocationContext) -> LocalBoxFuture<'static, Result<Result<Box<dyn std::any::Any>, Box<dyn std::any::Any>>, RuntimeFailure>> {
190        match operation {
191            SEND_OPERATION => {
192                let Ok(request) = request.downcast::<SendRequest>() else {
193                    return Box::pin(futures::future::ready(Err(RuntimeFailure::ProtocolViolation { capability: CAPABILITY_ID })));
194                };
195                let invocation = Rc::clone(&self.provider).send(context, *request);
196                Box::pin(async move {
197                    invocation.await.map(|result| {
198                        result
199                            .map(|value| Box::new(value) as Box<dyn std::any::Any>)
200                            .map_err(|error| Box::new(error) as Box<dyn std::any::Any>)
201                    })
202                })
203            }
204            _ => Box::pin(futures::future::ready(Err(RuntimeFailure::UnknownOperation { capability: CAPABILITY_ID, operation: operation.to_owned() }))),
205        }
206    }
207}
208
209#[derive(Debug)]
210pub struct ClientClient {
211    send: NativeRequestHandle<Client>,
212}
213impl ClientClient {
214    pub fn new(handle: NativeRequestHandle<Client>) -> Self {
215        Self { send: handle }
216    }
217
218    pub fn from_dependencies(dependencies: &ModuleDependencies) -> Result<Self, RuntimeFailure> {
219        Ok(Self {
220            send: dependencies.one::<Client>()?,
221        })
222    }
223
224    pub async fn send(&self, request: SendRequest) -> Result<SendResponse, ClientInvocationError> {
225        self.send.invoke(SEND_OPERATION, request).await
226            .map_err(ClientInvocationError::Runtime)?
227            .map_err(ClientInvocationError::Domain)
228    }
229
230    pub async fn send_with_context(&self, context: InvocationContext, request: SendRequest) -> Result<SendResponse, ClientInvocationError> {
231        self.send.invoke_with_context(SEND_OPERATION, context, request).await
232            .map_err(ClientInvocationError::Runtime)?
233            .map_err(ClientInvocationError::Domain)
234    }
235}
236
237#[derive(Clone, Debug, PartialEq)]
238pub enum ClientInvocationError {
239    Domain(SendError),
240    Runtime(RuntimeFailure),
241}