Coverage Report

Created: 2025-06-16 06:50

/rust/registry/src/index.crates.io-6f17d22bba15001f/write16-1.0.0/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright Mozilla Foundation
2
//
3
// Licensed under the Apache License (Version 2.0), or the MIT license,
4
// (the "Licenses") at your option. You may not use this file except in
5
// compliance with one of the Licenses. You may obtain copies of the
6
// Licenses at:
7
//
8
//    https://www.apache.org/licenses/LICENSE-2.0
9
//    https://opensource.org/licenses/MIT
10
//
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the Licenses is distributed on an "AS IS" BASIS,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the Licenses for the specific language governing permissions and
15
// limitations under the Licenses.
16
17
#![no_std]
18
19
//! `write16` provides the trait `Write16`, which a UTF-16 analog of the
20
//! `core::fmt::Write` trait (the sink partβ€”not the formatting part).
21
22
#[cfg(feature = "alloc")]
23
extern crate alloc;
24
#[cfg(feature = "arrayvec")]
25
extern crate arrayvec;
26
#[cfg(feature = "smallvec")]
27
extern crate smallvec;
28
29
/// A UTF-16 sink analogous to `core::fmt::Write`.
30
pub trait Write16 {
31
    /// Write a slice containing UTF-16 to the sink.
32
    ///
33
    /// The implementor of the trait should not validate UTF-16.
34
    /// It's the responsibility of the caller to pass valid
35
    /// UTF-16.
36
    fn write_slice(&mut self, s: &[u16]) -> core::fmt::Result;
37
38
    /// Write a Unicode scalar value to the sink.
39
    #[inline(always)]
40
    fn write_char(&mut self, c: char) -> core::fmt::Result {
41
        let mut buf = [0u16; 2];
42
        self.write_slice(c.encode_utf16(&mut buf))
43
    }
44
45
    /// A hint that the caller expects to write `upcoming` UTF-16
46
    /// code units. The implementation must not assume `upcoming`
47
    /// to be exact. The caller may write more or fewer code units
48
    /// using `write_slice()` and `write_char()`. However, the
49
    /// caller should try to give reasonable estimates if it uses
50
    /// this method.
51
    ///
52
    /// For `Vec` and `SmallVec`, this maps to `reserve()`.
53
    /// The default implementation does nothing.
54
    #[inline(always)]
55
0
    fn size_hint(&mut self, upcoming: usize) -> core::fmt::Result {
56
0
        let _ = upcoming;
57
0
        Ok(())
58
0
    }
59
}
60
61
#[cfg(feature = "alloc")]
62
impl Write16 for alloc::vec::Vec<u16> {
63
    #[inline(always)]
64
0
    fn write_slice(&mut self, s: &[u16]) -> core::fmt::Result {
65
0
        self.extend_from_slice(s);
66
0
        Ok(())
67
0
    }
68
69
    #[inline(always)]
70
0
    fn write_char(&mut self, c: char) -> core::fmt::Result {
71
0
        if c <= '\u{FFFF}' {
72
0
            self.push(c as u16);
73
0
        } else {
74
0
            let mut buf = [0u16; 2];
75
0
            let u = u32::from(c);
76
0
            buf[0] = (0xD7C0 + (u >> 10)) as u16;
77
0
            buf[1] = (0xDC00 + (u & 0x3FF)) as u16;
78
0
            self.extend_from_slice(&mut buf);
79
0
        }
80
0
        Ok(())
81
0
    }
82
83
    #[inline(always)]
84
0
    fn size_hint(&mut self, upcoming: usize) -> core::fmt::Result {
85
0
        self.reserve(upcoming);
86
0
        Ok(())
87
0
    }
88
}
89
90
#[cfg(feature = "smallvec")]
91
impl<A: smallvec::Array<Item = u16>> Write16 for smallvec::SmallVec<A> {
92
    #[inline(always)]
93
    fn write_slice(&mut self, s: &[u16]) -> core::fmt::Result {
94
        self.extend_from_slice(s);
95
        Ok(())
96
    }
97
98
    #[inline(always)]
99
    fn write_char(&mut self, c: char) -> core::fmt::Result {
100
        if c <= '\u{FFFF}' {
101
            self.push(c as u16);
102
        } else {
103
            let mut buf = [0u16; 2];
104
            let u = u32::from(c);
105
            buf[0] = (0xD7C0 + (u >> 10)) as u16;
106
            buf[1] = (0xDC00 + (u & 0x3FF)) as u16;
107
            self.extend_from_slice(&mut buf);
108
        }
109
        Ok(())
110
    }
111
112
    #[inline(always)]
113
    fn size_hint(&mut self, upcoming: usize) -> core::fmt::Result {
114
        self.reserve(upcoming);
115
        Ok(())
116
    }
117
}
118
119
#[cfg(feature = "arrayvec")]
120
impl<const CAP: usize> Write16 for arrayvec::ArrayVec<u16, CAP> {
121
    #[inline(always)]
122
    fn write_slice(&mut self, s: &[u16]) -> core::fmt::Result {
123
        if self.try_extend_from_slice(s).is_ok() {
124
            Ok(())
125
        } else {
126
            Err(core::fmt::Error {})
127
        }
128
    }
129
130
    #[inline(always)]
131
    fn write_char(&mut self, c: char) -> core::fmt::Result {
132
        if c <= '\u{FFFF}' {
133
            if self.try_push(c as u16).is_ok() {
134
                Ok(())
135
            } else {
136
                Err(core::fmt::Error {})
137
            }
138
        } else {
139
            let mut buf = [0u16; 2];
140
            let u = u32::from(c);
141
            buf[0] = (0xD7C0 + (u >> 10)) as u16;
142
            buf[1] = (0xDC00 + (u & 0x3FF)) as u16;
143
            self.write_slice(&mut buf)
144
        }
145
    }
146
}
147
148
#[cfg(test)]
149
mod tests {
150
    use crate::Write16;
151
152
    #[cfg(feature = "alloc")]
153
    #[test]
154
    fn test_vec() {
155
        let mut v: alloc::vec::Vec<u16> = alloc::vec::Vec::new();
156
        assert_eq!(v.capacity(), 0);
157
        assert!(v.size_hint(32).is_ok());
158
        assert!(v.capacity() >= 32);
159
        assert_eq!(v.len(), 0);
160
        assert!(v.write_slice([0x0061u16, 0x0062u16].as_slice()).is_ok());
161
        assert_eq!(v.len(), 2);
162
        assert!(v.write_char('β˜ƒ').is_ok());
163
        assert_eq!(v.len(), 3);
164
        assert!(v.write_char('😊').is_ok());
165
        assert_eq!(v.len(), 5);
166
        assert_eq!(
167
            v.as_slice(),
168
            [0x0061u16, 0x0062u16, 0x2603u16, 0xD83Du16, 0xDE0Au16].as_slice()
169
        );
170
    }
171
172
    #[cfg(feature = "smallvec")]
173
    #[test]
174
    fn test_smallvec() {
175
        let mut v: smallvec::SmallVec<[u16; 2]> = smallvec::SmallVec::new();
176
        assert_eq!(v.capacity(), 2);
177
        assert!(v.size_hint(32).is_ok());
178
        assert!(v.capacity() >= 32);
179
        assert_eq!(v.len(), 0);
180
        assert!(v.write_slice([0x0061u16, 0x0062u16].as_slice()).is_ok());
181
        assert_eq!(v.len(), 2);
182
        assert!(v.write_char('β˜ƒ').is_ok());
183
        assert_eq!(v.len(), 3);
184
        assert!(v.write_char('😊').is_ok());
185
        assert_eq!(v.len(), 5);
186
        assert_eq!(
187
            v.as_slice(),
188
            [0x0061u16, 0x0062u16, 0x2603u16, 0xD83Du16, 0xDE0Au16].as_slice()
189
        );
190
    }
191
192
    #[cfg(feature = "arrayvec")]
193
    #[test]
194
    fn test_arrayvec() {
195
        let mut v: arrayvec::ArrayVec<u16, 4> = arrayvec::ArrayVec::new();
196
        assert_eq!(v.capacity(), 4);
197
        assert!(v.size_hint(32).is_ok());
198
        assert_eq!(v.capacity(), 4);
199
        assert_eq!(v.len(), 0);
200
        assert!(v.write_char('😊').is_ok());
201
        assert_eq!(v.len(), 2);
202
        assert!(v.write_char('β˜ƒ').is_ok());
203
        assert_eq!(v.len(), 3);
204
        assert!(v.write_char('😊').is_err());
205
        assert_eq!(v.len(), 3);
206
        assert_eq!(v.as_slice(), [0xD83Du16, 0xDE0Au16, 0x2603u16].as_slice());
207
    }
208
}