use anyhow::anyhow;
use libc::c_char;
use serde_json::Value as JsonValue;
use tracing::trace;
use pact_models::provider_states::ProviderState;
use crate::{as_mut, as_ref, ffi_fn};
use crate::util::*;
ffi_fn! {
fn pactffi_provider_state_get_name(provider_state: *const ProviderState) -> *const c_char {
let provider_state = as_ref!(provider_state);
let name = string::to_c(&provider_state.name)?;
name as *const c_char
} {
std::ptr::null()
}
}
ffi_fn! {
fn pactffi_provider_state_get_param_iter(
provider_state: *mut ProviderState
) -> *mut ProviderStateParamIterator {
let provider_state = as_mut!(provider_state);
let iter = ProviderStateParamIterator {
keys: provider_state.params.keys().cloned().collect(),
current: 0,
provider_state: provider_state as *const ProviderState,
};
ptr::raw_to(iter)
} {
std::ptr::null_mut()
}
}
ffi_fn! {
fn pactffi_provider_state_param_iter_next(
iter: *mut ProviderStateParamIterator
) -> *mut ProviderStateParamPair {
let iter = as_mut!(iter);
let provider_state = as_ref!(iter.provider_state);
match iter.next() {
Some(key) => {
let (key, value) = provider_state
.params
.get_key_value(key)
.ok_or(anyhow!("iter provided invalid param key"))?;
let pair = ProviderStateParamPair::new(key, value)?;
ptr::raw_to(pair)
}
None => {
trace!("iter past the end of params");
std::ptr::null_mut()
}
}
} {
std::ptr::null_mut()
}
}
ffi_fn! {
fn pactffi_provider_state_delete(provider_state: *mut ProviderState) {
ptr::drop_raw(provider_state);
}
}
ffi_fn! {
fn pactffi_provider_state_param_iter_delete(iter: *mut ProviderStateParamIterator) {
ptr::drop_raw(iter);
}
}
ffi_fn! {
fn pactffi_provider_state_param_pair_delete(pair: *mut ProviderStateParamPair) {
ptr::drop_raw(pair);
}
}
#[derive(Debug)]
pub struct ProviderStateParamIterator {
keys: Vec<String>,
current: usize,
provider_state: *const ProviderState,
}
impl ProviderStateParamIterator {
fn next(&mut self) -> Option<&String> {
let idx = self.current;
self.current += 1;
self.keys.get(idx)
}
}
#[derive(Debug)]
#[repr(C)]
#[allow(missing_copy_implementations)]
pub struct ProviderStateParamPair {
key: *const c_char,
value: *const c_char,
}
impl ProviderStateParamPair {
fn new(
key: &str,
value: &JsonValue,
) -> anyhow::Result<ProviderStateParamPair> {
let value = value.to_string();
Ok(ProviderStateParamPair {
key: string::to_c(key)? as *const c_char,
value: string::to_c(&value)? as *const c_char,
})
}
}