Skip to main content

opcua/types/
localized_text.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5//! Contains the definition of `LocalizedText`.
6use std::{
7    fmt,
8    io::{Read, Write},
9};
10
11use crate::types::{encoding::*, string::*};
12
13use serde::{Deserialize, Serialize};
14
15/// JSON encoding
16///  Locale    The Localeportion of LocalizedTextvalues shall be encoded as a JSON string
17///
18/// Text       The Textportion of LocalizedTextvalues shall be encoded as a JSON string.
19
20/// A human readable text with an optional locale identifier.
21#[derive(PartialEq, Default, Debug, Clone, Serialize, Deserialize)]
22#[serde(rename_all = "PascalCase")]
23pub struct LocalizedText {
24    /// The locale. Omitted from stream if null or empty
25    pub locale: UAString,
26    /// The text in the specified locale. Omitted frmo stream if null or empty.
27    pub text: UAString,
28}
29
30impl<'a> From<&'a str> for LocalizedText {
31    fn from(value: &'a str) -> Self {
32        Self {
33            locale: UAString::from(""),
34            text: UAString::from(value),
35        }
36    }
37}
38
39impl From<&String> for LocalizedText {
40    fn from(value: &String) -> Self {
41        Self {
42            locale: UAString::from(""),
43            text: UAString::from(value),
44        }
45    }
46}
47
48impl From<String> for LocalizedText {
49    fn from(value: String) -> Self {
50        Self {
51            locale: UAString::from(""),
52            text: UAString::from(value),
53        }
54    }
55}
56
57impl fmt::Display for LocalizedText {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        write!(f, "{}", self.text)
60    }
61}
62
63impl BinaryEncoder<LocalizedText> for LocalizedText {
64    fn byte_len(&self) -> usize {
65        let mut size = 1;
66        if !self.locale.is_empty() {
67            size += self.locale.byte_len();
68        }
69        if !self.text.is_empty() {
70            size += self.text.byte_len();
71        }
72        size
73    }
74
75    fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
76        let mut size = 0;
77        // A bit mask that indicates which fields are present in the stream.
78        // The mask has the following bits:
79        // 0x01    Locale
80        // 0x02    Text
81        let mut encoding_mask: u8 = 0;
82        if !self.locale.is_empty() {
83            encoding_mask |= 0x1;
84        }
85        if !self.text.is_empty() {
86            encoding_mask |= 0x2;
87        }
88        size += encoding_mask.encode(stream)?;
89        if !self.locale.is_empty() {
90            size += self.locale.encode(stream)?;
91        }
92        if !self.text.is_empty() {
93            size += self.text.encode(stream)?;
94        }
95        Ok(size)
96    }
97
98    fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
99        let encoding_mask = u8::decode(stream, decoding_options)?;
100        let locale = if encoding_mask & 0x1 != 0 {
101            UAString::decode(stream, decoding_options)?
102        } else {
103            UAString::null()
104        };
105        let text = if encoding_mask & 0x2 != 0 {
106            UAString::decode(stream, decoding_options)?
107        } else {
108            UAString::null()
109        };
110        Ok(LocalizedText { locale, text })
111    }
112}
113
114impl LocalizedText {
115    pub fn new(locale: &str, text: &str) -> LocalizedText {
116        LocalizedText {
117            locale: UAString::from(locale),
118            text: UAString::from(text),
119        }
120    }
121
122    pub fn null() -> LocalizedText {
123        LocalizedText {
124            locale: UAString::null(),
125            text: UAString::null(),
126        }
127    }
128}