1use std::{
8 self,
9 convert::TryFrom,
10 fmt,
11 io::{Read, Write},
12 str::FromStr,
13 sync::atomic::{AtomicUsize, Ordering},
14 u16, u32,
15};
16
17use crate::{
18 byte_string::ByteString,
19 encoding::*,
20 guid::Guid,
21 node_ids::{ObjectId, ReferenceTypeId},
22 status_codes::StatusCode,
23 string::*,
24};
25
26#[derive(Eq, PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
28pub enum Identifier {
29 Numeric(u32),
30 String(UAString),
31 Guid(Guid),
32 ByteString(ByteString),
33}
34
35impl fmt::Display for Identifier {
36 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37 match self {
38 Identifier::Numeric(v) => write!(f, "i={}", *v),
39 Identifier::String(v) => write!(f, "s={}", v),
40 Identifier::Guid(v) => write!(f, "g={:?}", v),
41 Identifier::ByteString(v) => write!(f, "b={}", v.as_base64()),
42 }
43 }
44}
45
46impl FromStr for Identifier {
47 type Err = ();
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 if s.len() < 2 {
51 Err(())
52 } else {
53 let k = &s[..2];
54 let v = &s[2..];
55 match k {
56 "i=" => v.parse::<u32>().map(|v| v.into()).map_err(|_| ()),
57 "s=" => Ok(UAString::from(v).into()),
58 "g=" => Guid::from_str(v).map(|v| v.into()).map_err(|_| ()),
59 "b=" => ByteString::from_base64(v).map(|v| v.into()).ok_or(()),
60 _ => Err(()),
61 }
62 }
63 }
64}
65
66impl From<i32> for Identifier {
67 fn from(v: i32) -> Self {
68 Identifier::Numeric(v as u32)
69 }
70}
71
72impl From<u32> for Identifier {
73 fn from(v: u32) -> Self {
74 Identifier::Numeric(v as u32)
75 }
76}
77
78impl<'a> From<&'a str> for Identifier {
79 fn from(v: &'a str) -> Self {
80 Identifier::from(UAString::from(v))
81 }
82}
83
84impl From<&String> for Identifier {
85 fn from(v: &String) -> Self {
86 Identifier::from(UAString::from(v))
87 }
88}
89
90impl From<String> for Identifier {
91 fn from(v: String) -> Self {
92 Identifier::from(UAString::from(v))
93 }
94}
95
96impl From<UAString> for Identifier {
97 fn from(v: UAString) -> Self {
98 Identifier::String(v)
99 }
100}
101
102impl From<Guid> for Identifier {
103 fn from(v: Guid) -> Self {
104 Identifier::Guid(v)
105 }
106}
107
108impl From<ByteString> for Identifier {
109 fn from(v: ByteString) -> Self {
110 Identifier::ByteString(v)
111 }
112}
113
114#[derive(Debug)]
115pub struct NodeIdError;
116
117impl fmt::Display for NodeIdError {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 write!(f, "NodeIdError")
120 }
121}
122
123impl std::error::Error for NodeIdError {}
124
125#[derive(PartialEq, Eq, Clone, Debug, Hash, Serialize, Deserialize)]
127pub struct NodeId {
128 pub namespace: u16,
130 pub identifier: Identifier,
132}
133
134impl fmt::Display for NodeId {
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 if self.namespace != 0 {
137 write!(f, "ns={};{}", self.namespace, self.identifier)
138 } else {
139 write!(f, "{}", self.identifier)
140 }
141 }
142}
143
144impl BinaryEncoder<NodeId> for NodeId {
145 fn byte_len(&self) -> usize {
146 let size: usize = match self.identifier {
148 Identifier::Numeric(value) => {
149 if self.namespace == 0 && value <= 255 {
150 2
151 } else if self.namespace <= 255 && value <= 65535 {
152 4
153 } else {
154 7
155 }
156 }
157 Identifier::String(ref value) => 3 + value.byte_len(),
158 Identifier::Guid(ref value) => 3 + value.byte_len(),
159 Identifier::ByteString(ref value) => 3 + value.byte_len(),
160 };
161 size
162 }
163
164 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
165 let mut size: usize = 0;
166 match &self.identifier {
168 Identifier::Numeric(value) => {
169 if self.namespace == 0 && *value <= 255 {
170 size += write_u8(stream, 0x0)?;
172 size += write_u8(stream, *value as u8)?;
173 } else if self.namespace <= 255 && *value <= 65535 {
174 size += write_u8(stream, 0x1)?;
176 size += write_u8(stream, self.namespace as u8)?;
177 size += write_u16(stream, *value as u16)?;
178 } else {
179 size += write_u8(stream, 0x2)?;
181 size += write_u16(stream, self.namespace)?;
182 size += write_u32(stream, *value)?;
183 }
184 }
185 Identifier::String(value) => {
186 size += write_u8(stream, 0x3)?;
187 size += write_u16(stream, self.namespace)?;
188 size += value.encode(stream)?;
189 }
190 Identifier::Guid(value) => {
191 size += write_u8(stream, 0x4)?;
192 size += write_u16(stream, self.namespace)?;
193 size += value.encode(stream)?;
194 }
195 Identifier::ByteString(value) => {
196 size += write_u8(stream, 0x5)?;
197 size += write_u16(stream, self.namespace)?;
198 size += value.encode(stream)?;
199 }
200 }
201 assert_eq!(size, self.byte_len());
202 Ok(size)
203 }
204
205 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
206 let identifier = read_u8(stream)?;
207 let node_id = match identifier {
208 0x0 => {
209 let namespace = 0;
210 let value = read_u8(stream)?;
211 NodeId::new(namespace, u32::from(value))
212 }
213 0x1 => {
214 let namespace = read_u8(stream)?;
215 let value = read_u16(stream)?;
216 NodeId::new(u16::from(namespace), u32::from(value))
217 }
218 0x2 => {
219 let namespace = read_u16(stream)?;
220 let value = read_u32(stream)?;
221 NodeId::new(namespace, value)
222 }
223 0x3 => {
224 let namespace = read_u16(stream)?;
225 let value = UAString::decode(stream, decoding_options)?;
226 NodeId::new(namespace, value)
227 }
228 0x4 => {
229 let namespace = read_u16(stream)?;
230 let value = Guid::decode(stream, decoding_options)?;
231 NodeId::new(namespace, value)
232 }
233 0x5 => {
234 let namespace = read_u16(stream)?;
235 let value = ByteString::decode(stream, decoding_options)?;
236 NodeId::new(namespace, value)
237 }
238 _ => {
239 error!("Unrecognized node id type {}", identifier);
240 return Err(StatusCode::BadDecodingError);
241 }
242 };
243 Ok(node_id)
244 }
245}
246
247impl FromStr for NodeId {
248 type Err = StatusCode;
249 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
250 use regex::Regex;
251
252 lazy_static! {
265 static ref RE: Regex = Regex::new(r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb]=.+)$").unwrap();
267 }
268
269 let captures = RE.captures(s).ok_or(StatusCode::BadNodeIdInvalid)?;
270
271 let namespace = if let Some(ns) = captures.name("ns") {
273 ns.as_str()
274 .parse::<u16>()
275 .map_err(|_| StatusCode::BadNodeIdInvalid)?
276 } else {
277 0
278 };
279
280 let t = captures.name("t").unwrap();
282 Identifier::from_str(t.as_str())
283 .map(|t| NodeId::new(namespace, t))
284 .map_err(|_| StatusCode::BadNodeIdInvalid)
285 }
286}
287
288impl From<&NodeId> for NodeId {
289 fn from(v: &NodeId) -> Self {
290 v.clone()
291 }
292}
293
294impl Into<String> for NodeId {
295 fn into(self) -> String {
296 self.to_string()
297 }
298}
299
300impl<'a> From<(u16, &'a str)> for NodeId {
301 fn from(v: (u16, &'a str)) -> Self {
302 Self::new(v.0, UAString::from(v.1))
303 }
304}
305
306impl From<(u16, UAString)> for NodeId {
307 fn from(v: (u16, UAString)) -> Self {
308 Self::new(v.0, v.1)
309 }
310}
311
312impl From<(u16, u32)> for NodeId {
313 fn from(v: (u16, u32)) -> Self {
314 Self::new(v.0, v.1)
315 }
316}
317
318impl From<(u16, Guid)> for NodeId {
319 fn from(v: (u16, Guid)) -> Self {
320 Self::new(v.0, v.1)
321 }
322}
323
324impl From<(u16, ByteString)> for NodeId {
325 fn from(v: (u16, ByteString)) -> Self {
326 Self::new(v.0, v.1)
327 }
328}
329
330static NEXT_NODE_ID_NUMERIC: AtomicUsize = AtomicUsize::new(0);
331
332impl Default for NodeId {
333 fn default() -> Self {
334 NodeId::null()
335 }
336}
337
338impl NodeId {
339 pub fn new<T>(namespace: u16, value: T) -> NodeId
342 where
343 T: 'static + Into<Identifier>,
344 {
345 NodeId {
346 namespace,
347 identifier: value.into(),
348 }
349 }
350
351 pub fn root_folder_id() -> NodeId {
353 ObjectId::RootFolder.into()
354 }
355
356 pub fn objects_folder_id() -> NodeId {
358 ObjectId::ObjectsFolder.into()
359 }
360
361 pub fn types_folder_id() -> NodeId {
363 ObjectId::TypesFolder.into()
364 }
365
366 pub fn views_folder_id() -> NodeId {
368 ObjectId::ViewsFolder.into()
369 }
370
371 pub fn is_null(&self) -> bool {
373 self.namespace == 0 && self.identifier == Identifier::Numeric(0)
374 }
375
376 pub fn null() -> NodeId {
378 NodeId::new(0, 0u32)
379 }
380
381 pub fn next_numeric(namespace: u16) -> NodeId {
383 NodeId::new(
384 namespace,
385 NEXT_NODE_ID_NUMERIC.fetch_add(1, Ordering::SeqCst) as u32,
386 )
387 }
388
389 pub fn as_object_id(&self) -> std::result::Result<ObjectId, NodeIdError> {
391 match self.identifier {
392 Identifier::Numeric(id) if self.namespace == 0 => {
393 ObjectId::try_from(id).map_err(|_| NodeIdError)
394 }
395 _ => Err(NodeIdError),
396 }
397 }
398
399 pub fn as_reference_type_id(&self) -> std::result::Result<ReferenceTypeId, NodeIdError> {
400 if self.is_null() {
403 Err(NodeIdError)
404 } else {
405 match self.identifier {
406 Identifier::Numeric(id) if self.namespace == 0 => {
407 ReferenceTypeId::try_from(id).map_err(|_| NodeIdError)
408 }
409 _ => Err(NodeIdError),
410 }
411 }
412 }
413
414 pub fn is_numeric(&self) -> bool {
416 matches!(self.identifier, Identifier::Numeric(_))
417 }
418
419 pub fn is_string(&self) -> bool {
421 matches!(self.identifier, Identifier::String(_))
422 }
423
424 pub fn is_guid(&self) -> bool {
426 matches!(self.identifier, Identifier::Guid(_))
427 }
428
429 pub fn is_byte_string(&self) -> bool {
431 matches!(self.identifier, Identifier::ByteString(_))
432 }
433}
434
435#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
437pub struct ExpandedNodeId {
438 pub node_id: NodeId,
439 pub namespace_uri: UAString,
440 pub server_index: u32,
441}
442
443impl BinaryEncoder<ExpandedNodeId> for ExpandedNodeId {
444 fn byte_len(&self) -> usize {
445 let mut size = self.node_id.byte_len();
446 if !self.namespace_uri.is_null() {
447 size += self.namespace_uri.byte_len();
448 }
449 if self.server_index != 0 {
450 size += self.server_index.byte_len();
451 }
452 size
453 }
454
455 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
456 let mut size: usize = 0;
457
458 let mut data_encoding = 0;
459 if !self.namespace_uri.is_null() {
460 data_encoding |= 0x80;
461 }
462 if self.server_index != 0 {
463 data_encoding |= 0x40;
464 }
465
466 match &self.node_id.identifier {
468 Identifier::Numeric(value) => {
469 if self.node_id.namespace == 0 && *value <= 255 {
470 size += write_u8(stream, data_encoding)?;
472 size += write_u8(stream, *value as u8)?;
473 } else if self.node_id.namespace <= 255 && *value <= 65535 {
474 size += write_u8(stream, data_encoding | 0x1)?;
476 size += write_u8(stream, self.node_id.namespace as u8)?;
477 size += write_u16(stream, *value as u16)?;
478 } else {
479 size += write_u8(stream, data_encoding | 0x2)?;
481 size += write_u16(stream, self.node_id.namespace)?;
482 size += write_u32(stream, *value)?;
483 }
484 }
485 Identifier::String(value) => {
486 size += write_u8(stream, data_encoding | 0x3)?;
487 size += write_u16(stream, self.node_id.namespace)?;
488 size += value.encode(stream)?;
489 }
490 Identifier::Guid(value) => {
491 size += write_u8(stream, data_encoding | 0x4)?;
492 size += write_u16(stream, self.node_id.namespace)?;
493 size += value.encode(stream)?;
494 }
495 Identifier::ByteString(ref value) => {
496 size += write_u8(stream, data_encoding | 0x5)?;
497 size += write_u16(stream, self.node_id.namespace)?;
498 size += value.encode(stream)?;
499 }
500 }
501 if !self.namespace_uri.is_null() {
502 size += self.namespace_uri.encode(stream)?;
503 }
504 if self.server_index != 0 {
505 size += self.server_index.encode(stream)?;
506 }
507 assert_eq!(size, self.byte_len());
508 Ok(size)
509 }
510
511 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
512 let data_encoding = read_u8(stream)?;
513 let identifier = data_encoding & 0x0f;
514 let node_id = match identifier {
515 0x0 => {
516 let value = read_u8(stream)?;
517 NodeId::new(0, u32::from(value))
518 }
519 0x1 => {
520 let namespace = read_u8(stream)?;
521 let value = read_u16(stream)?;
522 NodeId::new(u16::from(namespace), u32::from(value))
523 }
524 0x2 => {
525 let namespace = read_u16(stream)?;
526 let value = read_u32(stream)?;
527 NodeId::new(namespace, value)
528 }
529 0x3 => {
530 let namespace = read_u16(stream)?;
531 let value = UAString::decode(stream, decoding_options)?;
532 NodeId::new(namespace, value)
533 }
534 0x4 => {
535 let namespace = read_u16(stream)?;
536 let value = Guid::decode(stream, decoding_options)?;
537 NodeId::new(namespace, value)
538 }
539 0x5 => {
540 let namespace = read_u16(stream)?;
541 let value = ByteString::decode(stream, decoding_options)?;
542 NodeId::new(namespace, value)
543 }
544 _ => {
545 error!("Unrecognized expanded node id type {}", identifier);
546 return Err(StatusCode::BadDecodingError);
547 }
548 };
549
550 let namespace_uri = if data_encoding & 0x80 != 0 {
552 UAString::decode(stream, decoding_options)?
553 } else {
554 UAString::null()
555 };
556 let server_index = if data_encoding & 0x40 != 0 {
557 u32::decode(stream, decoding_options)?
558 } else {
559 0
560 };
561
562 Ok(ExpandedNodeId {
563 node_id,
564 namespace_uri,
565 server_index,
566 })
567 }
568}
569
570impl<'a> Into<ExpandedNodeId> for &'a NodeId {
571 fn into(self) -> ExpandedNodeId {
572 self.clone().into()
573 }
574}
575
576impl From<NodeId> for ExpandedNodeId {
577 fn from(v: NodeId) -> Self {
578 ExpandedNodeId {
579 node_id: v,
580 namespace_uri: UAString::null(),
581 server_index: 0,
582 }
583 }
584}
585
586impl fmt::Display for ExpandedNodeId {
587 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
588 if self.namespace_uri.is_empty() {
590 write!(f, "svr={};{}", self.server_index, self.node_id)
592 } else {
593 let namespace_uri = String::from(self.namespace_uri.as_ref())
595 .replace('%', "%25")
596 .replace(';', "%3b");
597 write!(
599 f,
600 "svr={};nsu={};{}",
601 self.server_index, namespace_uri, self.node_id.identifier
602 )
603 }
604 }
605}
606
607impl FromStr for ExpandedNodeId {
608 type Err = StatusCode;
609 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
610 use regex::Regex;
611
612 lazy_static! {
619 static ref RE: Regex = Regex::new(r"^svr=(?P<svr>[0-9]+);(ns=(?P<ns>[0-9]+)|nsu=(?P<nsu>[^;]+));(?P<t>[isgb]=.+)$").unwrap();
621 }
622
623 let captures = RE.captures(s).ok_or(StatusCode::BadNodeIdInvalid)?;
624
625 let server_index = captures
627 .name("svr")
628 .ok_or(StatusCode::BadNodeIdInvalid)
629 .and_then(|server_index| {
630 server_index
631 .as_str()
632 .parse::<u32>()
633 .map_err(|_| StatusCode::BadNodeIdInvalid)
634 })?;
635
636 let namespace_uri = if let Some(nsu) = captures.name("nsu") {
638 let nsu = String::from(nsu.as_str())
640 .replace("%3b", ";")
641 .replace("%25", "%");
642 UAString::from(nsu)
643 } else {
644 UAString::null()
645 };
646
647 let namespace = if let Some(ns) = captures.name("ns") {
648 ns.as_str()
649 .parse::<u16>()
650 .map_err(|_| StatusCode::BadNodeIdInvalid)?
651 } else {
652 0
653 };
654
655 let t = captures.name("t").unwrap();
657 Identifier::from_str(t.as_str())
658 .map(|t| ExpandedNodeId {
659 server_index,
660 namespace_uri,
661 node_id: NodeId::new(namespace, t),
662 })
663 .map_err(|_| StatusCode::BadNodeIdInvalid)
664 }
665}
666
667impl ExpandedNodeId {
668 pub fn new<T>(value: T) -> ExpandedNodeId
670 where
671 T: 'static + Into<ExpandedNodeId>,
672 {
673 value.into()
674 }
675
676 pub fn null() -> ExpandedNodeId {
677 Self::new(NodeId::null())
678 }
679
680 pub fn is_null(&self) -> bool {
681 self.node_id.is_null()
682 }
683}