Skip to main content

ahri_tre_protocol/
protocol_envelope.rs

1use crate::{
2    ProtocolVersion, RequestId, public_error::ProtocolError, request::ProtocolRequest,
3    warning::ProtocolWarning,
4};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct ProtocolRequestEnvelope {
9    #[serde(default, skip_serializing_if = "Option::is_none")]
10    pub request_id: Option<RequestId>,
11    pub protocol_version: ProtocolVersion,
12    #[serde(flatten)]
13    pub request: ProtocolRequest,
14}
15
16impl ProtocolRequestEnvelope {
17    /// Check the envelope version before interpreting any version-specific body.
18    /// Malformed or absent versions remain the caller's envelope-validation error.
19    pub fn reject_unsupported_version(
20        value: &serde_json::Value,
21    ) -> Option<ProtocolFailureEnvelope> {
22        let requested = value.get("protocol_version")?.as_str()?;
23        let version = ProtocolVersion::parse(requested).ok()?;
24        let current = ProtocolVersion::current();
25        version.ensure_supported(&current).err()?;
26        let request_id = value
27            .get("request_id")
28            .cloned()
29            .and_then(|id| serde_json::from_value(id).ok())
30            .unwrap_or_default();
31        Some(ProtocolFailureEnvelope::new(
32            request_id,
33            version,
34            crate::request::kind::PROTOCOL_INVALID_REQUEST,
35            ProtocolError::new(
36                crate::public_error::ProtocolErrorCode::UnsupportedProtocolVersion,
37                "unsupported protocol version",
38            )
39            .with_target("protocol_version")
40            .with_details(
41                crate::public_error::ProtocolErrorDetails::UnsupportedProtocolVersion {
42                    requested: requested.to_string(),
43                    supported: current.to_string(),
44                },
45            ),
46        ))
47    }
48
49    pub fn new(protocol_version: ProtocolVersion, request: ProtocolRequest) -> Self {
50        Self {
51            request_id: None,
52            protocol_version,
53            request,
54        }
55    }
56
57    pub fn kind(&self) -> &'static str {
58        self.request.kind()
59    }
60}
61
62#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
63#[serde(untagged)]
64pub enum ProtocolResponseEnvelope<T> {
65    Success(ProtocolSuccessEnvelope<T>),
66    Failure(ProtocolFailureEnvelope),
67}
68
69#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
70pub struct ProtocolSuccessEnvelope<T> {
71    pub ok: bool,
72    pub request_id: RequestId,
73    pub protocol_version: ProtocolVersion,
74    pub kind: String,
75    pub warnings: Vec<ProtocolWarning>,
76    pub data: T,
77    /// Internal Trusted-to-Managed handoff; Managed consumes it before returning data.
78    #[serde(default, skip_serializing_if = "Option::is_none")]
79    pub content_transfer: Option<Box<crate::content::ContentDescriptor>>,
80}
81
82impl<T> ProtocolSuccessEnvelope<T> {
83    pub fn new(
84        request_id: RequestId,
85        protocol_version: ProtocolVersion,
86        kind: impl Into<String>,
87        data: T,
88    ) -> Self {
89        Self {
90            ok: true,
91            request_id,
92            protocol_version,
93            kind: kind.into(),
94            warnings: Vec::new(),
95            data,
96            content_transfer: None,
97        }
98    }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
102pub struct ProtocolFailureEnvelope {
103    pub ok: bool,
104    pub request_id: RequestId,
105    pub protocol_version: ProtocolVersion,
106    pub kind: String,
107    pub warnings: Vec<ProtocolWarning>,
108    pub error: ProtocolError,
109}
110
111impl ProtocolFailureEnvelope {
112    pub fn new(
113        request_id: RequestId,
114        protocol_version: ProtocolVersion,
115        kind: impl Into<String>,
116        error: ProtocolError,
117    ) -> Self {
118        Self {
119            ok: false,
120            request_id,
121            protocol_version,
122            kind: kind.into(),
123            warnings: Vec::new(),
124            error,
125        }
126    }
127}