opcua_server/node_manager/
method.rs1use opcua_types::{
2 CallMethodRequest, CallMethodResult, DiagnosticBits, DiagnosticInfo, NodeId, StatusCode,
3 Variant,
4};
5
6use super::IntoResult;
7
8#[derive(Debug)]
9pub struct MethodCall {
11 object_id: NodeId,
12 method_id: NodeId,
13 arguments: Vec<Variant>,
14 diagnostic_bits: DiagnosticBits,
15
16 status: StatusCode,
17 argument_results: Vec<StatusCode>,
18 outputs: Vec<Variant>,
19 diagnostic_info: Option<DiagnosticInfo>,
20}
21
22impl MethodCall {
23 pub(crate) fn new(request: CallMethodRequest, diagnostic_bits: DiagnosticBits) -> Self {
24 Self {
25 object_id: request.object_id,
26 method_id: request.method_id,
27 arguments: request.input_arguments.unwrap_or_default(),
28 status: StatusCode::BadMethodInvalid,
29 argument_results: Vec::new(),
30 outputs: Vec::new(),
31 diagnostic_bits,
32 diagnostic_info: None,
33 }
34 }
35
36 pub fn set_argument_error(&mut self, argument_results: Vec<StatusCode>) {
41 self.argument_results = argument_results;
42 self.status = StatusCode::BadInvalidArgument;
43 }
44
45 pub fn set_status(&mut self, status: StatusCode) {
47 self.status = status;
48 }
49
50 pub fn set_outputs(&mut self, outputs: Vec<Variant>) {
52 self.outputs = outputs;
53 }
54
55 pub fn arguments(&self) -> &[Variant] {
57 &self.arguments
58 }
59
60 pub fn method_id(&self) -> &NodeId {
62 &self.method_id
63 }
64
65 pub fn object_id(&self) -> &NodeId {
67 &self.object_id
68 }
69
70 pub fn status(&self) -> StatusCode {
72 self.status
73 }
74
75 pub fn diagnostic_bits(&self) -> DiagnosticBits {
77 self.diagnostic_bits
78 }
79
80 pub fn set_diagnostic_info(&mut self, diagnostic_info: DiagnosticInfo) {
83 self.diagnostic_info = Some(diagnostic_info);
84 }
85}
86
87impl IntoResult for MethodCall {
88 type Result = CallMethodResult;
89
90 fn into_result(self) -> (Self::Result, Option<DiagnosticInfo>) {
91 (
92 CallMethodResult {
93 status_code: self.status,
94 input_argument_diagnostic_infos: None,
95 input_argument_results: if !self.argument_results.is_empty() {
96 Some(self.argument_results)
97 } else {
98 None
99 },
100 output_arguments: Some(self.outputs),
101 },
102 self.diagnostic_info,
103 )
104 }
105}
106
107#[macro_export]
121macro_rules! load_method_args {
122 ($call:expr, $($type:ident),+) => {
123 {
124 let mut arguments = $call.arguments().iter();
125 (move || {
126 Ok($(
127 match arguments.next().map(|v| v.convert(VariantTypeId::Scalar(VariantScalarTypeId::$type))) {
128 Some(Variant::$type(val)) => val,
129 _ => return Err(StatusCode::BadInvalidArgument),
130 }
131 ),*)
132 })()
133 }
134
135 };
136}