///|
/// The identifier portion of an OPC UA NodeId.
pub(all) enum NodeIdIdentifier {
Numeric(UInt32)
String(String)
Guid(Bytes)
Opaque(Bytes)
}
///|
/// An OPC UA NodeId.
pub(all) struct NodeId {
namespace_index : UInt16
identifier : NodeIdIdentifier
}
///|
/// Construct a numeric NodeId.
pub fn NodeId::numeric(namespace_index : UInt16, identifier : UInt32) -> NodeId {
{ namespace_index, identifier: Numeric(identifier), }
}
///|
/// Construct a string NodeId.
pub fn NodeId::string(namespace_index : UInt16, identifier : String) -> NodeId {
{ namespace_index, identifier: String(identifier), }
}
///|
/// Construct a Guid NodeId.
pub fn NodeId::guid(namespace_index : UInt16, identifier : Bytes) -> NodeId {
{ namespace_index, identifier: Guid(identifier), }
}
///|
/// Construct an opaque NodeId.
pub fn NodeId::bytes(namespace_index : UInt16, identifier : Bytes) -> NodeId {
{ namespace_index, identifier: Opaque(identifier), }
}
///|
/// Render a NodeId for diagnostics.
pub fn NodeId::to_string(self : NodeId) -> String {
match self.identifier {
Numeric(value) => "ns=\{self.namespace_index};i=\{value}"
String(value) => "ns=\{self.namespace_index};s=\{value}"
Guid(_) => "ns=\{self.namespace_index};g=<16-byte-guid>"
Opaque(_) => "ns=\{self.namespace_index};b="
}
}
///|
/// Decode a NodeId.
pub fn UaReader::read_node_id(self : UaReader) -> NodeId raise UaError {
let encoding = self.read_u8()
if encoding > 5 {
raise InvalidNodeIdEncoding(encoding)
}
let namespace_index : UInt16 = match encoding {
0 => {
let value = self.read_u8()
if value > 255 {
raise InvalidNodeIdEncoding(encoding)
}
value.to_uint16()
}
1 => {
let value = self.read_u8()
if value > 255 {
raise InvalidNodeIdEncoding(encoding)
}
value.to_uint16()
}
_ => self.read_uint16()
}
let identifier = match encoding {
0 => {
let value = self.read_u8()
if value > 255 {
raise InvalidNodeIdEncoding(encoding)
}
Numeric(value)
}
1 => Numeric(self.read_uint16().to_uint())
2 => Numeric(self.read_uint32())
3 => String(self.read_required_string())
4 => {
let guid = self.take(16).to_owned()
Guid(guid)
}
5 => Opaque(self.read_required_bytes())
other => raise InvalidNodeIdEncoding(other)
}
{ namespace_index, identifier, }
}
///|
/// Encode a NodeId using the most compact numeric representation.
pub fn UaWriter::write_node_id(
self : UaWriter,
value : NodeId,
) -> Unit raise UaError {
match value.identifier {
Numeric(identifier) =>
if value.namespace_index.to_uint() <= 255U && identifier <= 255U {
self.write_u8(0)
self.write_u8(value.namespace_index.to_uint())
self.write_u8(identifier)
} else if value.namespace_index.to_uint() <= 255U && identifier <= 65535U {
self.write_u8(1)
self.write_u8(value.namespace_index.to_uint())
self.write_uint16(identifier.to_uint16())
} else {
self.write_u8(2)
self.write_uint16(value.namespace_index)
self.write_uint32(identifier)
}
String(identifier) => {
self.write_u8(3)
self.write_uint16(value.namespace_index)
self.write_string(identifier)
}
Guid(identifier) => {
if identifier.length() != 16 {
raise InvalidGuidLength(identifier.length())
}
self.write_u8(4)
self.write_uint16(value.namespace_index)
self.buffer.write_bytes(identifier.exact_view())
}
Opaque(identifier) => {
self.write_u8(5)
self.write_uint16(value.namespace_index)
self.write_bytes(identifier)
}
}
}