use std::io::{self, Error, ErrorKind};
use std::ptr;
use super::super::{ReadIter, GetIter, SetIter, Appender, Prepender};
#[derive(Copy, Clone)]
pub struct Filling {
v: u8,
n: usize,
}
#[inline]
pub fn filling(val: u8, count: usize) -> Filling {
Filling { v: val, n: count }
}
impl Filling {
#[inline]
pub fn new(val: u8, count: usize) -> Self {
Filling { v: val, n: count }
}
#[inline]
pub fn val(&self) -> u8 {
self.v
}
#[inline]
pub fn count(&self) -> usize {
self.n
}
}
#[inline]
pub fn read(chain: &mut ReadIter) -> io::Result<Vec<u8>> {
let len = chain.len();
read_exact(chain, len)
}
pub fn read_exact(chain: &mut ReadIter, mut n: usize) -> io::Result<Vec<u8>> {
if n == 0 {
return Ok(Vec::new());
}
let mut buf = Vec::with_capacity(n);
unsafe { buf.set_len(n) };
let mut ptr_dst = buf.as_mut_ptr();
for mut block in chain {
let off = block.read_pos();
let ptr_src = unsafe { block.as_ptr().offset(off as isize) };
let len = block.len();
if len >= n {
unsafe { ptr::copy_nonoverlapping(ptr_src, ptr_dst, n) };
block.set_read_pos(off + n);
return Ok(buf);
}
n -= len;
unsafe {
ptr::copy_nonoverlapping(ptr_src, ptr_dst, len);
ptr_dst = ptr_dst.offset(len as isize);
}
let pos = block.write_pos();
block.set_read_pos(pos);
}
Err(Error::new(
ErrorKind::UnexpectedEof,
"codec::u8s::read_exact",
))
}
#[inline]
pub fn get(chain: &mut GetIter) -> io::Result<Vec<u8>> {
let len = chain.len();
get_exact(chain, len)
}
pub fn get_exact(chain: &mut GetIter, mut n: usize) -> io::Result<Vec<u8>> {
if n == 0 {
return Ok(Vec::new());
}
let mut buf = Vec::with_capacity(n);
unsafe { buf.set_len(n) };
let mut ptr_dst = buf.as_mut_ptr();
for block in chain {
let off = block.read_pos() as isize;
let ptr_src = unsafe { block.as_ptr().offset(off) };
let len = block.len();
if len >= n {
unsafe { ptr::copy_nonoverlapping(ptr_src, ptr_dst, n) };
return Ok(buf);
}
n -= len;
unsafe {
ptr::copy_nonoverlapping(ptr_src, ptr_dst, len);
ptr_dst = ptr_dst.offset(len as isize);
}
}
Err(Error::new(
ErrorKind::UnexpectedEof,
"codec::u8s::get_exact",
))
}
pub fn set(v: &[u8], chain: &mut SetIter) -> io::Result<usize> {
let mut ptr_src = v.as_ptr();
let mut n = v.len();
for mut block in chain {
let off = block.read_pos() as isize;
let ptr_dst = unsafe { block.as_mut_ptr().offset(off) };
let len = block.len();
if len >= n {
unsafe { ptr::copy_nonoverlapping(ptr_src, ptr_dst, n) };
return Ok(v.len());
}
n -= len;
unsafe {
ptr::copy_nonoverlapping(ptr_src, ptr_dst, len);
ptr_src = ptr_src.offset(len as isize);
}
}
Err(Error::new(ErrorKind::UnexpectedEof, "codec::u8s::set"))
}
pub fn append(v: &[u8], chain: &mut Appender) -> io::Result<usize> {
let mut ptr_src = v.as_ptr();
let mut n = v.len();
loop {
if let Some(mut block) = chain.last_mut() {
let off = block.write_pos();
let ptr_dst = unsafe { block.as_mut_ptr().offset(off as isize) };
let appendable = block.appendable();
if appendable >= n {
unsafe { ptr::copy_nonoverlapping(ptr_src, ptr_dst, n) };
block.set_write_pos(off + n);
return Ok(v.len());
}
n -= appendable;
unsafe {
ptr::copy_nonoverlapping(ptr_src, ptr_dst, appendable);
ptr_src = ptr_src.offset(appendable as isize);
}
let cap = block.capacity();
block.set_write_pos(cap);
}
chain.append(0);
}
}
pub fn append_bytes(v: Vec<u8>, chain: &mut Appender) -> io::Result<usize> {
let n = v.len();
if n < 6 * 1024 {
append(&v, chain)
} else {
chain.append_bytes(v);
Ok(n)
}
}
pub fn prepend(v: &[u8], chain: &mut Prepender) -> io::Result<usize> {
let mut ptr_src = v.as_ptr();
let mut n = v.len();
unsafe { ptr_src = ptr_src.offset(n as isize) };
loop {
if let Some(mut block) = chain.first_mut() {
let prependable = block.prependable();
let mut ptr_dst = block.as_mut_ptr();
if prependable >= n {
let off = prependable - n;
unsafe {
ptr_dst = ptr_dst.offset(off as isize);
ptr_src = ptr_src.offset(-(n as isize));
ptr::copy_nonoverlapping(ptr_src, ptr_dst, n);
}
block.set_read_pos(off);
return Ok(v.len());
}
n -= prependable;
unsafe {
ptr_src = ptr_src.offset(-(prependable as isize));
ptr::copy_nonoverlapping(ptr_src, ptr_dst, prependable);
}
block.set_read_pos(0);
}
chain.prepend(0);
}
}
pub fn prepend_bytes(v: Vec<u8>, chain: &mut Prepender) -> io::Result<usize> {
let n = v.len();
if n < 6 * 1024 {
prepend(&v, chain)
} else {
chain.prepend_bytes(v);
Ok(n)
}
}
pub fn set_fill(filling: Filling, chain: &mut SetIter) -> io::Result<usize> {
let mut n = filling.count();
for mut block in chain {
let off = block.read_pos() as isize;
let ptr_dst = unsafe { block.as_mut_ptr().offset(off) };
let len = block.len();
if len >= n {
unsafe { ptr::write_bytes(ptr_dst, filling.val(), n) };
return Ok(filling.count());
}
n -= len;
unsafe { ptr::write_bytes(ptr_dst, filling.val(), len) };
}
Err(Error::new(ErrorKind::UnexpectedEof, "codec::u8s::set_fill"))
}
pub fn append_fill(filling: Filling, chain: &mut Appender) -> io::Result<usize> {
let mut n = filling.count();
loop {
if let Some(mut block) = chain.last_mut() {
let off = block.write_pos();
let ptr_dst = unsafe { block.as_mut_ptr().offset(off as isize) };
let appendable = block.appendable();
if appendable >= n {
unsafe { ptr::write_bytes(ptr_dst, filling.val(), n) };
block.set_write_pos(off + n);
return Ok(filling.count());
}
n -= appendable;
unsafe { ptr::write_bytes(ptr_dst, filling.val(), appendable) };
let cap = block.capacity();
block.set_write_pos(cap);
}
chain.append(0);
}
}
pub fn prepend_fill(filling: Filling, chain: &mut Prepender) -> io::Result<usize> {
let mut n = filling.count();
loop {
if let Some(mut block) = chain.first_mut() {
let prependable = block.prependable();
let mut ptr_dst = block.as_mut_ptr();
if prependable >= n {
let off = prependable - n;
unsafe {
ptr_dst = ptr_dst.offset(off as isize);
ptr::write_bytes(ptr_dst, filling.val(), n);
}
block.set_read_pos(off);
return Ok(filling.count());
}
n -= prependable;
unsafe { ptr::write_bytes(ptr_dst, filling.val(), prependable) };
block.set_read_pos(0);
}
chain.prepend(0);
}
}