#![doc = include_str!("../README.md")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(
nonstandard_style,
rust_2018_idioms,
rustdoc::broken_intra_doc_links,
rustdoc::private_intra_doc_links
)]
#![forbid(non_ascii_idents)]
#[cxx::bridge(namespace = "libnixstore")]
mod ffi {
struct InternalPathInfo {
drv: String,
narhash: String,
time: i64,
size: usize,
refs: Vec<String>,
sigs: Vec<String>,
ca: String,
}
struct InternalTuple {
lhs: String,
rhs: String,
}
struct InternalDrv {
outputs: Vec<InternalTuple>,
input_drvs: Vec<String>,
input_srcs: Vec<String>,
platform: String,
builder: String,
args: Vec<String>,
env: Vec<InternalTuple>,
}
unsafe extern "C++" {
include!("libnixstore/include/nix.h");
fn init();
fn set_verbosity(level: i32);
fn is_valid_path(path: &str) -> Result<bool>;
fn query_references(path: &str) -> Result<Vec<String>>;
fn query_path_hash(path: &str) -> Result<String>;
fn query_deriver(path: &str) -> Result<String>;
fn query_path_info(path: &str, base32: bool) -> Result<InternalPathInfo>;
fn query_raw_realisation(output_id: &str) -> Result<String>;
fn query_path_from_hash_part(hash_part: &str) -> Result<String>;
fn compute_fs_closure(
flip_direction: bool,
include_outputs: bool,
paths: Vec<&str>,
) -> Result<Vec<String>>;
fn topo_sort_paths(paths: Vec<&str>) -> Result<Vec<String>>;
fn follow_links_to_store_path(path: &str) -> Result<String>;
fn export_paths(fd: i32, paths: Vec<&str>) -> Result<()>;
fn import_paths(fd: i32, dont_check_signs: bool) -> Result<()>;
fn hash_path(algo: &str, base32: bool, path: &str) -> Result<String>;
fn hash_file(algo: &str, base32: bool, path: &str) -> Result<String>;
fn hash_string(algo: &str, base32: bool, s: &str) -> Result<String>;
fn convert_hash(algo: &str, s: &str, to_base_32: bool) -> Result<String>;
fn sign_string(secret_key: &str, msg: &str) -> Result<String>;
fn check_signature(public_key: &str, sig: &str, msg: &str) -> Result<bool>;
fn add_to_store(src_path: &str, recursive: i32, algo: &str) -> Result<String>;
fn make_fixed_output_path(
recursive: bool,
algo: &str,
hash: &str,
name: &str,
) -> Result<String>;
fn derivation_from_path(drv_path: &str) -> Result<InternalDrv>;
fn add_temp_root(store_path: &str) -> Result<()>;
fn get_bin_dir() -> String;
fn get_store_dir() -> String;
fn get_build_log(derivation_path: &str) -> Result<String>;
fn get_nar_list(store_path: &str) -> Result<String>;
fn dump_path(
store_part: &str,
callback: unsafe extern "C" fn(data: &[u8], user_data: usize) -> bool,
user_data: usize,
);
}
}
fn string_to_opt(v: String) -> Option<String> {
if v.is_empty() {
None
} else {
Some(v)
}
}
pub struct PathInfo {
pub drv: Option<String>,
pub narhash: String,
pub time: i64,
pub size: usize,
pub refs: Vec<String>,
pub sigs: Vec<String>,
pub ca: Option<String>,
}
pub struct Drv {
pub outputs: std::collections::HashMap<String, Option<String>>,
pub input_drvs: Vec<String>,
pub input_srcs: Vec<String>,
pub platform: String,
pub builder: String,
pub args: Vec<String>,
pub env: std::collections::HashMap<String, String>,
}
pub enum Radix {
Base16,
Base32,
}
impl Default for Radix {
fn default() -> Self {
Self::Base32
}
}
#[inline]
pub fn init() {
ffi::init();
}
#[inline]
pub fn set_verbosity(level: i32) {
ffi::set_verbosity(level);
}
#[inline]
#[must_use]
pub fn is_valid_path(path: &str) -> bool {
ffi::is_valid_path(path).unwrap_or(false)
}
#[inline]
pub fn query_references(path: &str) -> Result<Vec<String>, cxx::Exception> {
ffi::query_references(path)
}
#[inline]
pub fn query_path_hash(path: &str) -> Result<String, cxx::Exception> {
ffi::query_path_hash(path)
}
#[inline]
#[must_use]
pub fn query_deriver(path: &str) -> Option<String> {
match ffi::query_deriver(path) {
Ok(v) => string_to_opt(v),
Err(_) => None,
}
}
#[inline]
pub fn query_path_info(path: &str, radix: Radix) -> Result<PathInfo, cxx::Exception> {
let res = ffi::query_path_info(path, matches!(radix, Radix::Base32))?;
Ok(PathInfo {
drv: string_to_opt(res.drv),
narhash: res.narhash,
time: res.time,
size: res.size,
refs: res.refs,
sigs: res.sigs,
ca: string_to_opt(res.ca),
})
}
#[inline]
#[must_use]
pub fn query_raw_realisation(output_id: &str) -> Option<String> {
match ffi::query_raw_realisation(output_id) {
Ok(v) => string_to_opt(v),
Err(_) => None,
}
}
#[inline]
#[must_use]
pub fn query_path_from_hash_part(hash_part: &str) -> Option<String> {
match ffi::query_path_from_hash_part(hash_part) {
Ok(v) => string_to_opt(v),
Err(_) => None,
}
}
#[inline]
pub fn compute_fs_closure(
flip_direction: bool,
include_outputs: bool,
paths: Vec<&str>,
) -> Result<Vec<String>, cxx::Exception> {
ffi::compute_fs_closure(flip_direction, include_outputs, paths)
}
#[inline]
pub fn topo_sort_paths(paths: Vec<&str>) -> Result<Vec<String>, cxx::Exception> {
ffi::topo_sort_paths(paths)
}
#[inline]
pub fn follow_links_to_store_path(path: &str) -> Result<String, cxx::Exception> {
ffi::follow_links_to_store_path(path)
}
#[inline]
pub fn export_paths(fd: i32, paths: Vec<&str>) -> Result<(), cxx::Exception> {
ffi::export_paths(fd, paths)
}
#[inline]
pub fn import_paths(fd: i32, dont_check_signs: bool) -> Result<(), cxx::Exception> {
ffi::import_paths(fd, dont_check_signs)
}
#[inline]
pub fn hash_path(algo: &str, radix: Radix, path: &str) -> Result<String, cxx::Exception> {
ffi::hash_path(algo, matches!(radix, Radix::Base32), path)
}
#[inline]
pub fn hash_file(algo: &str, radix: Radix, path: &str) -> Result<String, cxx::Exception> {
ffi::hash_file(algo, matches!(radix, Radix::Base32), path)
}
#[inline]
pub fn hash_string(algo: &str, radix: Radix, s: &str) -> Result<String, cxx::Exception> {
ffi::hash_string(algo, matches!(radix, Radix::Base32), s)
}
#[inline]
pub fn convert_hash(algo: &str, s: &str, to_radix: Radix) -> Result<String, cxx::Exception> {
ffi::convert_hash(algo, s, matches!(to_radix, Radix::Base32))
}
#[inline]
pub fn sign_string(secret_key: &str, msg: &str) -> Result<String, cxx::Exception> {
ffi::sign_string(secret_key, msg)
}
#[inline]
pub fn check_signature(public_key: &str, sig: &str, msg: &str) -> Result<bool, cxx::Exception> {
ffi::check_signature(public_key, sig, msg)
}
#[inline]
pub fn add_to_store(src_path: &str, recursive: i32, algo: &str) -> Result<String, cxx::Exception> {
ffi::add_to_store(src_path, recursive, algo)
}
#[inline]
pub fn make_fixed_output_path(
recursive: bool,
algo: &str,
hash: &str,
name: &str,
) -> Result<String, cxx::Exception> {
ffi::make_fixed_output_path(recursive, algo, hash, name)
}
#[inline]
pub fn derivation_from_path(drv_path: &str) -> Result<Drv, cxx::Exception> {
let res = ffi::derivation_from_path(drv_path)?;
let mut outputs = std::collections::HashMap::new();
for out in res.outputs {
outputs.insert(out.lhs, string_to_opt(out.rhs));
}
let mut env = std::collections::HashMap::new();
for v in res.env {
env.insert(v.lhs, v.rhs);
}
Ok(Drv {
outputs,
input_drvs: res.input_drvs,
input_srcs: res.input_srcs,
platform: res.platform,
builder: res.builder,
args: res.args,
env,
})
}
#[inline]
pub fn add_temp_root(store_path: &str) -> Result<(), cxx::Exception> {
ffi::add_temp_root(store_path)
}
#[inline]
#[must_use]
pub fn get_bin_dir() -> String {
ffi::get_bin_dir()
}
#[inline]
#[must_use]
pub fn get_store_dir() -> String {
ffi::get_store_dir()
}
#[inline]
#[must_use]
pub fn get_build_log(derivation_path: &str) -> Option<String> {
match ffi::get_build_log(derivation_path) {
Ok(v) => string_to_opt(v),
Err(_) => None,
}
}
#[inline]
pub fn get_nar_list(store_path: &str) -> Result<String, cxx::Exception> {
ffi::get_nar_list(store_path)
}
fn dump_path_trampoline<F>(data: &[u8], userdata: usize) -> bool
where
F: FnMut(&[u8]) -> bool,
{
let closure = unsafe { &mut *(userdata as *mut std::ffi::c_void).cast::<F>() };
closure(data)
}
#[inline]
pub fn dump_path<F>(store_path: &str, callback: F)
where
F: FnMut(&[u8]) -> bool,
{
ffi::dump_path(
store_path,
dump_path_trampoline::<F>,
std::ptr::addr_of!(callback).cast::<std::ffi::c_void>() as usize,
);
}