1use std::io::{Read, Write};
14
15use crate::{
16 encoding::{BinaryDecodable, BinaryEncodable, EncodingResult},
17 localized_text::LocalizedText,
18 node_id::NodeId,
19 string::UAString,
20 write_u32, Context, DataTypeId, Error, MessageInfo, ObjectId,
21};
22
23#[allow(unused)]
30mod opcua {
31 pub(super) use crate as types;
32}
33
34#[derive(Clone, Debug, PartialEq, Default, crate::UaNullable)]
35#[cfg_attr(feature = "json", derive(crate::JsonEncodable, crate::JsonDecodable))]
36#[cfg_attr(
37 feature = "xml",
38 derive(crate::XmlEncodable, crate::XmlDecodable, crate::XmlType)
39)]
40pub struct Argument {
42 pub name: UAString,
44 pub data_type: NodeId,
46 pub value_rank: i32,
48 pub array_dimensions: Option<Vec<u32>>,
50 pub description: LocalizedText,
52}
53
54impl MessageInfo for Argument {
55 fn type_id(&self) -> ObjectId {
56 ObjectId::Argument_Encoding_DefaultBinary
57 }
58 fn json_type_id(&self) -> ObjectId {
59 ObjectId::Argument_Encoding_DefaultJson
60 }
61 fn xml_type_id(&self) -> ObjectId {
62 ObjectId::Argument_Encoding_DefaultXml
63 }
64 fn data_type_id(&self) -> crate::DataTypeId {
65 DataTypeId::Argument
66 }
67}
68
69impl BinaryEncodable for Argument {
70 fn byte_len(&self, ctx: &crate::Context<'_>) -> usize {
71 let mut size = 0;
72 size += self.name.byte_len(ctx);
73 size += self.data_type.byte_len(ctx);
74 size += self.value_rank.byte_len(ctx);
75 size += self.array_dimensions.byte_len(ctx);
76 size += self.description.byte_len(ctx);
77 size
78 }
79
80 fn encode<S: Write + ?Sized>(&self, stream: &mut S, ctx: &Context<'_>) -> EncodingResult<()> {
81 self.name.encode(stream, ctx)?;
82 self.data_type.encode(stream, ctx)?;
83 self.value_rank.encode(stream, ctx)?;
84 if self.value_rank > 0 {
86 if let Some(ref array_dimensions) = self.array_dimensions {
87 if self.value_rank as usize != array_dimensions.len() {
88 return Err(Error::encoding(
89 format!("The array dimensions {} of the Argument should match value rank {} and they don't", array_dimensions.len(), self.value_rank)));
90 }
91 self.array_dimensions.encode(stream, ctx)?;
92 } else {
93 return Err(Error::encoding(format!("The array dimensions are expected in the Argument matching value rank {} and they aren't", self.value_rank)));
94 }
95 } else {
96 write_u32(stream, 0u32)?;
97 }
98
99 self.description.encode(stream, ctx)?;
100 Ok(())
101 }
102}
103
104impl BinaryDecodable for Argument {
105 fn decode<S: Read + ?Sized>(stream: &mut S, ctx: &Context<'_>) -> EncodingResult<Self> {
106 let name = UAString::decode(stream, ctx)?;
107 let data_type = NodeId::decode(stream, ctx)?;
108 let value_rank = i32::decode(stream, ctx)?;
109 let array_dimensions: Option<Vec<u32>> = BinaryDecodable::decode(stream, ctx)?;
111 if let Some(ref array_dimensions) = array_dimensions {
112 if value_rank > 0 && value_rank as usize != array_dimensions.len() {
113 return Err(Error::decoding(format!("The array dimensions {} of the Argument should match value rank {} and they don't", array_dimensions.len(), value_rank)));
114 }
115 }
116 let description = LocalizedText::decode(stream, ctx)?;
117 Ok(Argument {
118 name,
119 data_type,
120 value_rank,
121 array_dimensions,
122 description,
123 })
124 }
125}