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