blob: 894d4c6e6a9bb85f0113c5bcd28275ac03a45305 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Implements the interface required by `audio_streams` using the cros_async Executor.
//!
//! It implements the `AudioStreamsExecutor` trait for `Executor`, so it can be passed into
//! the audio_streams API.
use std::io::Result;
#[cfg(any(target_os = "android", target_os = "linux"))]
use std::os::unix::net::UnixStream;
#[cfg(windows)]
use std::os::windows::io::RawHandle;
use std::time::Duration;
use async_trait::async_trait;
#[cfg(any(target_os = "android", target_os = "linux"))]
use audio_streams::async_api::AsyncStream;
use audio_streams::async_api::AudioStreamsExecutor;
use audio_streams::async_api::EventAsyncWrapper;
use audio_streams::async_api::ReadAsync;
use audio_streams::async_api::ReadWriteAsync;
use audio_streams::async_api::WriteAsync;
#[cfg(any(target_os = "android", target_os = "linux"))]
use base::Descriptor;
#[cfg(windows)]
use base::Event;
#[cfg(windows)]
use base::FromRawDescriptor;
#[cfg(any(target_os = "android", target_os = "linux"))]
use base::RawDescriptor;
#[cfg(any(target_os = "android", target_os = "linux"))]
use super::AsyncWrapper;
use crate::EventAsync;
use crate::IntoAsync;
use crate::IoSource;
use crate::TimerAsync;
/// A wrapper around IoSource that is compatible with the audio_streams traits.
pub struct IoSourceWrapper<T: IntoAsync + Send> {
source: IoSource<T>,
}
#[async_trait(?Send)]
impl<T: IntoAsync + Send> ReadAsync for IoSourceWrapper<T> {
async fn read_to_vec<'a>(
&'a self,
file_offset: Option<u64>,
vec: Vec<u8>,
) -> Result<(usize, Vec<u8>)> {
self.source
.read_to_vec(file_offset, vec)
.await
.map_err(Into::into)
}
}
#[async_trait(?Send)]
impl<T: IntoAsync + Send> WriteAsync for IoSourceWrapper<T> {
async fn write_from_vec<'a>(
&'a self,
file_offset: Option<u64>,
vec: Vec<u8>,
) -> Result<(usize, Vec<u8>)> {
self.source
.write_from_vec(file_offset, vec)
.await
.map_err(Into::into)
}
}
#[async_trait(?Send)]
impl<T: IntoAsync + Send> ReadWriteAsync for IoSourceWrapper<T> {}
#[async_trait(?Send)]
impl EventAsyncWrapper for EventAsync {
async fn wait(&self) -> Result<u64> {
self.next_val().await.map_err(Into::into)
}
}
#[async_trait(?Send)]
impl AudioStreamsExecutor for super::Executor {
#[cfg(any(target_os = "android", target_os = "linux"))]
fn async_unix_stream(&self, stream: UnixStream) -> Result<AsyncStream> {
Ok(Box::new(IoSourceWrapper {
source: self.async_from(AsyncWrapper::new(stream))?,
}))
}
/// # Safety
/// This is only safe if `event` is a handle to a Windows Event.
#[cfg(windows)]
unsafe fn async_event(&self, event: RawHandle) -> Result<Box<dyn EventAsyncWrapper>> {
Ok(Box::new(
EventAsync::new(Event::from_raw_descriptor(event), self)
.map_err(std::io::Error::from)?,
))
}
async fn delay(&self, dur: Duration) -> Result<()> {
TimerAsync::sleep(self, dur).await.map_err(Into::into)
}
#[cfg(any(target_os = "android", target_os = "linux"))]
async fn wait_fd_readable(&self, fd: RawDescriptor) -> Result<()> {
self.async_from(AsyncWrapper::new(Descriptor(fd)))?
.wait_readable()
.await
.map_err(Into::into)
}
}