pub mod array_read;
pub mod array_read_write;
pub mod array_write;
use derive_more::Deref;
use ffi_support::FfiStr;
use zarrs::array::{Array, ArrayMetadata};
use crate::{
storage::{ZarrsStorage, ZarrsStorageEnum},
ZarrsResult, LAST_ERROR,
};
#[doc(hidden)]
#[allow(clippy::upper_case_acronyms)]
pub enum ZarrsArrayEnum {
R(Array<dyn zarrs::storage::ReadableStorageTraits>),
W(Array<dyn zarrs::storage::WritableStorageTraits>),
L(Array<dyn zarrs::storage::ListableStorageTraits>),
RL(Array<dyn zarrs::storage::ReadableListableStorageTraits>),
RW(Array<dyn zarrs::storage::ReadableWritableStorageTraits>),
RWL(Array<dyn zarrs::storage::ReadableWritableListableStorageTraits>),
}
macro_rules! array_fn {
($array:expr, $fn:ident ) => {
match $array {
ZarrsArrayEnum::R(array) => array.$fn(),
ZarrsArrayEnum::W(array) => array.$fn(),
ZarrsArrayEnum::L(array) => array.$fn(),
ZarrsArrayEnum::RL(array) => array.$fn(),
ZarrsArrayEnum::RW(array) => array.$fn(),
ZarrsArrayEnum::RWL(array) => array.$fn(),
}
};
($array:expr, $fn:ident, $( $args:expr ),* ) => {
match $array {
ZarrsArrayEnum::R(array) => array.$fn($( $args ),*),
ZarrsArrayEnum::W(array) => array.$fn($( $args ),*),
ZarrsArrayEnum::L(array) => array.$fn($( $args ),*),
ZarrsArrayEnum::RL(array) => array.$fn($( $args ),*),
ZarrsArrayEnum::RW(array) => array.$fn($( $args ),*),
ZarrsArrayEnum::RWL(array) => array.$fn($( $args ),*),
}
};
}
pub(crate) use array_fn;
#[doc(hidden)]
#[derive(Deref)]
pub struct ZarrsArray_T(pub ZarrsArrayEnum);
pub type ZarrsArray = *mut ZarrsArray_T;
#[no_mangle]
pub unsafe extern "C" fn zarrsCreateArrayRW(
storage: ZarrsStorage,
path: FfiStr,
pArray: *mut ZarrsArray,
) -> ZarrsResult {
if storage.is_null() {
*LAST_ERROR = "storage is null".to_string();
return ZarrsResult::ZARRS_ERROR_NULL_PTR;
}
let storage = &**storage;
if let ZarrsStorageEnum::RW(storage) = storage {
match Array::new(storage.clone(), path.into()) {
Ok(array) => {
*pArray = Box::into_raw(Box::new(ZarrsArray_T(ZarrsArrayEnum::RW(array))));
ZarrsResult::ZARRS_SUCCESS
}
Err(err) => {
*LAST_ERROR = err.to_string();
ZarrsResult::ZARRS_ERROR_ARRAY
}
}
} else {
*LAST_ERROR = "storage does not support read and write".to_string();
ZarrsResult::ZARRS_ERROR_STORAGE_CAPABILITY
}
}
#[no_mangle]
pub unsafe extern "C" fn zarrsCreateArrayRWWithMetadata(
storage: ZarrsStorage,
path: FfiStr,
metadata: FfiStr,
pArray: *mut ZarrsArray,
) -> ZarrsResult {
if storage.is_null() {
*LAST_ERROR = "storage is null".to_string();
return ZarrsResult::ZARRS_ERROR_NULL_PTR;
}
let storage = &**storage;
let metadata = match serde_json::from_str::<ArrayMetadata>(metadata.as_str()) {
Ok(metadata) => metadata,
Err(err) => {
*LAST_ERROR = err.to_string();
return ZarrsResult::ZARRS_ERROR_INVALID_METADATA;
}
};
if let ZarrsStorageEnum::RW(storage) = storage {
match Array::new_with_metadata(storage.clone(), path.into(), metadata) {
Ok(array) => {
*pArray = Box::into_raw(Box::new(ZarrsArray_T(ZarrsArrayEnum::RW(array))));
ZarrsResult::ZARRS_SUCCESS
}
Err(err) => {
*LAST_ERROR = err.to_string();
ZarrsResult::ZARRS_ERROR_ARRAY
}
}
} else {
*LAST_ERROR = "storage does not support read and write".to_string();
ZarrsResult::ZARRS_ERROR_STORAGE_CAPABILITY
}
}
#[no_mangle]
pub unsafe extern "C" fn zarrsDestroyArray(array: ZarrsArray) -> ZarrsResult {
if array.is_null() {
ZarrsResult::ZARRS_ERROR_NULL_PTR
} else {
unsafe { array.to_owned().drop_in_place() };
ZarrsResult::ZARRS_SUCCESS
}
}
#[no_mangle]
pub unsafe extern "C" fn zarrsArrayGetChunkSize(
array: ZarrsArray,
chunk_indices: *const u64,
chunk_indices_len: usize,
chunk_bytes_length: *mut usize,
) -> ZarrsResult {
if array.is_null() {
return ZarrsResult::ZARRS_ERROR_NULL_PTR;
}
let array = &**array;
let chunk_indices = std::slice::from_raw_parts(chunk_indices, chunk_indices_len);
let chunk_representation = array_fn!(array, chunk_array_representation, chunk_indices);
match chunk_representation {
Ok(chunk_representation) => {
*chunk_bytes_length = usize::try_from(chunk_representation.size()).unwrap();
ZarrsResult::ZARRS_SUCCESS
}
Err(err) => {
*LAST_ERROR = err.to_string();
ZarrsResult::ZARRS_ERROR_INVALID_INDICES
}
}
}
#[no_mangle]
pub unsafe extern "C" fn zarrsArrayGetSubsetSize(
array: ZarrsArray,
subset_shape: *const usize,
subset_dimensionality: usize,
subset_bytes_length: *mut usize,
) -> ZarrsResult {
if array.is_null() {
return ZarrsResult::ZARRS_ERROR_NULL_PTR;
}
let array = &**array;
let subset_shape = std::slice::from_raw_parts(subset_shape, subset_dimensionality);
let data_type = array_fn!(array, data_type);
*subset_bytes_length = subset_shape.iter().product::<usize>() * data_type.size();
ZarrsResult::ZARRS_SUCCESS
}