Skip to content

Commit 5e866af

Browse files
committed
Add MaybeFuture::map
1 parent 8dfb3e5 commit 5e866af

File tree

5 files changed

+130
-71
lines changed

5 files changed

+130
-71
lines changed

src/device.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,24 @@ impl Device {
4646
pub(crate) fn open(
4747
d: &DeviceInfo,
4848
) -> impl MaybeFuture<Output = Result<Device, std::io::Error>> {
49-
platform::Device::from_device_info(d)
49+
platform::Device::from_device_info(d).map(|d| d.map(Device::wrap))
5050
}
5151

5252
/// Wraps a device that is already open.
5353
#[cfg(any(target_os = "android", target_os = "linux"))]
5454
pub fn from_fd(fd: std::os::fd::OwnedFd) -> impl MaybeFuture<Output = Result<Device, Error>> {
55-
platform::Device::from_fd(fd)
55+
platform::Device::from_fd(fd).map(|d| d.map(Device::wrap))
5656
}
5757

5858
/// Open an interface of the device and claim it for exclusive use.
5959
pub fn claim_interface(
6060
&self,
6161
interface: u8,
6262
) -> impl MaybeFuture<Output = Result<Interface, Error>> {
63-
self.backend.clone().claim_interface(interface)
63+
self.backend
64+
.clone()
65+
.claim_interface(interface)
66+
.map(|i| i.map(Interface::wrap))
6467
}
6568

6669
/// Detach kernel drivers and open an interface of the device and claim it for exclusive use.
@@ -72,7 +75,10 @@ impl Device {
7275
&self,
7376
interface: u8,
7477
) -> impl MaybeFuture<Output = Result<Interface, Error>> {
75-
self.backend.clone().detach_and_claim_interface(interface)
78+
self.backend
79+
.clone()
80+
.detach_and_claim_interface(interface)
81+
.map(|i| i.map(Interface::wrap))
7682
}
7783

7884
/// Detach kernel drivers for the specified interface.

src/maybe_future.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use std::future::IntoFuture;
1+
use std::{
2+
future::{Future, IntoFuture},
3+
pin::Pin,
4+
task::{Context, Poll},
5+
};
26

37
/// IO that may be performed synchronously or asynchronously.
48
///
@@ -8,6 +12,17 @@ pub trait MaybeFuture: IntoFuture {
812
/// Block waiting for the action to complete
913
#[cfg(not(target_arch = "wasm32"))]
1014
fn wait(self) -> Self::Output;
15+
16+
/// Apply a function to the output.
17+
fn map<T: FnOnce(Self::Output) -> R + Unpin, R>(self, f: T) -> Map<Self, T>
18+
where
19+
Self: Sized,
20+
{
21+
Map {
22+
wrapped: self,
23+
func: f,
24+
}
25+
}
1126
}
1227

1328
#[cfg(any(
@@ -73,3 +88,47 @@ impl<T> MaybeFuture for Ready<T> {
7388
self.0
7489
}
7590
}
91+
92+
pub struct Map<F, T> {
93+
wrapped: F,
94+
func: T,
95+
}
96+
97+
impl<F: MaybeFuture, T: FnOnce(F::Output) -> R, R> IntoFuture for Map<F, T> {
98+
type Output = R;
99+
type IntoFuture = MapFut<F::IntoFuture, T>;
100+
101+
fn into_future(self) -> Self::IntoFuture {
102+
MapFut {
103+
wrapped: self.wrapped.into_future(),
104+
func: Some(self.func),
105+
}
106+
}
107+
}
108+
109+
impl<F: MaybeFuture, T: FnOnce(F::Output) -> R, R> MaybeFuture for Map<F, T> {
110+
fn wait(self) -> Self::Output {
111+
(self.func)(self.wrapped.wait())
112+
}
113+
}
114+
115+
pub struct MapFut<F, T> {
116+
wrapped: F,
117+
func: Option<T>,
118+
}
119+
120+
impl<F: Future, T: FnOnce(F::Output) -> R, R> Future for MapFut<F, T> {
121+
type Output = R;
122+
123+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
124+
// SAFETY: structural pin projection: `self.wrapped` is always pinned.
125+
let wrapped = unsafe { self.as_mut().map_unchecked_mut(|s| &mut s.wrapped) };
126+
127+
Future::poll(wrapped, cx).map(|output| {
128+
// SAFETY: `self.func` is never pinned.
129+
let func = unsafe { &mut self.as_mut().get_unchecked_mut().func };
130+
131+
(func.take().expect("polled after completion"))(output)
132+
})
133+
}
134+
}

