Skip to main content

opcua/types/
response_header.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5use std::{
6    self,
7    io::{Read, Write},
8};
9
10use crate::types::{
11    data_types::*, date_time::DateTime, diagnostic_info::DiagnosticInfo, encoding::*,
12    extension_object::ExtensionObject, request_header::RequestHeader, status_codes::StatusCode,
13    string::UAString,
14};
15
16/// The `ResponseHeader` contains information common to every response from server to client.
17#[derive(Debug, Clone, PartialEq)]
18pub struct ResponseHeader {
19    pub timestamp: UtcTime,
20    pub request_handle: IntegerId,
21    pub service_result: StatusCode,
22    pub service_diagnostics: DiagnosticInfo,
23    pub string_table: Option<Vec<UAString>>,
24    pub additional_header: ExtensionObject,
25}
26
27impl BinaryEncoder<ResponseHeader> for ResponseHeader {
28    fn byte_len(&self) -> usize {
29        let mut size = 0;
30        size += self.timestamp.byte_len();
31        size += self.request_handle.byte_len();
32        size += self.service_result.byte_len();
33        size += self.service_diagnostics.byte_len();
34        size += byte_len_array(&self.string_table);
35        size += self.additional_header.byte_len();
36        size
37    }
38
39    fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
40        let mut size = 0;
41        size += self.timestamp.encode(stream)?;
42        size += self.request_handle.encode(stream)?;
43        size += self.service_result.encode(stream)?;
44        size += self.service_diagnostics.encode(stream)?;
45        size += write_array(stream, &self.string_table)?;
46        size += self.additional_header.encode(stream)?;
47        assert_eq!(size, self.byte_len());
48        Ok(size)
49    }
50
51    fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
52        let timestamp = UtcTime::decode(stream, decoding_options)?;
53        let request_handle = IntegerId::decode(stream, decoding_options)?;
54        let service_result = StatusCode::decode(stream, decoding_options)?;
55        let service_diagnostics = DiagnosticInfo::decode(stream, decoding_options)?;
56        let string_table: Option<Vec<UAString>> = read_array(stream, decoding_options)?;
57        let additional_header = ExtensionObject::decode(stream, decoding_options)?;
58        Ok(ResponseHeader {
59            timestamp,
60            request_handle,
61            service_result,
62            service_diagnostics,
63            string_table,
64            additional_header,
65        })
66    }
67}
68
69impl ResponseHeader {
70    pub fn new_good(request_header: &RequestHeader) -> ResponseHeader {
71        ResponseHeader::new_service_result(request_header, StatusCode::Good)
72    }
73
74    pub fn new_service_result(
75        request_header: &RequestHeader,
76        service_result: StatusCode,
77    ) -> ResponseHeader {
78        ResponseHeader::new_timestamped_service_result(
79            DateTime::now(),
80            request_header,
81            service_result,
82        )
83    }
84
85    pub fn new_timestamped_service_result(
86        timestamp: DateTime,
87        request_header: &RequestHeader,
88        service_result: StatusCode,
89    ) -> ResponseHeader {
90        ResponseHeader {
91            timestamp,
92            request_handle: request_header.request_handle,
93            service_result,
94            service_diagnostics: DiagnosticInfo::default(),
95            string_table: None,
96            additional_header: ExtensionObject::null(),
97        }
98    }
99
100    /// For testing, nothing else
101    pub fn null() -> ResponseHeader {
102        ResponseHeader {
103            timestamp: DateTime::now(),
104            request_handle: 0,
105            service_result: StatusCode::Good,
106            service_diagnostics: DiagnosticInfo::default(),
107            string_table: None,
108            additional_header: ExtensionObject::null(),
109        }
110    }
111}