use opendp_derive::bootstrap;
use crate::{
core::{FfiResult, Measure, PrivacyMap},
error::Fallible,
ffi::any::{AnyMeasure, AnyMeasurement, AnyObject, Downcast},
measures::{MaxDivergence, ZeroConcentratedDivergence, ffi::ExtrinsicDivergence},
};
#[bootstrap(features("contrib"))]
fn make_approximate(measurement: &AnyMeasurement) -> Fallible<AnyMeasurement> {
fn monomorphize<MO: 'static + Measure>(
measurement: &AnyMeasurement,
) -> Fallible<AnyMeasurement> {
let privacy_map = measurement.privacy_map.clone();
let measurement = measurement.with_map(
measurement.input_metric.clone(),
try_!(measurement.output_measure.clone().downcast::<MO>()),
PrivacyMap::new_fallible(move |d_in: &AnyObject| {
privacy_map.eval(d_in)?.downcast::<MO::Distance>()
}),
)?;
let m = super::make_approximate(measurement)?;
let privacy_map = m.privacy_map.clone();
m.with_map(
m.input_metric.clone(),
AnyMeasure::new(m.output_measure.clone()),
PrivacyMap::new_fallible(move |d_in: &AnyObject| {
privacy_map.eval(d_in).map(AnyObject::new)
}),
)
}
dispatch!(
monomorphize,
[(
measurement.output_measure.type_,
[
MaxDivergence,
ZeroConcentratedDivergence,
ExtrinsicDivergence
]
)],
(measurement)
)
.into()
}
#[unsafe(no_mangle)]
pub extern "C" fn opendp_combinators__make_approximate(
measurement: *const AnyMeasurement,
) -> FfiResult<*mut AnyMeasurement> {
FfiResult::from(make_approximate(try_as_ref!(measurement)))
}