libnixstore_sys/
lib.rs

1use std::ffi::{CString, CStr};
2
3#[derive(Debug)]
4pub enum Error {
5//    StringConversionFailed,
6    FfiNullPtr(std::ffi::NulError),
7    NullPtr,
8}
9
10impl From<std::ffi::NulError> for Error {
11    fn from(other: std::ffi::NulError) -> Error {
12        return Error::FfiNullPtr(other);
13    }
14}
15
16type Result<T> = std::result::Result<T, Error>;
17
18mod ffi {
19    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
20}
21
22#[derive(Debug)]
23pub struct PathInfo {
24    pub path: String,
25    pub deriver: String,
26    pub nar_hash: String,
27    pub references: String,
28    pub registration_time: i64,
29    pub nar_size: u64,
30    pub ultimate: bool,
31    pub signatures: String,
32    pub ca: String,
33}
34
35impl PathInfo {
36    fn from_cpathinfo(cpi: &ffi::CPathInfo) -> Self {
37        Self {
38            path: unsafe { CStr::from_ptr(cpi.path).to_string_lossy().to_string() },
39            deriver: unsafe { CStr::from_ptr(cpi.deriver).to_string_lossy().to_string() },
40            nar_hash: unsafe { CStr::from_ptr(cpi.narHash).to_string_lossy().to_string() },
41            references: unsafe { CStr::from_ptr(cpi.references).to_string_lossy().to_string() },
42            registration_time: cpi.registrationTime as i64,
43            nar_size: cpi.narSize,
44            ultimate: cpi.ultimate != 0,
45            signatures: unsafe { CStr::from_ptr(cpi.signatures).to_string_lossy().to_string() },
46            ca: unsafe { CStr::from_ptr(cpi.ca).to_string_lossy().to_string() },
47        }
48    }
49}
50
51#[derive(Debug)]
52pub struct Instance {
53    instp: *mut ffi::nixstorec_instance,
54}
55
56unsafe impl Send for Instance {}
57impl Drop for Instance {
58    fn drop(&mut self) {
59        unsafe { ffi::nixstorec_free_instance(self.instp) };
60    }
61}
62
63impl Instance {
64    pub fn new() -> Result<Instance> {
65        let instp = unsafe {
66            ffi::nixstorec_new_instance()
67        };
68
69        if instp == 0 as _ {
70            return Err(Error::NullPtr);
71        }
72
73        Ok(Self{
74            instp
75        })
76    }
77
78    pub fn is_valid_path<T: AsRef<str>>(&mut self, path: T) -> Result<bool> {
79        let path = std::ffi::CString::new(path.as_ref())?;
80
81        let c_path = path.as_ptr();
82
83        unsafe {
84            let ret : bool = ffi::nixstorec_is_valid_path(self.instp, c_path) != 0;
85            return Ok(ret);
86        }
87    }
88
89    pub fn query_path_info<T: AsRef<str>>(&mut self, path: T) -> Result<Option<PathInfo>> {
90        let path : CString = std::ffi::CString::new(path.as_ref())?;
91        let c_path = path.as_ptr();
92
93        let c_pathinfo_ptr = unsafe {
94            ffi::nixstorec_query_path_info(self.instp, c_path)
95        };
96
97        if c_pathinfo_ptr == 0 as _ {
98            return Ok(None);
99        }
100
101        let pathinfo = {
102            let c_pathinfo = unsafe { *c_pathinfo_ptr };
103            PathInfo::from_cpathinfo(&c_pathinfo)
104        };
105
106        unsafe { ffi::nixstorec_free_path_info(c_pathinfo_ptr); }
107
108        return Ok(Some(pathinfo));
109    }
110
111    pub fn query_path_from_hash_part<T: AsRef<str>>(&mut self, hash_part: T) -> Result<Option<String>> {
112
113        let hash_path_c = CString::new(hash_part.as_ref())?;
114
115        let path_c = unsafe { ffi::nixstorec_query_path_from_hash_part(self.instp, hash_path_c.as_ptr()) };
116
117        if path_c == 0 as _ {
118            return Err(Error::NullPtr);
119        }
120
121        let path = unsafe {
122            CStr::from_ptr(path_c).to_string_lossy().to_string()
123        };
124
125        unsafe { ffi::nixstorec_free(path_c as _); }
126
127        if path.is_empty() {
128            Ok(None)
129        } else {
130            Ok(Some(path))
131        }
132    }
133
134    pub fn query_path_from_file_hash<T: AsRef<str>>(&mut self, file_hash: T) -> Result<Option<String>> {
135
136        let file_hash_c = CString::new(file_hash.as_ref())?;
137
138        let path_c = unsafe { ffi::nixstorec_query_path_from_file_hash(self.instp, file_hash_c.as_ptr()) };
139
140        if path_c == 0 as _ {
141            return Err(Error::NullPtr);
142        }
143
144        let path = unsafe {
145            CStr::from_ptr(path_c).to_string_lossy().to_string()
146        };
147
148        let ptr = path_c as _;
149
150        unsafe {
151            ffi::nixstorec_free(ptr);
152        }
153
154        if path.is_empty() {
155            Ok(None)
156        } else {
157            Ok(Some(path))
158        }
159    }
160}
161
162
163
164#[cfg(test)]
165mod tests {
166    #[test]
167//     fn query_path_from_nar_hash() {
168//         let v = super::query_path_from_nar_hash("fooooo");
169//         println!("{:?}", v);
170//         assert!(v.is_ok());
171//     }
172//
173//     #[test]
174//     fn query_path_from_hash_part() {
175//         let v = super::query_path_from_hash_part("foooooooooo");
176//         println!("{:?}", v);
177//         assert!(v.is_ok());
178//     }
179
180    #[test]
181    fn query_path_info() {
182        for i in 0..100 {
183            let mut instance = super::Instance::new().unwrap();
184            let v = instance.query_path_info("testtesttest");
185            println!("{:?}", v);
186            assert!(v.unwrap().is_none())
187        }
188    }
189}