extern crate std;
use core::ptr;
use std::io::{IoSlice, Write};
#[cfg(feature = "fastvec")]
use crate::FastVec;
#[cfg(feature = "arrayvec")]
use crate::ArrayVec;
#[cfg(feature = "smallvec")]
use crate::SmallVec;
#[cfg(all(feature = "arrayvec"))]
impl<const N: usize> Write for ArrayVec<u8, N> {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let len = self.len();
let num = core::cmp::min(N - len, buf.len());
unsafe {
ptr::copy_nonoverlapping(buf.as_ptr(), self.as_mut_ptr().add(len), num);
self.set_len(len + num);
}
Ok(num)
}
#[inline(always)]
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
#[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> std::io::Result<usize> {
let mut num = 0;
for buf in bufs {
if self.is_full() {
break;
}
num += self.write(buf)?;
}
Ok(num)
}
}
#[cfg(all(feature = "fastvec"))]
impl<const N: usize> Write for FastVec<u8, N> {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let len = self.len();
let num = buf.len();
let vec = self.data();
vec.reserve(num);
unsafe {
ptr::copy_nonoverlapping(buf.as_ptr(), vec.as_mut_ptr().add(len), num);
vec.set_len(len + num);
}
Ok(num)
}
#[inline(always)]
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
#[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> std::io::Result<usize> {
let num = bufs.iter().map(|b| b.len()).sum::<usize>();
let vec = self.data();
vec.reserve(num);
for buf in bufs {
let buf_len = buf.len();
let vec_len = vec.len();
unsafe {
ptr::copy_nonoverlapping(buf.as_ptr(), vec.as_mut_ptr().add(vec_len), buf_len);
vec.set_len(vec_len + buf_len);
}
}
Ok(num)
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
Write::write(self, buf)?;
Ok(())
}
}
#[cfg(all(feature = "smallvec"))]
impl<const N: usize> Write for SmallVec<u8, N> {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let len = self.len();
let num = buf.len();
self.reserve(num);
unsafe {
ptr::copy_nonoverlapping(buf.as_ptr(), self.as_mut_ptr().add(len), num);
self.set_len(len + num);
}
Ok(num)
}
#[inline(always)]
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
#[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> std::io::Result<usize> {
let num = bufs.iter().map(|b| b.len()).sum::<usize>();
self.reserve(num);
let base_ptr = self.as_mut_ptr();
for buf in bufs {
let buf_len = buf.len();
let vec_len = self.len();
unsafe {
ptr::copy_nonoverlapping(buf.as_ptr(), base_ptr.add(vec_len), buf_len);
self.set_len(vec_len + buf_len);
}
}
Ok(num)
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
Write::write(self, buf)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::{IoSlice, Write};
#[test]
#[cfg(feature = "arrayvec")]
fn arrayvec_write_basic_and_partial() {
let mut v: ArrayVec<u8, 4> = ArrayVec::new();
let n = v.write(b"ab").unwrap();
assert_eq!(n, 2);
assert_eq!(v.len(), 2);
assert_eq!(v, b"ab");
let n = v.write(b"cdef").unwrap();
assert_eq!(n, 2); assert_eq!(v.len(), 4);
assert_eq!(v, b"abcd");
assert_eq!(v.write(b"abcd").unwrap(), 0);
assert_eq!(v, b"abcd");
}
#[test]
#[cfg(feature = "arrayvec")]
fn arrayvec_write_vectored_partial_stop_on_full() {
let mut v: ArrayVec<u8, 5> = ArrayVec::new();
let bufs = [
IoSlice::new(b"ab"),
IoSlice::new(b"cde"),
IoSlice::new(b"f"),
];
let n = v.write_vectored(&bufs).unwrap();
assert_eq!(n, 5);
assert_eq!(v, b"abcde");
}
#[test]
#[cfg(feature = "fastvec")]
fn fastvec_write_and_vectored() {
let mut v: FastVec<u8, 4> = FastVec::new();
let n = v.write(b"hello").unwrap();
assert_eq!(n, 5);
assert_eq!(v.len(), 5);
assert_eq!(v, b"hello");
let bufs = [IoSlice::new(b" "), IoSlice::new(b"world")];
let n = v.write_vectored(&bufs).unwrap();
assert_eq!(n, 6);
assert_eq!(v, b"hello world");
}
#[test]
#[cfg(feature = "fastvec")]
fn fastvec_write_all_grows() {
let mut v: FastVec<u8, 3> = FastVec::new();
let data = [b'x'; 257];
v.write_all(&data).unwrap();
assert_eq!(v.len(), 257);
assert!(v.as_slice().iter().all(|&c| c == b'x'));
}
#[test]
#[cfg(feature = "smallvec")]
fn smallvec_write_and_vectored() {
let mut v: SmallVec<u8, 4> = SmallVec::new();
let n = v.write(b"hello").unwrap();
assert_eq!(n, 5);
assert_eq!(v.len(), 5);
assert_eq!(v, b"hello");
let bufs = [IoSlice::new(b" "), IoSlice::new(b"world")];
let n = v.write_vectored(&bufs).unwrap();
assert_eq!(n, 6);
assert_eq!(v, b"hello world");
}
#[test]
#[cfg(feature = "smallvec")]
fn smallvec_write_all_grows() {
let mut v: SmallVec<u8, 3> = SmallVec::new();
let data = [b'y'; 257];
v.write_all(&data).unwrap();
assert_eq!(v.len(), 257);
assert!(v.as_slice().iter().all(|&c| c == b'y'));
}
}