libstaticvec 0.2.1

Experimentally provides a cdylib wrapping a (currently minimal) subset of the functionality of StaticVec, for use from C or any language with dynamic library support.
#![allow(incomplete_features)]
#![feature(const_extern_fn)]
#![feature(const_generics)]
#![feature(const_raw_ptr_deref)]

use staticvec::StaticVec;

#[cfg(feature = "capacity_16")]
pub const VECTOR_CAPACITY: usize = 16;

#[cfg(feature = "capacity_32")]
pub const VECTOR_CAPACITY: usize = 32;

#[cfg(feature = "capacity_64")]
pub const VECTOR_CAPACITY: usize = 64;

#[cfg(feature = "capacity_128")]
pub const VECTOR_CAPACITY: usize = 128;

#[cfg(feature = "capacity_256")]
pub const VECTOR_CAPACITY: usize = 256;

#[cfg(feature = "capacity_512")]
pub const VECTOR_CAPACITY: usize = 512;

pub type VoidPtr = *const core::ffi::c_void;

// TODO: Figure out if there's any possible way to accept more than
// just opaque pointers.
pub type CStaticVec = StaticVec<VoidPtr, VECTOR_CAPACITY>;

// TODO: Maybe make this an actual union or something? Might not be worth
// it though.
#[repr(C)]
pub struct COption {
  is_some: bool,
  value: VoidPtr,
}

#[no_mangle]
pub const unsafe extern "C" fn staticvec_capacity(vec: *const CStaticVec) -> usize {
  (*vec).capacity()
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_clear(vec: *mut CStaticVec) {
  (*vec).clear();
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_contains(vec: *const CStaticVec, item: VoidPtr) -> bool {
  (*vec).contains(&item)
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_get(vec: *const CStaticVec, index: usize) -> VoidPtr {
  (*vec)[index]
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_insert(vec: *mut CStaticVec, index: usize, item: VoidPtr) {
  (*vec).insert(index, item);
}

#[no_mangle]
pub const unsafe extern "C" fn staticvec_len(vec: *const CStaticVec) -> usize {
  (*vec).len()
}

#[no_mangle]
pub const extern "C" fn staticvec_new() -> CStaticVec {
  StaticVec::new()
}

#[no_mangle]
pub const extern "C" fn staticvec_new_from_const_array(values: [VoidPtr; VECTOR_CAPACITY]) -> CStaticVec {
  StaticVec::new_from_const_array(values)
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_pop(vec: *mut CStaticVec) -> COption {
  let res = (*vec).pop();
  if res.is_some() {
    COption {
      is_some: true,
      value: res.unwrap(),
    }
  } else {
    COption {
      is_some: false,
      value: core::ptr::null(),
    }
  }
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_push(vec: *mut CStaticVec, item: VoidPtr) {
  (*vec).push(item);
}

#[no_mangle]
pub const unsafe extern "C" fn staticvec_remaining_capacity(vec: *const CStaticVec) -> usize {
  (*vec).remaining_capacity()
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_remove(vec: *mut CStaticVec, index: usize) -> VoidPtr {
  (*vec).remove(index)
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_remove_item(vec: *mut CStaticVec, item: VoidPtr) -> COption {
  let res = (*vec).remove_item(&item);
  if res.is_some() {
    COption {
      is_some: true,
      value: res.unwrap(),
    }
  } else {
    COption {
      is_some: false,
      value: core::ptr::null(),
    }
  }
}

#[no_mangle]
pub unsafe extern "C" fn staticvec_set(vec: *mut CStaticVec, index: usize, item: VoidPtr) {
  (*vec)[index] = item
}

#[no_mangle]
pub const unsafe extern "C" fn staticvec_size_in_bytes(vec: *const CStaticVec) -> usize {
  (*vec).size_in_bytes()
}