opcua_types/
response_header.rs1use std::{
8 self,
9 io::{Read, Write},
10};
11
12use crate::{
13 data_types::*,
14 date_time::DateTime,
15 diagnostic_info::DiagnosticInfo,
16 encoding::{BinaryDecodable, BinaryEncodable, EncodingResult},
17 extension_object::ExtensionObject,
18 request_header::RequestHeader,
19 status_code::StatusCode,
20 string::UAString,
21 Error,
22};
23
24#[allow(unused)]
25mod opcua {
26 pub(super) use crate as types;
27}
28
29#[derive(Debug, Clone, PartialEq, Default, crate::UaNullable)]
31#[cfg_attr(
32 feature = "json",
33 derive(opcua_macros::JsonEncodable, opcua_macros::JsonDecodable)
34)]
35#[cfg_attr(
36 feature = "xml",
37 derive(crate::XmlEncodable, crate::XmlDecodable, crate::XmlType)
38)]
39pub struct ResponseHeader {
40 pub timestamp: UtcTime,
42 pub request_handle: IntegerId,
44 pub service_result: StatusCode,
46 pub service_diagnostics: DiagnosticInfo,
48 pub string_table: Option<Vec<UAString>>,
50 pub additional_header: ExtensionObject,
52}
53
54impl BinaryEncodable for ResponseHeader {
55 fn byte_len(&self, ctx: &opcua::types::Context<'_>) -> usize {
56 let mut size = 0;
57 size += self.timestamp.byte_len(ctx);
58 size += self.request_handle.byte_len(ctx);
59 size += self.service_result.byte_len(ctx);
60 size += self.service_diagnostics.byte_len(ctx);
61 size += self.string_table.byte_len(ctx);
62 size += self.additional_header.byte_len(ctx);
63 size
64 }
65
66 fn encode<S: Write + ?Sized>(
67 &self,
68 stream: &mut S,
69 ctx: &crate::Context<'_>,
70 ) -> EncodingResult<()> {
71 self.timestamp.encode(stream, ctx)?;
72 self.request_handle.encode(stream, ctx)?;
73 self.service_result.encode(stream, ctx)?;
74 self.service_diagnostics.encode(stream, ctx)?;
75 self.string_table.encode(stream, ctx)?;
76 self.additional_header.encode(stream, ctx)
77 }
78}
79
80impl BinaryDecodable for ResponseHeader {
81 fn decode<S: Read + ?Sized>(stream: &mut S, ctx: &crate::Context<'_>) -> EncodingResult<Self> {
82 let timestamp = UtcTime::decode(stream, ctx)?;
83 let request_handle = IntegerId::decode(stream, ctx)?;
84 let (service_result, service_diagnostics, string_table, additional_header) = (|| {
86 let service_result = StatusCode::decode(stream, ctx)?;
87 let service_diagnostics = DiagnosticInfo::decode(stream, ctx)?;
88 let string_table = BinaryDecodable::decode(stream, ctx)?;
89 let additional_header = ExtensionObject::decode(stream, ctx)?;
90 Ok((
91 service_result,
92 service_diagnostics,
93 string_table,
94 additional_header,
95 ))
96 })()
97 .map_err(|e: Error| e.with_request_handle(request_handle))?;
98 Ok(ResponseHeader {
99 timestamp,
100 request_handle,
101 service_result,
102 service_diagnostics,
103 string_table,
104 additional_header,
105 })
106 }
107}
108
109pub trait AsRequestHandle {
111 fn as_request_handle(&self) -> u32;
113}
114
115impl AsRequestHandle for &RequestHeader {
116 fn as_request_handle(&self) -> u32 {
117 self.request_handle
118 }
119}
120
121impl AsRequestHandle for u32 {
122 fn as_request_handle(&self) -> u32 {
123 *self
124 }
125}
126
127impl ResponseHeader {
128 pub fn new_good(request_header: impl AsRequestHandle) -> ResponseHeader {
130 ResponseHeader::new_service_result(request_header, StatusCode::Good)
131 }
132
133 pub fn new_service_result(
135 request_header: impl AsRequestHandle,
136 service_result: StatusCode,
137 ) -> ResponseHeader {
138 ResponseHeader::new_timestamped_service_result(
139 DateTime::now(),
140 request_header,
141 service_result,
142 )
143 }
144
145 pub fn new_timestamped_service_result(
147 timestamp: DateTime,
148 request_header: impl AsRequestHandle,
149 service_result: StatusCode,
150 ) -> ResponseHeader {
151 ResponseHeader {
152 timestamp,
153 request_handle: request_header.as_request_handle(),
154 service_result,
155 service_diagnostics: DiagnosticInfo::default(),
156 string_table: None,
157 additional_header: ExtensionObject::null(),
158 }
159 }
160
161 pub fn null() -> ResponseHeader {
163 ResponseHeader {
164 timestamp: DateTime::now(),
165 request_handle: 0,
166 service_result: StatusCode::Good,
167 service_diagnostics: DiagnosticInfo::default(),
168 string_table: None,
169 additional_header: ExtensionObject::null(),
170 }
171 }
172}