#![no_std]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "arrayvec")]
extern crate arrayvec;
#[cfg(feature = "smallvec")]
extern crate smallvec;
pub trait Write16 {
fn write_slice(&mut self, s: &[u16]) -> core::fmt::Result;
#[inline(always)]
fn write_char(&mut self, c: char) -> core::fmt::Result {
let mut buf = [0u16; 2];
self.write_slice(c.encode_utf16(&mut buf))
}
#[inline(always)]
fn size_hint(&mut self, upcoming: usize) -> core::fmt::Result {
let _ = upcoming;
Ok(())
}
}
#[cfg(feature = "alloc")]
impl Write16 for alloc::vec::Vec<u16> {
#[inline(always)]
fn write_slice(&mut self, s: &[u16]) -> core::fmt::Result {
self.extend_from_slice(s);
Ok(())
}
#[inline(always)]
fn write_char(&mut self, c: char) -> core::fmt::Result {
if c <= '\u{FFFF}' {
self.push(c as u16);
} else {
let mut buf = [0u16; 2];
let u = u32::from(c);
buf[0] = (0xD7C0 + (u >> 10)) as u16;
buf[1] = (0xDC00 + (u & 0x3FF)) as u16;
self.extend_from_slice(&mut buf);
}
Ok(())
}
#[inline(always)]
fn size_hint(&mut self, upcoming: usize) -> core::fmt::Result {
self.reserve(upcoming);
Ok(())
}
}
#[cfg(feature = "smallvec")]
impl<A: smallvec::Array<Item = u16>> Write16 for smallvec::SmallVec<A> {
#[inline(always)]
fn write_slice(&mut self, s: &[u16]) -> core::fmt::Result {
self.extend_from_slice(s);
Ok(())
}
#[inline(always)]
fn write_char(&mut self, c: char) -> core::fmt::Result {
if c <= '\u{FFFF}' {
self.push(c as u16);
} else {
let mut buf = [0u16; 2];
let u = u32::from(c);
buf[0] = (0xD7C0 + (u >> 10)) as u16;
buf[1] = (0xDC00 + (u & 0x3FF)) as u16;
self.extend_from_slice(&mut buf);
}
Ok(())
}
#[inline(always)]
fn size_hint(&mut self, upcoming: usize) -> core::fmt::Result {
self.reserve(upcoming);
Ok(())
}
}
#[cfg(feature = "arrayvec")]
impl<const CAP: usize> Write16 for arrayvec::ArrayVec<u16, CAP> {
#[inline(always)]
fn write_slice(&mut self, s: &[u16]) -> core::fmt::Result {
if self.try_extend_from_slice(s).is_ok() {
Ok(())
} else {
Err(core::fmt::Error {})
}
}
#[inline(always)]
fn write_char(&mut self, c: char) -> core::fmt::Result {
if c <= '\u{FFFF}' {
if self.try_push(c as u16).is_ok() {
Ok(())
} else {
Err(core::fmt::Error {})
}
} else {
let mut buf = [0u16; 2];
let u = u32::from(c);
buf[0] = (0xD7C0 + (u >> 10)) as u16;
buf[1] = (0xDC00 + (u & 0x3FF)) as u16;
self.write_slice(&mut buf)
}
}
}
#[cfg(test)]
mod tests {
use crate::Write16;
#[cfg(feature = "alloc")]
#[test]
fn test_vec() {
let mut v: alloc::vec::Vec<u16> = alloc::vec::Vec::new();
assert_eq!(v.capacity(), 0);
assert!(v.size_hint(32).is_ok());
assert!(v.capacity() >= 32);
assert_eq!(v.len(), 0);
assert!(v.write_slice([0x0061u16, 0x0062u16].as_slice()).is_ok());
assert_eq!(v.len(), 2);
assert!(v.write_char('β').is_ok());
assert_eq!(v.len(), 3);
assert!(v.write_char('π').is_ok());
assert_eq!(v.len(), 5);
assert_eq!(
v.as_slice(),
[0x0061u16, 0x0062u16, 0x2603u16, 0xD83Du16, 0xDE0Au16].as_slice()
);
}
#[cfg(feature = "smallvec")]
#[test]
fn test_smallvec() {
let mut v: smallvec::SmallVec<[u16; 2]> = smallvec::SmallVec::new();
assert_eq!(v.capacity(), 2);
assert!(v.size_hint(32).is_ok());
assert!(v.capacity() >= 32);
assert_eq!(v.len(), 0);
assert!(v.write_slice([0x0061u16, 0x0062u16].as_slice()).is_ok());
assert_eq!(v.len(), 2);
assert!(v.write_char('β').is_ok());
assert_eq!(v.len(), 3);
assert!(v.write_char('π').is_ok());
assert_eq!(v.len(), 5);
assert_eq!(
v.as_slice(),
[0x0061u16, 0x0062u16, 0x2603u16, 0xD83Du16, 0xDE0Au16].as_slice()
);
}
#[cfg(feature = "arrayvec")]
#[test]
fn test_arrayvec() {
let mut v: arrayvec::ArrayVec<u16, 4> = arrayvec::ArrayVec::new();
assert_eq!(v.capacity(), 4);
assert!(v.size_hint(32).is_ok());
assert_eq!(v.capacity(), 4);
assert_eq!(v.len(), 0);
assert!(v.write_char('π').is_ok());
assert_eq!(v.len(), 2);
assert!(v.write_char('β').is_ok());
assert_eq!(v.len(), 3);
assert!(v.write_char('π').is_err());
assert_eq!(v.len(), 3);
assert_eq!(v.as_slice(), [0xD83Du16, 0xDE0Au16, 0x2603u16].as_slice());
}
}