Skip to content

Commit

Permalink
Add String::from_utf16.
Browse files Browse the repository at this point in the history
  • Loading branch information
reitermarkus committed Nov 22, 2023
1 parent 7cd2625 commit 8b70be0
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ mod histbuf;
mod indexmap;
mod indexset;
mod linear_map;
mod string;
pub mod string;
mod vec;

#[cfg(feature = "serde")]
Expand Down
56 changes: 54 additions & 2 deletions src/string.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html)
//! A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).

use core::{
cmp::Ordering,
Expand All @@ -10,7 +10,20 @@ use core::{

use crate::Vec;

/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html)
/// A possible error value when converting a `String` from a UTF-16 byte slice.
///
/// This type is the error type for the [`from_utf16`] method on [`String`].
///
/// [`from_utf16`]: String::from_utf16
#[derive(Debug, PartialEq, Eq)]
pub enum FromUtf16Error {
/// The capacity of the `String` is too small for the given operation.
Capacity,
/// Error decoding UTF-16.
DecodeUtf16Error(DecodeUtf16Error),
}

/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
pub struct String<const N: usize> {
vec: Vec<u8, N>,
}
Expand All @@ -36,6 +49,45 @@ impl<const N: usize> String<N> {
Self { vec: Vec::new() }
}

/// Decode a UTF-16–encoded slice `v` into a `String`, returning [`Err`]
/// if `v` contains any invalid data.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use heapless::String;
///
/// // 𝄞music
/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
/// 0x0073, 0x0069, 0x0063];
/// let s: String<10> = String::from_utf16(v).unwrap();
/// assert_eq!(s, "𝄞music");
///
/// // 𝄞mu<invalid>ic
/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
/// 0xD800, 0x0069, 0x0063];
/// assert!(String::<10>::from_utf16(v).is_err());
/// ```
#[inline]
pub fn from_utf16(v: &[u16]) -> Result<Self, FromUtf16Error> {
let mut s = Self::new();

for c in char::decode_utf16(v.iter().cloned()) {
match c {
Ok(c) => {
s.push(c).map_err(|_| FromUtf16Error::Capacity)?;
}
Err(err) => {
return Err(FromUtf16Error::DecodeUtf16Error(err));
}
}
}

Ok(s)
}

/// Convert UTF-8 bytes into a `String`.
///
/// # Examples
Expand Down
2 changes: 1 addition & 1 deletion src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ impl<const N: usize> fmt::Write for Vec<u8, N> {

impl<T, const N: usize> Drop for Vec<T, N> {
fn drop(&mut self) {
// We drop each element used in the vector by turning into a &mut[T]
// We drop each element used in the vector by turning into a `&mut [T]`.
unsafe {
ptr::drop_in_place(self.as_mut_slice());
}
Expand Down

0 comments on commit 8b70be0

Please sign in to comment.