blob: 9007d6d8dfb19f3eeeef4b6bbd5a3423036befd0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
use mullvad_types::device::Device;
use std::{ffi::CString, ptr};
#[repr(C)]
pub struct MullvadApiDeviceIterator {
ptr: *mut DeviceIterator,
}
impl MullvadApiDeviceIterator {
pub fn new(iter: impl IntoIterator<Item = Device> + 'static) -> Self {
let iter = Box::new(DeviceIterator::from(iter));
Self {
ptr: Box::into_raw(iter),
}
}
fn is_done(&self) -> bool {
self.ptr.is_null()
}
unsafe fn as_iter(&mut self) -> &mut Box<dyn Iterator<Item = Device>> {
let wrapper = unsafe { &mut *self.ptr };
&mut wrapper.iter
}
fn drop(mut self) {
if self.ptr.is_null() {
return;
}
let _ = unsafe { Box::from_raw(self.ptr) };
self.ptr = ptr::null_mut();
}
}
#[repr(C)]
pub struct MullvadApiDevice {
name_ptr: *const libc::c_char,
id: [u8; 16],
}
impl From<Device> for MullvadApiDevice {
fn from(dev: Device) -> Self {
let name = CString::new(dev.name).expect("Null bytes in name from API response");
let name_ptr = name.into_raw();
let id = *uuid::Uuid::parse_str(&dev.id)
.expect("Failed to parse UUID")
.as_bytes();
Self { name_ptr, id }
}
}
impl MullvadApiDevice {
fn drop(self) {
let _ = unsafe { CString::from_raw(self.name_ptr as *mut _) };
}
}
struct DeviceIterator {
iter: Box<dyn Iterator<Item = Device>>,
}
impl<T> From<T> for DeviceIterator
where
T: IntoIterator<Item = Device> + 'static,
{
fn from(i: T) -> Self {
let iter: Box<dyn Iterator<Item = Device>> = Box::new(i.into_iter());
Self { iter }
}
}
#[unsafe(no_mangle)]
pub extern "C" fn mullvad_api_device_iter_next(
mut iter: MullvadApiDeviceIterator,
device_ptr: *mut MullvadApiDevice,
) -> bool {
if iter.is_done() {
return false;
}
// SAFETY: Asuming self.ptr is still valid since iter.is_done() returned false;
let iter = unsafe { iter.as_iter() };
let Some(device) = iter.next() else {
return false;
};
// SAFETY: Assuming device pointer is valid
unsafe { ptr::write(device_ptr, device.into()) }
true
}
#[unsafe(no_mangle)]
pub extern "C" fn mullvad_api_device_iter_drop(iter: MullvadApiDeviceIterator) {
iter.drop()
}
#[unsafe(no_mangle)]
pub extern "C" fn mullvad_api_device_drop(device: MullvadApiDevice) {
device.drop()
}
|