opcua_types/
guid.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5//! Contains the implementation of `Guid`.
6
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8use std::{
9    fmt,
10    io::{Read, Write},
11    str::FromStr,
12};
13use uuid::Uuid;
14
15use crate::encoding::*;
16
17/// A Guid is a 16 byte Globally Unique Identifier.
18#[derive(Eq, PartialEq, Clone, Hash)]
19pub struct Guid {
20    uuid: Uuid,
21}
22
23impl Serialize for Guid {
24    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
25    where
26        S: Serializer,
27    {
28        self.uuid.to_string().serialize(serializer)
29    }
30}
31
32impl<'de> Deserialize<'de> for Guid {
33    fn deserialize<D>(deserializer: D) -> Result<Guid, D::Error>
34    where
35        D: Deserializer<'de>,
36    {
37        use serde::de::Error;
38
39        let result = String::deserialize(deserializer);
40        match result {
41            Ok(uuid) => Uuid::parse_str(&uuid)
42                .map(|uuid| Guid { uuid })
43                .map_err(|_| D::Error::custom("Invalid uuid")),
44            Err(err) => Err(err),
45        }
46    }
47}
48
49impl fmt::Display for Guid {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        write!(f, "{}", self.uuid)
52    }
53}
54
55impl fmt::Debug for Guid {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        write!(f, "{}", self.uuid.to_hyphenated())
58    }
59}
60
61impl BinaryEncoder<Guid> for Guid {
62    fn byte_len(&self) -> usize {
63        16
64    }
65
66    fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
67        let mut size: usize = 0;
68        size += process_encode_io_result(stream.write(self.uuid.as_bytes()))?;
69        Ok(size)
70    }
71
72    fn decode<S: Read>(stream: &mut S, _: &DecodingOptions) -> EncodingResult<Self> {
73        let mut bytes = [0u8; 16];
74        process_decode_io_result(stream.read_exact(&mut bytes))?;
75        Ok(Guid {
76            uuid: Uuid::from_bytes(bytes),
77        })
78    }
79}
80
81impl FromStr for Guid {
82    type Err = ();
83
84    fn from_str(s: &str) -> Result<Self, Self::Err> {
85        Uuid::from_str(s).map(|uuid| Guid { uuid }).map_err(|err| {
86            error!("Guid cannot be parsed from string, err = {:?}", err);
87        })
88    }
89}
90
91impl Default for Guid {
92    fn default() -> Self {
93        Guid::null()
94    }
95}
96
97impl Guid {
98    /// Return a null guid, i.e. 00000000-0000-0000-0000-000000000000
99    pub fn null() -> Guid {
100        Guid { uuid: Uuid::nil() }
101    }
102
103    /// Creates a random Guid
104    pub fn new() -> Guid {
105        Guid {
106            uuid: Uuid::new_v4(),
107        }
108    }
109
110    /// Returns the bytes of the Guid
111    pub fn as_bytes(&self) -> &[u8; 16] {
112        self.uuid.as_bytes()
113    }
114
115    // Creates a guid from bytes
116    pub fn from_bytes(bytes: [u8; 16]) -> Guid {
117        Guid {
118            uuid: Uuid::from_bytes(bytes),
119        }
120    }
121}