orbtk_utils/
string16.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4/// A UTF-16 encoded, growable string.
5///
6/// # Examples
7///
8/// let mut string16 = String16::from("Übung");
9/// string16.push('ä');
10#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
11pub struct String16 {
12    utf16: Vec<u16>,
13}
14
15impl String16 {
16    /// Creates a new empty `String16`.
17    pub fn new() -> Self {
18        String16 { utf16: vec![] }
19    }
20
21    /// Returns the length of this `String16`, in bytes.
22    ///
23    /// # Examples
24    ///
25    /// Basic usage:
26    ///
27    /// let a = String16::from("Übung");
28    ///
29    /// assert_eq!(a.len(), 5);
30    #[inline]
31    pub fn len(&self) -> usize {
32        self.utf16.len()
33    }
34
35    /// Returns a slice of [`u16`]s bytes that were attempted to convert to a `String`.
36    pub fn as_bytes(&self) -> &[u16] {
37        &self.utf16
38    }
39
40    /// Returns a mutable slice of [`u16`]s bytes that were attempted to convert to a `String`.
41    pub fn as_bytes_mut(&mut self) -> &mut [u16] {
42        &mut self.utf16
43    }
44
45    /// Inserts a string slice into this `String16` at a byte position.
46    pub fn insert_str(&mut self, idx: usize, string: &str) {
47        let mut counter = idx;
48        for u in string.encode_utf16() {
49            self.utf16.insert(counter, u);
50            counter += 1;
51        }
52    }
53
54    /// Appends a given char onto the end of this `String16`.
55    pub fn push(&mut self, ch: char) {
56        let mut buf = [0; 2];
57
58        for part in ch.encode_utf16(&mut buf) {
59            self.utf16.push(*part)
60        }
61    }
62
63    /// Removes a [`char`] from this `String16` at a byte position and returns it.
64    pub fn remove(&mut self, idx: usize) {
65        self.utf16.remove(idx);
66    }
67
68    /// Returns `true` if this `String16` has a length of zero, and `false` otherwise.
69    pub fn is_empty(&self) -> bool {
70        self.utf16.is_empty()
71    }
72
73    /// Returns `true` if this `String16` ends with the given string slice, or `false` otherwise.
74    pub fn ends_with(&self, pat: &str) -> bool {
75        self.as_string().ends_with(pat)
76    }
77
78    /// Truncates this `String16`, removing all contents.
79    pub fn clear(&mut self) {
80        self.utf16.clear()
81    }
82
83    /// Returns a string part begins with the `start`and ends with the `end` index.
84    pub fn get_string(&self, start: usize, end: usize) -> Option<String> {
85        self.utf16.get(start..end).map(String::from_utf16_lossy)
86    }
87
88    /// Converts the `String16` value to a String.
89    pub fn as_string(&self) -> String {
90        String::from_utf16_lossy(&self.utf16)
91    }
92}
93
94impl From<&str> for String16 {
95    fn from(s: &str) -> Self {
96        String16 {
97            utf16: s.encode_utf16().collect(),
98        }
99    }
100}
101
102impl From<String> for String16 {
103    fn from(string: String) -> Self {
104        String16 {
105            utf16: string.encode_utf16().collect(),
106        }
107    }
108}
109
110impl fmt::Debug for String16 {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        write!(f, "String16 {}", self.as_string())
113    }
114}
115
116impl fmt::Display for String16 {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        write!(f, "{}", self.as_string())
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125    #[test]
126    fn from_string() {
127        let string16 = String16::from(String::from("Übung"));
128        assert_eq!(string16.len(), 5);
129
130        let string16 = String16::from(String::from("World"));
131        assert_eq!(string16.len(), 5);
132    }
133
134    #[test]
135    fn from_str() {
136        let string16 = String16::from("Übung");
137        assert_eq!(string16.len(), 5);
138
139        let string16 = String16::from("World");
140        assert_eq!(string16.len(), 5);
141    }
142
143    #[test]
144    fn push() {
145        // Single-u16 encoded char
146        let mut string16 = String16::from("Fo");
147        string16.push('o');
148        assert_eq!(string16, String16::from("Foo"));
149
150        // Two-u16 encoded char
151        let mut string16 = String16::from("Bar");
152        string16.push('𝕊');
153        assert_eq!(string16, String16::from("Bar𝕊"));
154    }
155}