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
105
106
107
108
109
110
111
112
113
// 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)
    }
}