Skip to main content

rustbridge_core/
request.rs

1//! Request and response context types
2
3use serde::{Deserialize, Serialize};
4
5/// Context for an incoming request
6#[derive(Debug, Clone)]
7pub struct RequestContext {
8    /// Unique request ID
9    pub request_id: u64,
10    /// Message type tag
11    pub type_tag: String,
12    /// Optional correlation ID for tracking across systems
13    pub correlation_id: Option<String>,
14}
15
16impl RequestContext {
17    /// Create a new request context
18    pub fn new(request_id: u64, type_tag: impl Into<String>) -> Self {
19        Self {
20            request_id,
21            type_tag: type_tag.into(),
22            correlation_id: None,
23        }
24    }
25
26    /// Set correlation ID
27    pub fn with_correlation_id(mut self, id: impl Into<String>) -> Self {
28        self.correlation_id = Some(id.into());
29        self
30    }
31}
32
33/// Builder for constructing responses
34#[derive(Debug)]
35pub struct ResponseBuilder {
36    data: Option<Vec<u8>>,
37    error: Option<ResponseError>,
38}
39
40/// Error information in a response
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct ResponseError {
43    /// Error code
44    pub code: u32,
45    /// Error message
46    pub message: String,
47    /// Optional detailed information
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub details: Option<serde_json::Value>,
50}
51
52impl ResponseBuilder {
53    /// Create a new response builder
54    pub fn new() -> Self {
55        Self {
56            data: None,
57            error: None,
58        }
59    }
60
61    /// Set successful response data
62    pub fn data(mut self, data: Vec<u8>) -> Self {
63        self.data = Some(data);
64        self
65    }
66
67    /// Set response data from a serializable value
68    pub fn json<T: Serialize>(mut self, value: &T) -> Result<Self, serde_json::Error> {
69        self.data = Some(serde_json::to_vec(value)?);
70        Ok(self)
71    }
72
73    /// Set error response
74    pub fn error(mut self, code: u32, message: impl Into<String>) -> Self {
75        self.error = Some(ResponseError {
76            code,
77            message: message.into(),
78            details: None,
79        });
80        self
81    }
82
83    /// Set error with details
84    pub fn error_with_details(
85        mut self,
86        code: u32,
87        message: impl Into<String>,
88        details: serde_json::Value,
89    ) -> Self {
90        self.error = Some(ResponseError {
91            code,
92            message: message.into(),
93            details: Some(details),
94        });
95        self
96    }
97
98    /// Build the response
99    pub fn build(self) -> ResponseResult {
100        if let Some(error) = self.error {
101            ResponseResult::Error(error)
102        } else {
103            ResponseResult::Success(self.data.unwrap_or_default())
104        }
105    }
106}
107
108impl Default for ResponseBuilder {
109    fn default() -> Self {
110        Self::new()
111    }
112}
113
114/// Result of building a response
115#[derive(Debug)]
116pub enum ResponseResult {
117    /// Successful response with data
118    Success(Vec<u8>),
119    /// Error response
120    Error(ResponseError),
121}
122
123impl ResponseResult {
124    /// Check if this is a success response
125    pub fn is_success(&self) -> bool {
126        matches!(self, ResponseResult::Success(_))
127    }
128
129    /// Get the data if this is a success response
130    pub fn data(&self) -> Option<&[u8]> {
131        match self {
132            ResponseResult::Success(data) => Some(data),
133            ResponseResult::Error(_) => None,
134        }
135    }
136
137    /// Get the error if this is an error response
138    pub fn error(&self) -> Option<&ResponseError> {
139        match self {
140            ResponseResult::Success(_) => None,
141            ResponseResult::Error(err) => Some(err),
142        }
143    }
144}
145
146#[cfg(test)]
147#[path = "request/request_tests.rs"]
148mod request_tests;