nyquest-backend-winrt 0.4.0

Windows.Web.Http.HttpClient backend for nyquest
Documentation
use std::io;

use windows::core::HSTRING;
#[cfg(any(feature = "async-stream", feature = "blocking-stream"))]
use windows::Storage::Streams::{DataReader, InputStreamOptions};
use windows::Web::Http::{HttpResponseMessage, IHttpContent};

use crate::timer::Timer;

pub struct WinrtResponse {
    pub(crate) status: u16,
    pub(crate) content_length: Option<u64>,
    pub(crate) max_response_buffer_size: Option<u64>,
    pub(crate) request_timer: Timer,
    pub(crate) response: HttpResponseMessage,
    #[cfg(any(feature = "async-stream", feature = "blocking-stream"))]
    pub(crate) reader: Option<DataReader>,
}

impl WinrtResponse {
    pub(crate) fn new(
        res: HttpResponseMessage,
        response_size_limit: Option<u64>,
        request_timer: Timer,
    ) -> io::Result<WinrtResponse> {
        let content_length = match res.Content() {
            Ok(content) => content
                .Headers()?
                .ContentLength()
                .ok()
                .and_then(|v| v.Value().ok()),
            Err(_) => Some(0),
        };
        Ok(WinrtResponse {
            status: res.StatusCode()?.0 as u16,
            content_length,
            max_response_buffer_size: response_size_limit,
            request_timer,
            response: res,
            #[cfg(any(feature = "async-stream", feature = "blocking-stream"))]
            reader: None,
        })
    }

    pub(crate) fn get_header(&self, header: &str) -> io::Result<Vec<String>> {
        let headers = self.response.Headers()?;
        let header_name = HSTRING::from(header);
        let mut headers = headers.Lookup(&header_name).ok();
        if headers.is_none() {
            headers = self.content()?.Headers()?.Lookup(&header_name).ok();
        }
        Ok(headers.into_iter().map(|h| h.to_string_lossy()).collect())
    }

    pub(crate) fn content(&self) -> io::Result<IHttpContent> {
        Ok(self.response.Content()?)
    }

    #[cfg(any(feature = "async-stream", feature = "blocking-stream"))]
    pub(crate) fn reader_mut(&mut self) -> io::Result<&mut DataReader> {
        if self.reader.is_none() {
            let content = self.content()?;
            let content = content.ReadAsInputStreamAsync()?.get()?;
            let reader = DataReader::CreateDataReader(&content)?;
            reader.SetInputStreamOptions(InputStreamOptions::Partial)?;
            self.reader = Some(reader);
        }
        Ok(self.reader.as_mut().expect("DataReader is None"))
    }
}