Прочтите ответ gzip с помощью Hyper и Flate2

Hyper имеет функцию fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> для чтения содержимого ответа HTTP в предоставленный &mut [u8].

Flate2 может распаковать:

let mut d = GzDecoder::new("...".as_bytes()).unwrap();
let mut s = String::new();
d.read_to_string(&mut s).unwrap();
println!("{}", s);

Я пытаюсь соединить две вещи:

fn gunzip(r: &Response) -> String {
    let mut zs: &mut [u8] = &mut[];
    r.read(zs);
    let mut d = GzDecoder::new(zs).unwrap();
    let mut s = String::new();
    d.read_to_string(&mut s).unwrap();
    s
}

И я получаю ошибку:

error[E0277]: the trait bound `[u8]: std::io::Read` is not satisfied
   --> tests/integration.rs:232:21
    |
232 |         let mut d = GzDecoder::new(zs).unwrap();
    |                     ^^^^^^^^^^^^^^ trait `[u8]: std::io::Read` not satisfied
    |
    = help: the following implementations were found:
    = help:   <&'a [u8] as std::io::Read>
    = note: required because of the requirements on the impl of `std::io::Read` for `&mut [u8]`
    = note: required by `<flate2::read::DecoderReader<R>>::new`

Где я ошибаюсь?


Изменить: окончательное рабочее решение:

fn gunzip(r: &mut Response) -> String {
    let mut buffer = Vec::new();
    let _ = r.read_to_end(&mut buffer).unwrap();
    let mut d = GzDecoder::new(buffer.as_slice()).unwrap();
    let mut s = String::new();
    d.read_to_string(&mut s).unwrap();
    s
}

person Synesso    schedule 27.10.2016    source источник
comment
(В ответ на удаленный комментарий ...) Да, я сделал [попробовал &zs]. Результатов в trait '&&mut [u8]: std::io::Read' not satisfied.   -  person Synesso    schedule 28.10.2016
comment
Можете попробовать добавить к нему второй &? (Звучит глупо, но он работает на игровая площадка)   -  person Neikos    schedule 28.10.2016
comment
Это интересно, потому что это работает на детской площадке. Также хочу отметить, что [] - это массив длины 0, не позволяющий расти. Это означает, что чтение в конце концов ничего не даст. Испытайте удачу с Vec, если хотите прочитать все, например, через _ 3_   -  person Neikos    schedule 28.10.2016
comment
Это для гипер-клиента, верно?   -  person squiguy    schedule 28.10.2016
comment
Да, гипер-клиент.   -  person Synesso    schedule 28.10.2016
comment
Вы должны иметь возможность взаимно заимствовать r и передавать это GzDecoder, поскольку он принимает типы, реализующие Read, что делает клиент Response.   -  person squiguy    schedule 28.10.2016


Ответы (2)


Параметр GzDecoder::new определяется универсальным типом, поэтому Rust не будет выполнять некоторые преобразования, которые произошли бы, если бы ожидался фиксированный тип.

Вы можете преобразовать изменяемый фрагмент в неизменяемый фрагмент, разыменовав изменяемый фрагмент и взяв ссылку на результат.

let mut d = GzDecoder::new(&*zs).unwrap();
person Francis Gagné    schedule 28.10.2016

Вот еще один способ сделать это без использования другого буфера:

extern crate hyper;
extern crate flate2;

use std::io::Read;

use hyper::client::Client;
use hyper::header::{Headers, AcceptEncoding, Encoding, qitem};

use flate2::read::GzDecoder;

fn main() {
    let c = Client::new();

    let mut req = c.get("http://httpbin.org/gzip");
    let mut headers = Headers::new();
    headers.set(
        AcceptEncoding(vec![qitem(Encoding::Gzip)])
    );
    req = req.headers(headers);

    let res = req.send().unwrap();
    let mut decoder = GzDecoder::new(res).unwrap();
    let mut buf = String::new();

    let _ = decoder.read_to_string(&mut buf);
    println!("{}", buf);
}

В этом примере конечная точка gzip из HTTPBIN используется для проверки возможности использования Response в GzDecoder.

Зависимости, используемые в моем файле Cargo:

[dependencies]
hyper = "0.9"
flate2 = "0.2"

P.S. unwrap() Призывы для краткости :)

person squiguy    schedule 28.10.2016