cratestack_client_rust/client/
prepared.rs1use serde::{Deserialize, Serialize};
4
5use crate::{ClientError, RuntimeHeader};
6
7#[derive(Clone, Serialize, Deserialize)]
17#[serde(deny_unknown_fields)]
18pub struct PreparedCall {
19 pub(super) version: u8,
20 pub(super) base_url: String,
21 pub(super) method: String,
22 pub(super) path: String,
23 pub(super) route: String,
24 pub(super) params: Vec<String>,
25 pub(super) query: Option<String>,
26 pub(super) headers: Vec<RuntimeHeader>,
27 pub(super) body: Vec<u8>,
28 pub(super) content_type: String,
29 pub(super) plain_type: String,
30 pub(super) accept: String,
31 pub(super) op: String,
32 pub(super) contract: [u8; 32],
33 pub(super) key_tables: Vec<u8>,
34 pub(super) sealed: bool,
35}
36
37pub(super) const MAX_SERIALIZED: usize = 16 * 1024 * 1024;
38pub(super) const MAX_PAYLOAD: usize = 8 * 1024 * 1024;
39
40impl PreparedCall {
41 pub fn to_bytes(&self) -> Result<Vec<u8>, ClientError> {
43 self.validate()?;
44 let bytes = serde_json::to_vec(self).map_err(|e| bad(e.to_string()))?;
45 if bytes.len() > MAX_SERIALIZED {
46 return Err(bad("prepared descriptor exceeds 16 MiB"));
47 }
48 Ok(bytes)
49 }
50
51 pub fn from_bytes(bytes: &[u8]) -> Result<Self, ClientError> {
54 if bytes.len() > MAX_SERIALIZED {
55 return Err(bad("prepared descriptor exceeds 16 MiB"));
56 }
57 let call: Self = serde_json::from_slice(bytes).map_err(|e| bad(e.to_string()))?;
58 call.validate()?;
59 Ok(call)
60 }
61
62 pub(super) fn restore_identity_headers(
63 &self,
64 headers: &mut reqwest::header::HeaderMap,
65 ) -> Result<(), ClientError> {
66 for name in ["idempotency-key", "if-match"] {
67 headers.remove(name);
68 if let Some(saved) = self
69 .headers
70 .iter()
71 .find(|h| h.name.eq_ignore_ascii_case(name))
72 {
73 let value = reqwest::header::HeaderValue::from_str(&saved.value)
74 .map_err(|e| bad(e.to_string()))?;
75 headers.insert(reqwest::header::HeaderName::from_static(name), value);
76 }
77 }
78 Ok(())
79 }
80
81 pub fn payload(&self) -> &[u8] {
83 &self.body
84 }
85 pub fn payload_type(&self) -> &str {
87 &self.content_type
88 }
89 pub fn contract_sha(&self) -> &[u8; 32] {
91 &self.contract
92 }
93}
94
95pub(super) fn bad(message: impl Into<String>) -> ClientError {
96 ClientError::BadInput(message.into())
97}