src/platform/linux_usbfs/device.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub(crate) struct LinuxDevice {
5454
impl LinuxDevice {
5555
pub(crate) fn from_device_info(
5656
d: &DeviceInfo,
57-
) -> impl MaybeFuture<Output = Result<crate::Device, Error>> {
57+
) -> impl MaybeFuture<Output = Result<Arc<LinuxDevice>, Error>> {
5858
let busnum = d.busnum();
5959
let devnum = d.device_address();
6060
let sysfs_path = d.path.clone();
@@ -68,7 +68,9 @@ impl LinuxDevice {
6868
})
6969
}
7070

71-
pub(crate) fn from_fd(fd: OwnedFd) -> impl MaybeFuture<Output = Result<crate::Device, Error>> {
71+
pub(crate) fn from_fd(
72+
fd: OwnedFd,
73+
) -> impl MaybeFuture<Output = Result<Arc<LinuxDevice>, Error>> {
7274
Blocking::new(move || {
7375
debug!("Wrapping fd {} as usbfs device", fd.as_raw_fd());
7476
Self::create_inner(fd, None, None)
@@ -79,7 +81,7 @@ impl LinuxDevice {
7981
fd: OwnedFd,
8082
sysfs: Option<SysfsPath>,
8183
active_config: Option<u8>,
82-
) -> Result<crate::Device, Error> {
84+
) -> Result<Arc<LinuxDevice>, Error> {
8385
let descriptors = {
8486
let mut file = unsafe { ManuallyDrop::new(File::from_raw_fd(fd.as_raw_fd())) };
8587
// NOTE: Seek required on android
@@ -125,7 +127,7 @@ impl LinuxDevice {
125127
epoll::EventFlags::OUT,
126128
)?;
127129

128-
Ok(crate::Device::wrap(arc))
130+
Ok(arc)
129131
}
130132

131133
pub(crate) fn handle_usb_epoll(id: usize) {
@@ -284,7 +286,7 @@ impl LinuxDevice {
284286
pub(crate) fn claim_interface(
285287
self: Arc<Self>,
286288
interface_number: u8,
287-
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
289+
) -> impl MaybeFuture<Output = Result<Arc<LinuxInterface>, Error>> {
288290
Blocking::new(move || {
289291
usbfs::claim_interface(&self.fd, interface_number).inspect_err(|e| {
290292
warn!(
@@ -296,31 +298,31 @@ impl LinuxDevice {
296298
"Claimed interface {interface_number} on device id {dev}",
297299
dev = self.events_id
298300
);
299-
Ok(crate::Interface::wrap(Arc::new(LinuxInterface {
301+
Ok(Arc::new(LinuxInterface {
300302
device: self,
301303
interface_number,
302304
reattach: false,
303305
state: Mutex::new(Default::default()),
304-
})))
306+
}))
305307
})
306308
}
307309

308310
pub(crate) fn detach_and_claim_interface(
309311
self: Arc<Self>,
310312
interface_number: u8,
311-
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
313+
) -> impl MaybeFuture<Output = Result<Arc<LinuxInterface>, Error>> {
312314
Blocking::new(move || {
313315
usbfs::detach_and_claim_interface(&self.fd, interface_number)?;
314316
debug!(
315317
"Detached and claimed interface {interface_number} on device id {dev}",
316318
dev = self.events_id
317319
);
318-
Ok(crate::Interface::wrap(Arc::new(LinuxInterface {
320+
Ok(Arc::new(LinuxInterface {
319321
device: self,
320322
interface_number,
321323
reattach: true,
322324
state: Mutex::new(Default::default()),
323-
})))
325+
}))
324326
})
325327
}
326328

src/platform/macos_iokit/device.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn guess_active_config(dev: &IoKitDevice) -> Option<u8> {
5353
impl MacDevice {
5454
pub(crate) fn from_device_info(
5555
d: &DeviceInfo,
56-
) -> impl MaybeFuture<Output = Result<crate::Device, Error>> {
56+
) -> impl MaybeFuture<Output = Result<Arc<MacDevice>, Error>> {
5757
let registry_id = d.registry_id;
5858
let speed = d.speed;
5959
Blocking::new(move || {
@@ -88,15 +88,15 @@ impl MacDevice {
8888
res.unwrap_or(0)
8989
};
9090

91-
Ok(crate::Device::wrap(Arc::new(MacDevice {
91+
Ok(Arc::new(MacDevice {
9292
_event_registration,
9393
device,
9494
device_descriptor,
9595
speed,
9696
active_config: AtomicU8::new(active_config),
9797
is_open_exclusive: Mutex::new(opened),
9898
claimed_interfaces: AtomicUsize::new(0),
99-
})))
99+
}))
100100
})
101101
}
102102

@@ -236,7 +236,7 @@ impl MacDevice {
236236
pub(crate) fn claim_interface(
237237
self: Arc<Self>,
238238
interface_number: u8,
239-
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
239+
) -> impl MaybeFuture<Output = Result<Arc<MacInterface>, Error>> {
240240
Blocking::new(move || {
241241
let intf_service = self
242242
.device
@@ -254,21 +254,21 @@ impl MacDevice {
254254

255255
self.claimed_interfaces.fetch_add(1, Ordering::Acquire);
256256

257-
Ok(crate::Interface::wrap(Arc::new(MacInterface {
257+
Ok(Arc::new(MacInterface {
258258
device: self.clone(),
259259
interface_number,
260260
interface,
261261
endpoints: Mutex::new(endpoints),
262262
state: Mutex::new(InterfaceState::default()),
263263
_event_registration,
264-
})))
264+
}))
265265
})
266266
}
267267

268268
pub(crate) fn detach_and_claim_interface(
269269
self: Arc<Self>,
270270
interface: u8,
271-
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
271+
) -> impl MaybeFuture<Output = Result<Arc<MacInterface>, Error>> {
272272
self.claim_interface(interface)
273273
}
274274
}

src/platform/windows_winusb/device.rs

Lines changed: 41 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub(crate) struct WindowsDevice {
5353
impl WindowsDevice {
5454
pub(crate) fn from_device_info(
5555
d: &DeviceInfo,
56-
) -> impl MaybeFuture<Output = Result<crate::Device, Error>> {
56+
) -> impl MaybeFuture<Output = Result<Arc<WindowsDevice>, Error>> {
5757
let instance_id = d.instance_id.clone();
5858
let devinst = d.devinst;
5959
Blocking::new(move || {
@@ -85,14 +85,14 @@ impl WindowsDevice {
8585
})
8686
.collect();
8787

88-
Ok(crate::Device::wrap(Arc::new(WindowsDevice {
88+
Ok(Arc::new(WindowsDevice {
8989
device_descriptor,
9090
config_descriptors,
9191
speed: connection_info.speed,
9292
active_config: connection_info.active_config,
9393
devinst: devinst,
9494
handles: Mutex::new(BTreeMap::new()),
95-
})))
95+
}))
9696
})
9797
}
9898

@@ -145,63 +145,55 @@ impl WindowsDevice {
145145
pub(crate) fn claim_interface(
146146
self: Arc<Self>,
147147
interface_number: u8,
148-
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
148+
) -> impl MaybeFuture<Output = Result<Arc<WindowsInterface>, Error>> {
149149
Blocking::new(move || {
150-
self.claim_interface_blocking(interface_number)
151-
.map(crate::Interface::wrap)
152-
})
153-
}
154-
155-
fn claim_interface_blocking(
156-
self: &Arc<Self>,
157-
interface_number: u8,
158-
) -> Result<Arc<WindowsInterface>, Error> {
159-
let driver = get_driver_name(self.devinst);
160-
161-
let mut handles = self.handles.lock().unwrap();
162-
163-
if driver.eq_ignore_ascii_case("winusb") {
164-
match handles.entry(0) {
165-
Entry::Occupied(mut e) => e.get_mut().claim_interface(self, interface_number),
166-
Entry::Vacant(e) => {
167-
let path = get_winusb_device_path(self.devinst)?;
168-
let mut handle = WinusbFileHandle::new(&path, 0)?;
169-
let intf = handle.claim_interface(self, interface_number)?;
170-
e.insert(handle);
171-
Ok(intf)
150+
let driver = get_driver_name(self.devinst);
151+
152+
let mut handles = self.handles.lock().unwrap();
153+
154+
if driver.eq_ignore_ascii_case("winusb") {
155+
match handles.entry(0) {
156+
Entry::Occupied(mut e) => e.get_mut().claim_interface(&self, interface_number),
157+
Entry::Vacant(e) => {
158+
let path = get_winusb_device_path(self.devinst)?;
159+
let mut handle = WinusbFileHandle::new(&path, 0)?;
160+
let intf = handle.claim_interface(&self, interface_number)?;
161+
e.insert(handle);
162+
Ok(intf)
163+
}
172164
}
173-
}
174-
} else if driver.eq_ignore_ascii_case("usbccgp") {
175-
let (first_interface, child_dev) =
176-
find_usbccgp_child(self.devinst, interface_number)
177-
.ok_or_else(|| Error::new(ErrorKind::NotFound, "Interface not found"))?;
165+
} else if driver.eq_ignore_ascii_case("usbccgp") {
166+
let (first_interface, child_dev) =
167+
find_usbccgp_child(self.devinst, interface_number)
168+
.ok_or_else(|| Error::new(ErrorKind::NotFound, "Interface not found"))?;
178169

179-
if first_interface != interface_number {
180-
debug!("Guessing that interface {interface_number} is an associated interface of {first_interface}");
181-
}
170+
if first_interface != interface_number {
171+
debug!("Guessing that interface {interface_number} is an associated interface of {first_interface}");
172+
}
182173

183-
match handles.entry(first_interface) {
184-
Entry::Occupied(mut e) => e.get_mut().claim_interface(self, interface_number),
185-
Entry::Vacant(e) => {
186-
let path = get_usbccgp_winusb_device_path(child_dev)?;
187-
let mut handle = WinusbFileHandle::new(&path, first_interface)?;
188-
let intf = handle.claim_interface(self, interface_number)?;
189-
e.insert(handle);
190-
Ok(intf)
174+
match handles.entry(first_interface) {
175+
Entry::Occupied(mut e) => e.get_mut().claim_interface(&self, interface_number),
176+
Entry::Vacant(e) => {
177+
let path = get_usbccgp_winusb_device_path(child_dev)?;
178+
let mut handle = WinusbFileHandle::new(&path, first_interface)?;
179+
let intf = handle.claim_interface(&self, interface_number)?;
180+
e.insert(handle);
181+
Ok(intf)
182+
}
191183
}
184+
} else {
185+
Err(Error::new(
186+
ErrorKind::Unsupported,
187+
format!("Device driver is {driver:?}, not WinUSB or USBCCGP"),
188+
))
192189
}
193-
} else {
194-
Err(Error::new(
195-
ErrorKind::Unsupported,
196-
format!("Device driver is {driver:?}, not WinUSB or USBCCGP"),
197-
))
198-
}
190+
})
199191
}
200192

201193
pub(crate) fn detach_and_claim_interface(
202194
self: Arc<Self>,
203195
interface: u8,
204-
) -> impl MaybeFuture<Output = Result<crate::Interface, Error>> {
196+
) -> impl MaybeFuture<Output = Result<Arc<WindowsInterface>, Error>> {
205197
self.claim_interface(interface)
206198
}
207199
}

0 commit comments

Comments
 (0)