Skip to content

Commit 3b88d11

Browse files
committed
Add String::from_utf16.
1 parent c7c731d commit 3b88d11

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ mod histbuf;
9797
mod indexmap;
9898
mod indexset;
9999
mod linear_map;
100-
mod string;
100+
pub mod string;
101101
mod vec;
102102

103103
#[cfg(feature = "serde")]

src/string.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html)
22
33
use core::{
4+
char::DecodeUtf16Error,
45
cmp::Ordering,
56
fmt,
67
fmt::{Arguments, Write},
@@ -10,7 +11,29 @@ use core::{
1011

1112
use crate::Vec;
1213

13-
/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html)
14+
/// A possible error value when converting a [`String`] from a UTF-16 byte slice.
15+
///
16+
/// This type is the error type for the [`from_utf16`] method on [`String`].
17+
///
18+
/// [`from_utf16`]: String::from_utf16
19+
#[derive(Debug)]
20+
pub enum FromUtf16Error {
21+
/// The capacity of the `String` is too small for the given operation.
22+
Capacity,
23+
/// Error decoding UTF-16.
24+
DecodeUtf16Error(DecodeUtf16Error),
25+
}
26+
27+
impl fmt::Display for FromUtf16Error {
28+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29+
match self {
30+
Self::Capacity => "insufficient capacity".fmt(f),
31+
Self::DecodeUtf16Error(e) => write!(f, "invalid UTF-16: {}", e),
32+
}
33+
}
34+
}
35+
36+
/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
1437
pub struct String<const N: usize> {
1538
vec: Vec<u8, N>,
1639
}
@@ -36,6 +59,43 @@ impl<const N: usize> String<N> {
3659
Self { vec: Vec::new() }
3760
}
3861

62+
/// Decodes a UTF-16–encoded slice `v` into a `String`, returning [`Err`]
63+
/// if `v` contains any invalid data.
64+
///
65+
/// # Examples
66+
///
67+
/// Basic usage:
68+
///
69+
/// ```
70+
/// use heapless::String;
71+
///
72+
/// // 𝄞music
73+
/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0x0069, 0x0063];
74+
/// let s: String<10> = String::from_utf16(v).unwrap();
75+
/// assert_eq!(s, "𝄞music");
76+
///
77+
/// // 𝄞mu<invalid>ic
78+
/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063];
79+
/// assert!(String::<10>::from_utf16(v).is_err());
80+
/// ```
81+
#[inline]
82+
pub fn from_utf16(v: &[u16]) -> Result<Self, FromUtf16Error> {
83+
let mut s = Self::new();
84+
85+
for c in char::decode_utf16(v.iter().cloned()) {
86+
match c {
87+
Ok(c) => {
88+
s.push(c).map_err(|_| FromUtf16Error::Capacity)?;
89+
}
90+
Err(err) => {
91+
return Err(FromUtf16Error::DecodeUtf16Error(err));
92+
}
93+
}
94+
}
95+
96+
Ok(s)
97+
}
98+
3999
/// Convert UTF-8 bytes into a `String`.
40100
///
41101
/// # Examples

0 commit comments

Comments
 (0)