1use std::ffi::CStr;
2use std::os::raw::c_char;
3use std::{mem, ptr, slice, str};
4
5use uuid::Uuid;
6
7#[repr(C)]
15pub struct RelayStr {
16 pub data: *mut c_char,
18 pub len: usize,
20 pub owned: bool,
22}
23
24impl RelayStr {
25 pub(crate) fn new(s: &str) -> RelayStr {
27 RelayStr {
28 data: s.as_ptr() as *mut c_char,
29 len: s.len(),
30 owned: false,
31 }
32 }
33
34 pub(crate) fn from_string(mut s: String) -> RelayStr {
38 s.shrink_to_fit();
39 let rv = RelayStr {
40 data: s.as_ptr() as *mut c_char,
41 len: s.len(),
42 owned: true,
43 };
44 mem::forget(s);
45 rv
46 }
47
48 pub(crate) unsafe fn free(&mut self) {
50 if self.owned {
51 String::from_raw_parts(self.data as *mut _, self.len, self.len);
52 self.data = ptr::null_mut();
53 self.len = 0;
54 self.owned = false;
55 }
56 }
57
58 pub(crate) unsafe fn as_str(&self) -> &str {
60 str::from_utf8_unchecked(slice::from_raw_parts(self.data as *const _, self.len))
61 }
62}
63
64unsafe impl Sync for RelayStr {}
66unsafe impl Send for RelayStr {}
67
68impl Default for RelayStr {
69 fn default() -> RelayStr {
70 RelayStr {
71 data: ptr::null_mut(),
72 len: 0,
73 owned: false,
74 }
75 }
76}
77
78impl From<String> for RelayStr {
79 fn from(string: String) -> RelayStr {
80 RelayStr::from_string(string)
81 }
82}
83
84impl From<&str> for RelayStr {
85 fn from(string: &str) -> RelayStr {
86 RelayStr::new(string)
87 }
88}
89
90#[no_mangle]
92#[relay_ffi::catch_unwind]
93pub unsafe extern "C" fn relay_str_from_cstr(s: *const c_char) -> RelayStr {
94 let s = CStr::from_ptr(s).to_str()?;
95 RelayStr {
96 data: s.as_ptr() as *mut _,
97 len: s.len(),
98 owned: false,
99 }
100}
101
102#[no_mangle]
107#[relay_ffi::catch_unwind]
108pub unsafe extern "C" fn relay_str_free(s: *mut RelayStr) {
109 if !s.is_null() {
110 (*s).free()
111 }
112}
113
114#[repr(C)]
116pub struct RelayUuid {
117 pub data: [u8; 16],
119}
120
121impl RelayUuid {
122 pub(crate) fn new(uuid: Uuid) -> RelayUuid {
123 let data = *uuid.as_bytes();
124 Self { data }
125 }
126}
127
128impl From<Uuid> for RelayUuid {
129 fn from(uuid: Uuid) -> RelayUuid {
130 RelayUuid::new(uuid)
131 }
132}
133
134#[no_mangle]
136#[relay_ffi::catch_unwind]
137pub unsafe extern "C" fn relay_uuid_is_nil(uuid: *const RelayUuid) -> bool {
138 if let Ok(uuid) = Uuid::from_slice(&(*uuid).data[..]) {
139 uuid == Uuid::nil()
140 } else {
141 false
142 }
143}
144
145#[no_mangle]
150#[relay_ffi::catch_unwind]
151pub unsafe extern "C" fn relay_uuid_to_str(uuid: *const RelayUuid) -> RelayStr {
152 let uuid = Uuid::from_slice(&(*uuid).data[..]).unwrap_or_else(|_| Uuid::nil());
153 RelayStr::from_string(uuid.as_hyphenated().to_string())
154}
155
156#[repr(C)]
164pub struct RelayBuf {
165 pub data: *mut u8,
167 pub len: usize,
169 pub owned: bool,
171}
172
173impl RelayBuf {
174 pub(crate) unsafe fn free(&mut self) {
175 if self.owned {
176 Vec::from_raw_parts(self.data, self.len, self.len);
177 self.data = ptr::null_mut();
178 self.len = 0;
179 self.owned = false;
180 }
181 }
182
183 pub(crate) unsafe fn as_bytes(&self) -> &[u8] {
184 slice::from_raw_parts(self.data as *const u8, self.len)
185 }
186}
187
188impl Default for RelayBuf {
189 fn default() -> RelayBuf {
190 RelayBuf {
191 data: ptr::null_mut(),
192 len: 0,
193 owned: false,
194 }
195 }
196}
197
198#[no_mangle]
203#[relay_ffi::catch_unwind]
204pub unsafe extern "C" fn relay_buf_free(b: *mut RelayBuf) {
205 if !b.is_null() {
206 (*b).free()
207 }
208}