Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there support for the std::io::Read trait somehow? #1952

Open
davidanthoff opened this issue Aug 6, 2022 · 4 comments
Open

Is there support for the std::io::Read trait somehow? #1952

davidanthoff opened this issue Aug 6, 2022 · 4 comments
Labels
enhancement New feature or request

Comments

@davidanthoff
Copy link

I'm trying to use windows::Web::Http::HttpClient to download a file. I'm using HttpClient::GetInputStreamAsync to get an IInputStream and would like to somehow pass that to a function that expects something that implements the std::io::Read trait. Is that somehow possible? Or am I entirely on the wrong track here? It seems to me that somehow on some very general level I'm getting a stream from the Windows API here, and it would be nice if that composed nicely with the standard trait for reading from streams in Rust :)

@tim-weis
Copy link
Contributor

tim-weis commented Aug 6, 2022

That would actually require a trait with an async fn, which—to my knowledge—is not supported (IInputStream only exposes a ReadAsync method).

@Nerixyz
Copy link
Contributor

Nerixyz commented Aug 6, 2022

I'm not sure if we really need async in this case, since IAsyncOperation has a sync get method. I think the actual problem when implementing io::Read for IInputStream is the fact that you can't create a buffer(-view), that ReadAsync could read into.

However, there is an argument to be made that io::Read should be implemented for DataReader (and similarly io::Write for DataWriter - or the respective interface).

Proof of concept implementation
// for demonstration
#![feature(io_read_to_string)]

use std::io;
use windows::{
    core::Result,
    w,
    Foundation::Uri,
    Storage::Streams::{DataReader, IInputStream, InputStreamOptions},
    Web::Http::{HttpClient, IHttpContent},
};

struct DataReaderWrap(DataReader);

impl io::Read for DataReaderWrap {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut bytes =
            self.0
                .LoadAsync(buf.len() as u32)
                .map_err(|e| io::Error::from_raw_os_error(e.code().0))?
                .get()
                .map_err(|e| io::Error::from_raw_os_error(e.code().0))? as usize;
        bytes = bytes.min(buf.len());
        self.0
            .ReadBytes(&mut buf[0..bytes])
            .map_err(|e| io::Error::from_raw_os_error(e.code().0))
            .map(|_| bytes)
    }
}

fn main() -> Result<()> {
    let uri = Uri::CreateUri(w!("https://www.rust-lang.org/"))?;
    let http: HttpClient = HttpClient::new()?;
    let content: IHttpContent = http.GetAsync(&uri)?.get()?.Content()?;
    let is: IInputStream = content.ReadAsInputStreamAsync()?.get()?;
    let reader = DataReader::CreateDataReader(&is)?;
    // not needed but this might improve performance
    reader.SetInputStreamOptions(InputStreamOptions::ReadAhead)?;
    println!("{:?}", io::read_to_string(DataReaderWrap(reader)));
    Ok(())
}

@davidanthoff
Copy link
Author

@Nerixyz Fantastic, that piece of code solved my problem completely, thanks so much! And agreed, it would be nice if that was included by default in the crate.

@kennykerr kennykerr added question Further information is requested enhancement New feature or request and removed question Further information is requested labels Aug 22, 2022
@kennykerr
Copy link
Collaborator

Neat, thanks for the example @Nerixyz! I'll think about whether this trait can offered automatically.

@kennykerr kennykerr changed the title Is there support for the std::io::Read trait somehow? Is there support for the std::io::Read trait somehow? Sep 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants