lodepng 2.1.2

Reading and writing PNG files without system dependencies. Pure Rust port of LodePNG.
Documentation
use std::slice;
use std::ptr;
use ffi::{lodepng_free, lodepng_realloc, Error};

#[allow(non_camel_case_types)]
pub struct ucvector {
    data: *mut u8,
    size: usize,
    allocsize: usize,
}

impl ucvector {
    pub fn into_vec(self) -> Vec<u8> {
        self.slice().to_owned()
    }

    pub fn into_raw(mut self) -> (*mut u8, usize) {
        let ret = (self.data, self.size);
        self.data = ptr::null_mut();
        ret
    }

    pub fn reserve(&mut self, add_size: usize) {
        let n = self.size.checked_add(add_size).unwrap();
        self.reserve_abs(n).unwrap();
    }

    fn reserve_abs(&mut self, allocsize: usize) -> Result<(), Error> {
        if allocsize > self.allocsize {
            let newsize = if allocsize > self.allocsize * 2 {
                allocsize
            } else {
                allocsize * 3 / 2
            };
            let data = unsafe { lodepng_realloc(self.data as *mut _, newsize) };
            if data.is_null() {
                return Err(Error(83));
            }
            self.allocsize = newsize;
            self.data = data as *mut u8;
        }
        Ok(())
    }

    pub fn extend_from_slice(&mut self, data: &[u8]) -> Result<(), Error> {
        let start_offset = self.size;
        let new_length = start_offset.checked_add(data.len()).ok_or(Error(77))?;
        self.resize(new_length)?;
        self.slice_mut()[start_offset..start_offset + data.len()].clone_from_slice(data);
        Ok(())
    }

    pub fn resize(&mut self, size: usize) -> Result<(), Error> {
        self.reserve_abs(size)?;
        self.size = size;
        Ok(())
    }

    pub fn new() -> Self {
        Self {
            data: ptr::null_mut(),
            allocsize: 0,
            size: 0,
        }
    }

    pub unsafe fn from_raw(buffer: &mut *mut u8, size: usize) -> Self {
        let data = *buffer;
        *buffer = ptr::null_mut();
        Self {
            data,
            allocsize: size,
            size: size,
        }
    }

    pub fn len(&self) -> usize {
        self.size
    }

    pub fn last_mut(&mut self) -> &mut u8 {
        unsafe {
            assert!(self.size > 0);
            &mut *self.data.offset(self.size as isize - 1)
        }
    }

    pub fn slice(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(self.data, self.size) }
    }

    pub fn slice_mut(&mut self) -> &mut [u8] {
        unsafe { slice::from_raw_parts_mut(self.data, self.size) }
    }

    pub fn push(&mut self, c: u8) {
        let n = self.size + 1;
        self.resize(n).unwrap();
        *self.last_mut() = c;
    }
}

impl Drop for ucvector {
    fn drop(&mut self) {
        unsafe {
            lodepng_free(self.data as *mut _);
        }
    }
}