use buffer_trait::*;
use core::cmp::min;
use core::mem::MaybeUninit;
use std::io::IoSliceMut;
fn main() {
    unsafely();
    safely();
    safely_fast();
    wrap();
    borrow_and_wrap();
    println!("Ok!");
}
fn unsafely() {
    let mut plain_buf = [0_u8; 10];
    let num = unsafely_read(&mut plain_buf);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
    let mut uninit_buf = [MaybeUninit::<u8>::uninit(); 10];
    let (init, uninit) = unsafely_read(&mut uninit_buf);
    assert_eq!(init, &[0, 1, 2, 3, 4, 5, 6, 7]);
    assert_eq!(uninit.len(), 2);
    let mut vec_buf = Vec::with_capacity(10);
    let num = unsafely_read(spare_capacity(&mut vec_buf));
    assert_eq!(num, 8);
    assert_eq!(vec_buf.capacity(), 10);
    assert_eq!(vec_buf.len(), 8);
    assert_eq!(&vec_buf, &[0, 1, 2, 3, 4, 5, 6, 7]);
    let mut plain_buf = [0_u8; 10];
    let mut io_slice = IoSliceMut::new(&mut plain_buf);
    let num = unsafely_read(&mut io_slice);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
}
fn safely() {
    let mut plain_buf = [0_u8; 10];
    let num = safely_read(&mut plain_buf);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
    let mut uninit_buf = [MaybeUninit::<u8>::uninit(); 10];
    let (init, uninit) = safely_read(&mut uninit_buf);
    assert_eq!(init, &[0, 1, 2, 3, 4, 5, 6, 7]);
    assert_eq!(uninit.len(), 2);
    let mut vec_buf = Vec::with_capacity(10);
    let num = safely_read(spare_capacity(&mut vec_buf));
    assert_eq!(num, 8);
    assert_eq!(vec_buf.capacity(), 10);
    assert_eq!(vec_buf.len(), 8);
    assert_eq!(&vec_buf, &[0, 1, 2, 3, 4, 5, 6, 7]);
    let mut plain_buf = [0_u8; 10];
    let mut io_slice = IoSliceMut::new(&mut plain_buf);
    let num = safely_read(&mut io_slice);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
}
fn safely_fast() {
    let mut plain_buf = [0_u8; 10];
    let num = safely_read_fast(&mut plain_buf);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
    let mut uninit_buf = [MaybeUninit::<u8>::uninit(); 10];
    let (init, uninit) = safely_read_fast(&mut uninit_buf);
    assert_eq!(init, &[0, 1, 2, 3, 4, 5, 6, 7]);
    assert_eq!(uninit.len(), 2);
    let mut vec_buf = Vec::with_capacity(10);
    let num = safely_read_fast(spare_capacity(&mut vec_buf));
    assert_eq!(num, 8);
    assert_eq!(vec_buf.capacity(), 10);
    assert_eq!(vec_buf.len(), 8);
    assert_eq!(&vec_buf, &[0, 1, 2, 3, 4, 5, 6, 7]);
    let mut plain_buf = [0_u8; 10];
    let mut io_slice = IoSliceMut::new(&mut plain_buf);
    let num = safely_read_fast(&mut io_slice);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
}
fn wrap() {
    let mut plain_buf = [0_u8; 10];
    let num = wrap_read(&mut plain_buf);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
    let mut uninit_buf = [MaybeUninit::<u8>::uninit(); 10];
    let (init, uninit) = wrap_read(&mut uninit_buf);
    assert_eq!(init, &[0, 1, 2, 3, 4, 5, 6, 7]);
    assert_eq!(uninit.len(), 2);
    let mut vec_buf = Vec::with_capacity(10);
    let num = wrap_read(spare_capacity(&mut vec_buf));
    assert_eq!(num, 8);
    assert_eq!(vec_buf.capacity(), 10);
    assert_eq!(vec_buf.len(), 8);
    assert_eq!(&vec_buf, &[0, 1, 2, 3, 4, 5, 6, 7]);
    let mut plain_buf = [0_u8; 10];
    let mut io_slice = IoSliceMut::new(&mut plain_buf);
    let num = wrap_read(&mut io_slice);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
}
fn borrow_and_wrap() {
    let mut plain_buf = [0_u8; 10];
    let num = borrow_and_wrap_read(&mut plain_buf);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
    let mut uninit_buf = [MaybeUninit::<u8>::uninit(); 10];
    let (init, uninit) = borrow_and_wrap_read(&mut uninit_buf);
    assert_eq!(init, &[0, 1, 2, 3, 4, 5, 6, 7]);
    assert_eq!(uninit.len(), 2);
    let mut vec_buf = Vec::with_capacity(10);
    let num = borrow_and_wrap_read(spare_capacity(&mut vec_buf));
    assert_eq!(num, 8);
    assert_eq!(vec_buf.capacity(), 10);
    assert_eq!(vec_buf.len(), 8);
    assert_eq!(&vec_buf, &[0, 1, 2, 3, 4, 5, 6, 7]);
    let mut plain_buf = [0_u8; 10];
    let mut io_slice = IoSliceMut::new(&mut plain_buf);
    let num = borrow_and_wrap_read(&mut io_slice);
    assert_eq!(num, 8);
    assert_eq!(&plain_buf, &[0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
}
pub fn unsafely_read<B: Buffer<u8>>(mut b: B) -> B::Output {
    let ptr = b.buffer_ptr();
    let len = b.buffer_len();
    let num = min(len, 8);
        unsafe {
                                for i in 0..num {
            ptr.add(i).write(i as u8);
        }
                b.assume_init(num)
    }
}
#[forbid(unsafe_code)]
pub fn safely_read<B: Buffer<u8>>(b: B) -> B::Output {
    let mut cursor = b.cursor();
    let num = min(cursor.remaining(), 8);
        for i in 0..num {
        cursor.write(i as u8);
    }
    cursor.finish()
}
#[forbid(unsafe_code)]
pub fn safely_read_fast<B: Buffer<u8>>(b: B) -> B::Output {
    let mut cursor = b.cursor();
    let num = min(cursor.remaining(), 8);
            let mut v = Vec::with_capacity(num);
    for i in 0..num {
        v.push(i as u8);
    }
        cursor.write_slice(&v);
    cursor.finish()
}
#[forbid(unsafe_code)]
pub fn wrap_read<B: Buffer<u8>>(b: B) -> B::Output {
    let cursor = b.cursor();
    safely_read(cursor)
}
#[forbid(unsafe_code)]
pub fn borrow_and_wrap_read<B: Buffer<u8>>(b: B) -> B::Output {
    let mut cursor = b.cursor();
    safely_read(&mut cursor);
    cursor.finish()
}