ruyi 0.1.6

An event-driven framework for non-blocking, asynchronous I/O in Rust
Documentation
use std::io::{self, Error, ErrorKind};

use super::super::super::{ReadIter, GetIter, SetIter, Appender, Prepender};

pub fn read(chain: &mut ReadIter) -> io::Result<u16> {
    let mut v = 0u16;
    let mut shift = 0;
    for mut block in chain {
        let ptr_u8 = block.as_ptr();
        let write_pos = block.write_pos();
        for pos in block.read_pos()..write_pos {
            let b = unsafe { *ptr_u8.offset(pos as isize) } as u16;
            v |= (b & 0x7F).wrapping_shl(shift);
            if b & !0x7F == 0 {
                block.set_read_pos(pos + 1);
                return Ok(v);
            }
            shift = shift.wrapping_add(7);
        }
        block.set_read_pos(write_pos);
    }
    Err(Error::new(
        ErrorKind::UnexpectedEof,
        "codec::u16::varint::read",
    ))
}

pub fn get(chain: &mut GetIter) -> io::Result<u16> {
    let mut v = 0u16;
    let mut shift = 0;
    for block in chain {
        let ptr_u8 = block.as_ptr();
        for pos in block.read_pos()..block.write_pos() {
            let b = unsafe { *ptr_u8.offset(pos as isize) } as u16;
            v |= (b & 0x7F).wrapping_shl(shift);
            if b & !0x7F == 0 {
                return Ok(v);
            }
            shift = shift.wrapping_add(7);
        }
    }
    Err(Error::new(
        ErrorKind::UnexpectedEof,
        "codec::u16::varint::get",
    ))
}

pub fn set(mut v: u16, chain: &mut SetIter) -> io::Result<usize> {
    let mut n = 0usize;
    for mut block in chain {
        let ptr_u8 = block.as_mut_ptr();
        for pos in block.read_pos()..block.write_pos() {
            n += 1;
            if v & !0x7F == 0 {
                unsafe { *ptr_u8.offset(pos as isize) = v as u8 };
                return Ok(n);
            }
            let b = (v | 0x80) as u8;
            unsafe { *ptr_u8.offset(pos as isize) = b };
            v >>= 7;
        }
    }
    Err(Error::new(
        ErrorKind::UnexpectedEof,
        "codec::u16::varint::set",
    ))
}

pub fn append(mut v: u16, chain: &mut Appender) -> io::Result<usize> {
    let mut n = 0usize;
    loop {
        if let Some(mut block) = chain.last_mut() {
            let cap = block.capacity();
            let ptr_u8 = block.as_mut_ptr();
            for pos in block.write_pos()..cap {
                n += 1;
                if v & !0x7F == 0 {
                    unsafe { *ptr_u8.offset(pos as isize) = v as u8 };
                    block.set_write_pos(pos + 1);
                    return Ok(n);
                }
                let b = (v | 0x80) as u8;
                unsafe { *ptr_u8.offset(pos as isize) = b };
                v >>= 7;
            }
            block.set_write_pos(cap);
        }
        chain.append(0);
    }
}

pub fn prepend(v: u16, chain: &mut Prepender) -> io::Result<usize> {
    let mut shift = 0usize;
    while (v >> shift) > 0x7F {
        shift += 7;
    }
    let mut n = 0usize;
    let mut flag = 0u16;
    loop {
        if let Some(mut block) = chain.first_mut() {
            for pos in (0..block.read_pos()).rev() {
                n += 1;
                let b = (v >> shift | flag) as u8;
                unsafe { *block.as_mut_ptr().offset(pos as isize) = b };
                if shift == 0 {
                    block.set_read_pos(pos);
                    return Ok(n);
                }
                flag = 0x80;
                shift -= 7;
            }
            block.set_read_pos(0);
        }
        chain.prepend(0);
    }
}