use std::{cell::OnceCell, time::Duration};
use crate::{
ffi::{NsError, TryOrInitialize},
noosphere::{NoosphereContext, NoosphereContextConfiguration},
NoosphereNetwork, NoosphereSecurity, NoosphereStorage, NoosphereStorageConfig,
NoosphereStoragePath,
};
use anyhow::{anyhow, Result};
use pkg_version::*;
use safer_ffi::prelude::*;
use tokio::runtime::Runtime as TokioRuntime;
use url::Url;
#[ffi_export]
#[allow(unused)]
const NOOSPHERE_VERSION_MAJOR: u32 = pkg_version_major!();
#[ffi_export]
#[allow(unused)]
const NOOSPHERE_VERSION_MINOR: u32 = pkg_version_minor!();
#[ffi_export]
#[allow(unused)]
const NOOSPHERE_VERSION_PATCH: u32 = pkg_version_patch!();
#[derive_ReprC(rename = "ns_noosphere")]
#[repr(opaque)]
pub struct NsNoosphere {
inner: NoosphereContext,
async_runtime: OnceCell<TokioRuntime>,
}
impl NsNoosphere {
pub(crate) fn new(
global_storage_path: &str,
sphere_storage_path: &str,
gateway_api: Option<&Url>,
) -> Result<Self> {
Ok(NsNoosphere {
inner: NoosphereContext::new(NoosphereContextConfiguration {
storage: NoosphereStorage {
path: NoosphereStoragePath::Scoped(sphere_storage_path.into()),
config: NoosphereStorageConfig::default(),
},
security: NoosphereSecurity::Insecure {
path: global_storage_path.into(),
},
network: NoosphereNetwork::Http {
gateway_api: gateway_api.cloned(),
ipfs_gateway_url: None,
},
})?,
async_runtime: OnceCell::from(TokioRuntime::new()?),
})
}
pub(crate) fn async_runtime(&self) -> &TokioRuntime {
self.async_runtime.get().unwrap()
}
pub(crate) fn inner(&self) -> &NoosphereContext {
&self.inner
}
}
impl Drop for NsNoosphere {
fn drop(&mut self) {
if let Some(async_runtime) = self.async_runtime.take() {
async_runtime.shutdown_timeout(Duration::from_secs(60));
}
}
}
#[ffi_export]
pub fn ns_initialize(
global_storage_path: char_p::Ref<'_>,
sphere_storage_path: char_p::Ref<'_>,
gateway_url: Option<char_p::Ref<'_>>,
error_out: Option<Out<'_, repr_c::Box<NsError>>>,
) -> Option<repr_c::Box<NsNoosphere>> {
error_out.try_or_initialize(|| {
let gateway_url = match gateway_url {
Some(raw_url) => Some(Url::parse(raw_url.to_str()).map_err(|error| anyhow!(error))?),
None => None,
};
Ok(Box::new(NsNoosphere::new(
global_storage_path.to_str(),
sphere_storage_path.to_str(),
gateway_url.as_ref(),
)?)
.into())
})
}
#[ffi_export]
pub fn ns_free(noosphere: repr_c::Box<NsNoosphere>) {
drop(noosphere)
}
#[ffi_export]
pub fn ns_bytes_free(bytes: c_slice::Box<u8>) {
drop(bytes)
}
#[ffi_export]
pub fn ns_string_free(string: char_p::Box) {
drop(string)
}
#[ffi_export]
pub fn ns_string_array_free(string_array: c_slice::Box<char_p::Box>) {
drop(string_array)
}