nautilus_core/ffi/
uuid.rs1use std::{
23 collections::hash_map::DefaultHasher,
24 ffi::{CStr, c_char},
25 hash::{Hash, Hasher},
26};
27
28use crate::{UUID4, ffi::abort_on_panic};
29
30#[unsafe(no_mangle)]
32pub extern "C" fn uuid4_new() -> UUID4 {
33 abort_on_panic(UUID4::new)
34}
35
36#[unsafe(no_mangle)]
46pub unsafe extern "C" fn uuid4_from_cstr(ptr: *const c_char) -> UUID4 {
47 abort_on_panic(|| {
48 assert!(!ptr.is_null(), "`ptr` was NULL");
49 let cstr = unsafe { CStr::from_ptr(ptr) };
51 let value = cstr.to_str().expect("Failed to convert C string to UTF-8");
52 UUID4::from(value)
53 })
54}
55
56#[unsafe(no_mangle)]
61pub extern "C" fn uuid4_to_cstr(uuid: &UUID4) -> *const c_char {
62 abort_on_panic(|| uuid.to_cstr().as_ptr())
63}
64
65#[unsafe(no_mangle)]
67pub extern "C" fn uuid4_eq(lhs: &UUID4, rhs: &UUID4) -> u8 {
68 abort_on_panic(|| u8::from(lhs == rhs))
69}
70
71#[unsafe(no_mangle)]
73pub extern "C" fn uuid4_hash(uuid: &UUID4) -> u64 {
74 abort_on_panic(|| {
75 let mut h = DefaultHasher::new();
76 uuid.hash(&mut h);
77 h.finish()
78 })
79}
80
81#[cfg(test)]
82mod tests {
83 use std::ffi::CString;
84
85 use rstest::*;
86 use uuid::{self, Uuid};
87
88 use super::*;
89
90 #[rstest]
91 fn test_new() {
92 let uuid = uuid4_new();
93 let uuid_string = uuid.to_string();
94 let uuid_parsed = Uuid::parse_str(&uuid_string).expect("Uuid::parse_str failed");
95 assert_eq!(uuid_parsed.get_version().unwrap(), uuid::Version::Random);
96 }
97
98 #[rstest]
99 fn test_from_cstr() {
100 let uuid_string = "2d89666b-1a1e-4a75-b193-4eb3b454c757";
101 let uuid_cstring = CString::new(uuid_string).expect("CString::new failed");
102 let uuid_ptr = uuid_cstring.as_ptr();
103 let uuid = unsafe { uuid4_from_cstr(uuid_ptr) };
104 assert_eq!(uuid_string, uuid.to_string());
105 }
106
107 #[rstest]
108 fn test_to_cstr() {
109 let uuid_string = "2d89666b-1a1e-4a75-b193-4eb3b454c757";
110 let uuid = UUID4::from(uuid_string);
111 let uuid_ptr = uuid4_to_cstr(&uuid);
112 let uuid_cstr = unsafe { CStr::from_ptr(uuid_ptr) };
113 let uuid_result_string = uuid_cstr.to_str().expect("CStr::to_str failed").to_string();
114 assert_eq!(uuid_string, uuid_result_string);
115 }
116
117 #[rstest]
118 fn test_eq() {
119 let uuid1 = UUID4::from("2d89666b-1a1e-4a75-b193-4eb3b454c757");
120 let uuid2 = UUID4::from("2d89666b-1a1e-4a75-b193-4eb3b454c757");
121 let uuid3 = UUID4::from("2d89666b-1a1e-4a75-b193-4eb3b454c758");
122 assert_eq!(uuid4_eq(&uuid1, &uuid2), 1);
123 assert_eq!(uuid4_eq(&uuid1, &uuid3), 0);
124 }
125
126 #[rstest]
127 fn test_hash() {
128 let uuid1 = UUID4::from("2d89666b-1a1e-4a75-b193-4eb3b454c757");
129 let uuid2 = UUID4::from("2d89666b-1a1e-4a75-b193-4eb3b454c757");
130 let uuid3 = UUID4::from("2d89666b-1a1e-4a75-b193-4eb3b454c758");
131 assert_eq!(uuid4_hash(&uuid1), uuid4_hash(&uuid2));
132 assert_ne!(uuid4_hash(&uuid1), uuid4_hash(&uuid3));
133 }
134}