diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d49d1a..0003dac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- Add `zarrs{Get,Set}GlobalConfig` + ### Changed - Bump `zarrs` to 0.22.8 diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..ac54f00 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,62 @@ +use std::ffi::{c_char, CString}; + +use ffi_support::FfiStr; + +use crate::{ZarrsResult, LAST_ERROR}; + +/// Get the global zarrs configuration as a JSON string. +/// +/// # Safety +/// The caller must free the returned string with `zarrsStringFree`. +/// +/// # Errors +/// Returns `ZARRS_ERROR_CONFIG` if serialization fails. +#[no_mangle] +pub unsafe extern "C" fn zarrsGetGlobalConfig(pJsonString: *mut *mut c_char) -> ZarrsResult { + if pJsonString.is_null() { + *LAST_ERROR.lock().unwrap() = "pJsonString is null".to_string(); + return ZarrsResult::ZARRS_ERROR_NULL_PTR; + } + + let config = zarrs::config::global_config(); + + match serde_json::to_string_pretty(&*config) { + Ok(json_str) => match CString::new(json_str) { + Ok(cstring) => { + *pJsonString = cstring.into_raw(); + ZarrsResult::ZARRS_SUCCESS + } + Err(e) => { + *LAST_ERROR.lock().unwrap() = format!("Failed to create C string: {e}"); + ZarrsResult::ZARRS_ERROR_CONFIG + } + }, + Err(e) => { + *LAST_ERROR.lock().unwrap() = format!("Failed to serialize config: {e}"); + ZarrsResult::ZARRS_ERROR_CONFIG + } + } +} + +/// Set the global zarrs configuration from a JSON string. +/// +/// # Safety +/// The caller must provide a valid JSON string representing a zarrs Config. +/// +/// # Errors +/// Returns `ZARRS_ERROR_CONFIG` if deserialization fails or the JSON is invalid. +#[no_mangle] +pub unsafe extern "C" fn zarrsSetGlobalConfig(jsonString: FfiStr) -> ZarrsResult { + let json_str = jsonString.as_str(); + + match serde_json::from_str::(json_str) { + Ok(config) => { + *zarrs::config::global_config_mut() = config; + ZarrsResult::ZARRS_SUCCESS + } + Err(e) => { + *LAST_ERROR.lock().unwrap() = format!("Failed to deserialize config: {e}"); + ZarrsResult::ZARRS_ERROR_CONFIG + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 3bac793..01b1b2f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ use once_cell::sync::Lazy; extern crate zarrs; mod array; +mod config; mod group; mod storage; mod version; @@ -19,6 +20,7 @@ mod version; pub use array::{ array_read::*, array_read_write::*, array_sharded::*, array_write::*, data_type::*, *, }; +pub use config::*; pub use group::{group_write::*, *}; pub use storage::*; pub use version::*; @@ -41,6 +43,7 @@ pub enum ZarrsResult { ZARRS_ERROR_UNSUPPORTED_DATA_TYPE = -12, ZARRS_ERROR_GROUP = -13, ZARRS_ERROR_INCOMPATIBLE_DIMENSIONALITY = -14, + ZARRS_ERROR_CONFIG = -15, } static LAST_ERROR: Lazy> = Lazy::new(|| Mutex::new("".to_string())); diff --git a/zarrs.h b/zarrs.h index a9a8541..1ec3e8c 100644 --- a/zarrs.h +++ b/zarrs.h @@ -38,6 +38,7 @@ enum ZarrsResult ZARRS_ERROR_UNSUPPORTED_DATA_TYPE = -12, ZARRS_ERROR_GROUP = -13, ZARRS_ERROR_INCOMPATIBLE_DIMENSIONALITY = -14, + ZARRS_ERROR_CONFIG = -15, }; #ifndef __cplusplus typedef int32_t ZarrsResult; @@ -537,6 +538,17 @@ ZarrsResult zarrsDestroyStorage(ZarrsStorage storage); */ ZarrsResult zarrsFreeString(char *string); +/** + * Get the global zarrs configuration as a JSON string. + * + * # Safety + * The caller must free the returned string with `zarrsStringFree`. + * + * # Errors + * Returns `ZARRS_ERROR_CONFIG` if serialization fails. + */ +ZarrsResult zarrsGetGlobalConfig(char **pJsonString); + /** * Get the group attributes as a JSON string. * @@ -597,6 +609,17 @@ ZarrsResult zarrsOpenArrayRW(ZarrsStorage storage, const char* path, ZarrsArray */ ZarrsResult zarrsOpenGroupRW(ZarrsStorage storage, const char* path, ZarrsGroup *pGroup); +/** + * Set the global zarrs configuration from a JSON string. + * + * # Safety + * The caller must provide a valid JSON string representing a zarrs Config. + * + * # Errors + * Returns `ZARRS_ERROR_CONFIG` if deserialization fails or the JSON is invalid. + */ +ZarrsResult zarrsSetGlobalConfig(const char* jsonString); + /** * Get the zarrs version. *