Wrap a hyper::Body in a BufReader in Rust - rust

I have a hyper::Body and I want to wrap it in a BufReader (for example tokio::io::BufReader, but futures_util::io::BufReader or any other is fine too).
Using it directly didn't work:
fn foo(body: hyper::Body) {
let bufreader = tokio::io::BufReader::new(body);
}
error[E0277]: the trait bound `Body: AsyncRead` is not satisfied
--> src/lib.rs:2:47
|
2 | let bufreader = tokio::io::BufReader::new(body);
| ------------------------- ^^^^ the trait `AsyncRead` is not implemented for `Body`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `AsyncRead`:
&[u8]
&mut T
AddrStream
Box<T>
BufStream<RW>
DuplexStream
Pin<P>
Upgraded
and 20 others
note: required by a bound in `tokio::io::BufReader::<R>::new`
--> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.23.0/src/io/util/buf_reader.rs:37:9
|
37 | impl<R: AsyncRead> BufReader<R> {
| ^^^^^^^^^ required by this bound in `tokio::io::BufReader::<R>::new`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
I'm aware there are multiple AsyncRead in rust, tokio_util::compat::* and futures_util::compat::* can be used to convert between them, but it seems hyper::Body doesn't implement either of them.
It implements futures_core::stream::Stream but I don't know how to feed this into a BufReader.

Related

Define variable of type TimeZone

The following compiles and runs fine:
use chrono_tz::Tz;
use chrono::{TimeZone, NaiveDate};
use arrow2::temporal_conversions::parse_offset;
fn my_func(tz: &str) -> (){
let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
match parse_offset(&tz) {
Ok(time_zone) => {
println!("converted: {:?}", time_zone.from_utc_datetime(&ndt));
},
Err(_) => match tz.parse::<Tz>() {
Ok(time_zone) => {
println!("converted: {:?}", time_zone.from_utc_datetime(&ndt));
}
Err(error) => panic!("Problem opening the file: {:?}", error)
},
};
}
fn main() {
let time_zone = "Asia/Seoul";
my_func(&time_zone);
}
Noticed though that I'm doing
println!("converted: {:?}", time_zone.from_utc_datetime(&ndt));
twice.
I've tried refactoring to
use chrono_tz::Tz;
use chrono::{TimeZone, NaiveDate};
use arrow2::temporal_conversions::parse_offset;
fn my_func(tz: &str) -> (){
let ndt = NaiveDate::from_ymd_opt(2018, 9, 28).unwrap().and_hms_opt(2, 30, 0).unwrap();
let parsed_time_zone: TimeZone = match parse_offset(&tz) {
Ok(time_zone) => {
time_zone
},
Err(_) => match tz.parse::<Tz>() {
Ok(time_zone) => {
time_zone
}
Err(error) => panic!("Problem opening the file: {:?}", error)
},
};
println!("converted: {:?}", parsed_time_zone.from_utc_datetime(&ndt));
}
fn main() {
let time_zone = "Asia/Seoul";
my_func(&time_zone);
}
and get a long error:
error[E0782]: trait objects must include the `dyn` keyword
--> src/main.rs:7:27
|
7 | let parsed_time_zone: TimeZone = match parse_offset(&tz) {
| ^^^^^^^^
|
help: add `dyn` keyword before this trait
|
7 | let parsed_time_zone: dyn TimeZone = match parse_offset(&tz) {
| +++
error[E0191]: the value of the associated type `Offset` (from trait `TimeZone`) must be specified
--> src/main.rs:7:27
|
7 | let parsed_time_zone: TimeZone = match parse_offset(&tz) {
| ^^^^^^^^ help: specify the associated type: `TimeZone<Offset = Type>`
error[E0038]: the trait `TimeZone` cannot be made into an object
--> src/main.rs:7:27
|
7 | let parsed_time_zone: TimeZone = match parse_offset(&tz) {
| ^^^^^^^^ `TimeZone` cannot be made into an object
|
= note: the trait cannot be made into an object because it requires `Self: Sized`
= note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
error[E0308]: mismatched types
--> src/main.rs:9:13
|
9 | time_zone
| ^^^^^^^^^ expected trait object `dyn TimeZone`, found struct `FixedOffset`
|
= note: expected trait object `dyn TimeZone`
found struct `FixedOffset`
error[E0308]: mismatched types
--> src/main.rs:13:17
|
13 | time_zone
| ^^^^^^^^^ expected trait object `dyn TimeZone`, found enum `Tz`
|
= note: expected trait object `dyn TimeZone`
found enum `Tz`
error: the `from_utc_datetime` method cannot be invoked on a trait object
--> src/main.rs:18:50
|
18 | println!("converted: {:?}", parsed_time_zone.from_utc_datetime(&ndt));
| ^^^^^^^^^^^^^^^^^
|
::: /home/marcogorelli/.cargo/registry/src/github.com-1ecc6299db9ec823/chrono-0.4.23/src/offset/mod.rs:205:21
|
205 | pub trait TimeZone: Sized + Clone {
| ----- this has a `Sized` requirement
Some errors have detailed explanations: E0038, E0191, E0308, E0782.
For more information about an error, try `rustc --explain E0038`.
error: could not compile `tmp` due to 6 previous errors
I've tried the suggestion to do
let parsed_time_zone: dyn TimeZone = match parse_offset(&tz) {
but then it still errors with
error[E0191]: the value of the associated type `Offset` (from trait `TimeZone`) must be specified
--> src/main.rs:7:31
|
7 | let parsed_time_zone: dyn TimeZone = match parse_offset(&tz) {
| ^^^^^^^^ help: specify the associated type: `TimeZone<Offset = Type>`
How can I just parse tz as TimeZone, without specified whether it's Tz or FixedOffset, and then use it in the rest of the function?
You can't refactor this easily. Rust is strongly typed, and your two time_zone variables aren't the same type. One is chrono::FixedOffset, the other is chrono_tz::Tz.
If you do want to store both of them in the same variable, you have two possibilities:
trait object references (&dyn TimeZone)
Boxed trait objects (Box<dyn TimeZone).
dyn Timezone itself cannot directly be the type of a variable. It doesn't have a known size, because it could be any actual type of any size. Therefore you need one of the indirections above.
Both are non-ideal for your case though:
&dyn TimeZone won't work because someone has to own the actual object. You can't return a reference to a variable of an inner scope, as it gets dropped earlier than the reference does.
Box<dyn TimeZone> would work, no problem, but it introduces overhead: It will cause a heap allocation where the actual object will be put. The reason, as described earlier, is that a dyn object doesn't have a known size. Therefore, with Box, the actual object gets moved to the heap, and on the stack is the Box object, which has a known size.
So what I would do is: don't worry. The code duplication you have here is really minimal. I don't think it's worth the trouble.
Further detail I noticed after I wrote this answer:
TimeZone is : Sized, which means it isn't object safe and dyn TimeZone is disallowed entirely. So not even Box<dyn TimeZone> would work.

Wio Terminal how to use `writeln` method in UART

I use wio_terminal crate and implement UART communication.Previously following code could build but now it couldn't.
Now I use current version 0.6.1, previously I used version 0.3
#![no_std]
#![no_main]
use panic_halt as _;
use wio_terminal as wio;
use core::fmt::Write;
use wio::hal::clock::GenericClockController;
use wio::pac::Peripherals;
use wio::prelude::*;
use wio::{entry, Pins, Sets};
#[entry]
fn main() -> ! {
let mut peripherals = Peripherals::take().unwrap();
// Init clock
let mut clocks = GenericClockController::with_external_32kosc(
peripherals.GCLK,
&mut peripherals.MCLK,
&mut peripherals.OSC32KCTRL,
&mut peripherals.OSCCTRL,
&mut peripherals.NVMCTRL,
);
// Init UART driver
let mut sets: Sets = Pins::new(peripherals.PORT).split();
let mut serial = sets.uart.init(
&mut clocks,
115200.hz(),
peripherals.SERCOM2,
&mut peripherals.MCLK,
);
// Transfer UART
writeln!(&mut serial, "this is {} example!", "UART").unwrap();
}
Partly editted, so the line of error is different
This is the error message.
error[E0599]: the method `write_fmt` exists for mutable reference `&mut wio_terminal::atsamd_hal::sercom::uart::Uart<wio_terminal::atsamd_hal::sercom::uart::Config<wio_terminal::atsamd_hal::sercom::uart::Pads<SERCOM2, IoSet2, wio_terminal::atsamd_hal::gpio::Pin<PB27, wio_terminal::atsamd_hal::gpio::Alternate<wio_terminal::atsamd_hal::gpio::C>>, wio_terminal::atsamd_hal::gpio::Pin<PB26, wio_terminal::atsamd_hal::gpio::Alternate<wio_terminal::atsamd_hal::gpio::C>>>>, wio_terminal::atsamd_hal::sercom::uart::Duplex>`, but its trait bounds were not satisfied
--> examples\6-3-uart.rs:54:5
|
54 | writeln!(&mut serial, "this is {} example!", "UART").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
::: C:\Users\\.cargo\registry\src\github.com-1ecc6299db9ec823\atsamd-hal-0.15.1\src\sercom\uart.rs:602:1
|
602 | / pub struct Uart<C, D>
603 | | where
604 | | C: ValidConfig,
605 | | D: Capability,
... |
608 | | capability: PhantomData<D>,
609 | | }
| |_- doesn't satisfy `_: core::fmt::Write`
|
= note: the following trait bounds were not satisfied:
`wio_terminal::atsamd_hal::sercom::uart::Uart<wio_terminal::atsamd_hal::sercom::uart::Config<wio_terminal::atsamd_hal::sercom::uart::Pads<SERCOM2, IoSet2, wio_terminal::atsamd_hal::gpio::Pin<PB27, wio_terminal::atsamd_hal::gpio::Alternate<wio_terminal::atsamd_hal::gpio::C>>, wio_terminal::atsamd_hal::gpio::Pin<PB26, wio_terminal::atsamd_hal::gpio::Alternate<wio_terminal::atsamd_hal::gpio::C>>>>, wio_terminal::atsamd_hal::sercom::uart::Duplex>: core::fmt::Write`
which is required by `&mut wio_terminal::atsamd_hal::sercom::uart::Uart<wio_terminal::atsamd_hal::sercom::uart::Config<wio_terminal::atsamd_hal::sercom::uart::Pads<SERCOM2, IoSet2, wio_terminal::atsamd_hal::gpio::Pin<PB27, wio_terminal::atsamd_hal::gpio::Alternate<wio_terminal::atsamd_hal::gpio::C>>, wio_terminal::atsamd_hal::gpio::Pin<PB26, wio_terminal::atsamd_hal::gpio::Alternate<wio_terminal::atsamd_hal::gpio::C>>>>, wio_terminal::atsamd_hal::sercom::uart::Duplex>: core::fmt::Write`
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: unused import: `core::fmt::Write`
--> uart.rs:20:5
|
20 | use core::fmt::Write;
| ^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
For more information about this error, try `rustc --explain E0599`.
warning: `sample-template` (example "6-3-uart") generated 1 warning
error: could not compile `sample-template` due to previous error; 1 warning emitted
I couldn't understand and resolve this error. Please let me know how to resolve it.

access reference in struct causes cannot infer an appropriate lifetime for borrow expression due to conflicting requirements

I'm implementing a web service using tonic grpc crate.
Here is the my code:
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::sync::Mutex;
fn main() {
let my_struct = MyStruct {data_ref: RefCell::new(None), data: vec![MyData(28)]};
my_struct.my_fun();
// my_struct.my_fun_is_gone(); This is not working.
println!("{}", my_struct.data_ref.borrow().deref().unwrap().0);
}
/// AUTO GENERATED CODE OR THIRD PARTY TRAITS
///for example tonic generated Grpc services
trait TonicGeneratedGrpcService {
fn my_fun_is_gone(&self); //so I Can't change the &self lifetime parameter
}
struct MyData(u8);
struct MyStruct<'a> {
data: Vec<MyData>, //this struct is owns this property, there is no any problem
data_ref: RefCell<Option<&'a MyData>>, //And sometimes I want to save the data
}
impl<'a> TonicGeneratedGrpcService for MyStruct<'a> {
fn my_fun_is_gone(&self) { //I can't change the &self lifetime parameter because this is just an implementation of some super traits, change the lifetime parameters also requires change the super trait's method's lifetime.
//***********COMPILER ERROR is occurred HERE, how can I make this working?*************
let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
*self.data_ref.borrow_mut() = Some(some_of_data);
}
}
impl<'a> MyStruct<'a> {
//Below code is works fine if this is myself defined method, but I can't change the lifetime of "self" in super traits if this is a implementation of tonic generated service or other third party traits
fn my_fun(&'a self) {
let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
*self.data_ref.borrow_mut() = Some(some_of_data);
}
}
My final purpose is save the reference that one of the Vec<MyData> into data_ref field at runtime by some conditions.
Here is the compiler error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:28:29
|
28 | let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:26:23
|
26 | fn my_fun_is_gone(&self) { //I can't change the &self lifetime parameter because this is just an implementation of some super traits,...
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:28:29
|
28 | let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:25:6
|
25 | impl<'a> TonicGeneratedGrpcService for MyStruct<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:29:39
|
29 | *self.data_ref.borrow_mut() = Some(some_of_data);
| ^^^^^^^^^^^^^^^^^^
= note: expected `Option<&'a MyData>`
found `Option<&MyData>`
I can't change the source code of TonicGeneratedGrpcService trait because it may be in the third party crate or auto generated code,
and now I cannot find any way to make work the my_fun_is_gone method implementation.
Should I avoid the lifetime and use reference counted pointers (Rc, Arc) rather then save reference (&MyData) directly in struct MyStruct?
Or there any way to make work this?
As others said, Rust's lifetime system doesn't allow self-referential struct.
To solve this, you may directly store the index integer in the data_ref if data vec is only appended. Depending on your use case, you can also consider other options here Why can't I store a value and a reference to that value in the same struct?

Constraint associated type of a generic associated type

I have a type Builder with a Generic Associated Type (GAT) InstanceForBuilder<'a>.
I'd like to write a function (build_with_42_for_bool<Builder>) that constraints the Builder to only those cases where Builder::InstanceForBuilder<'a>::InstanceProperty == bool (for all 'a).
I've been playing around for a while to get the syntax around this for <'a> right, but haven't been able to make this work.
The lifetime can't be a template argument of the function itself, because the reference only lives inside it.
Is this possible at all yet, given that GAT is an unstable feature?
playground
#![feature(generic_associated_types)]
// Trait definitions.
trait Builder {
type InstanceForBuilder<'a>: Instance<'a>;
fn build<'a>(&self, val: &'a usize) -> Self::InstanceForBuilder<'a>;
}
trait Instance<'a> {
// Some functions will only work when the instance has some concrete associated type.
type InstanceProperty;
}
fn build_with_42_for_bool<B: Builder>(builder: B)
where
// TODO: What do I put here to make this work?
for<'a> B::InstanceForBuilder<'a>: Instance<'a, InstanceProperty = bool>,
{
builder.build(&42);
// Do some testing here. The Instance won't be returned.
}
// Now try it out.
struct MyBuilder;
struct MyInstance<'a> {
val: &'a usize,
}
impl Builder for MyBuilder {
type InstanceForBuilder<'a> = MyInstance<'a>;
fn build<'a>(&self, val: &'a usize) -> Self::InstanceForBuilder<'a> {
MyInstance { val }
}
}
impl<'a> Instance<'a> for MyInstance<'a> {
type InstanceProperty = bool;
}
fn main() {
let builder = MyBuilder;
build_with_42_for_bool(builder); // TODO: Doesn't work
}
In my actual code, build_with_42_for_bool is a helper for testing that constructs the arguments passed to build in a specific way. For now I'll probably just inline that function everywhere, since the only problem is how to specify the lifetime of this one function. The code itself works fine.
Here's the full error:
Compiling pairwise-aligner v0.1.0 (/home/philae/git/eth/git/astar-pairwise-aligner)
error[E0271]: type mismatch resolving `for<'a> <<_ as Builder>::InstanceForBuilder<'a> as Instance<'a>>::InstanceProperty == bool`
--> examples/test.rs:45:5
|
45 | build_with_42(builder); // TODO: Doesn't work
| ^^^^^^^^^^^^^ expected `bool`, found associated type
|
= note: expected type `bool`
found associated type `<<_ as Builder>::InstanceForBuilder<'_> as Instance<'_>>::InstanceProperty`
= help: consider constraining the associated type `<<_ as Builder>::InstanceForBuilder<'_> as Instance<'_>>::InstanceProperty` to `bool`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
note: required by a bound in `build_with_42`
--> examples/test.rs:19:53
|
16 | fn build_with_42<B: Builder>(builder: B)
| ------------- required by a bound in this
...
19 | for<'a> B::InstanceForBuilder<'a>: Instance<'a, InstanceProperty = bool>,
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `build_with_42`
error[E0271]: type mismatch resolving `for<'a> <MyBuilder as Builder>::InstanceForBuilder<'a> == <MyBuilder as Builder>::InstanceForBuilder<'a>`
--> examples/test.rs:45:5
|
45 | build_with_42(builder); // TODO: Doesn't work
| ^^^^^^^^^^^^^ type mismatch resolving `for<'a> <MyBuilder as Builder>::InstanceForBuilder<'a> == <MyBuilder as Builder>::InstanceForBuilder<'a>`
|
note: expected this to be `<MyBuilder as Builder>::InstanceForBuilder<'a>`
--> examples/test.rs:32:35
|
32 | type InstanceForBuilder<'a> = MyInstance<'a>;
| ^^^^^^^^^^^^^^
= note: expected associated type `<MyBuilder as Builder>::InstanceForBuilder<'a>`
found struct `MyInstance<'a>`
help: a method is available that returns `<MyBuilder as Builder>::InstanceForBuilder<'a>`
--> examples/test.rs:8:5
|
8 | fn build<'a>(&self, val: &'a usize) -> Self::InstanceForBuilder<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Builder::build`
note: required by a bound in `build_with_42`
--> examples/test.rs:19:40
|
16 | fn build_with_42<B: Builder>(builder: B)
| ------------- required by a bound in this
...
19 | for<'a> B::InstanceForBuilder<'a>: Instance<'a, InstanceProperty = bool>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `build_with_42`
For more information about this error, try `rustc --explain E0271`.
error: could not compile `pairwise-aligner` due to 2 previous errors
The correct syntax to do what you want is:
where B::InstanceForBuilder::InstanceProperty = bool
there's no need to introduce the for<'a> lifetime because the value of the associated type is not allowed to depend on the lifetime parameter. If you compile this code, you'll find that you get another error:
error: equality constraints are not yet supported in `where` clauses
--> src/main.rs:19:5
|
19 | B::InstanceForBuilder::InstanceProperty = bool,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported
|
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
There's no immediate workaround for this. If you badly need this, you may be able to write a new trait, implement it only for bool, and then constrain things to that trait. That will get messy quickly though.
The answer from DreamConspiracy is a little outdated. I'd like to reuse the example codes from him to show a compiled solution
Instead of
where B::InstanceForBuilder::InstanceProperty = bool
You should write
fn build_with_42_for_bool_instance<'a, B, I>(builder: B)
where
B : Builder<InstanceForBuilder<'a>=I>,
I : Instance<'a, InstanceProperty=bool>,
{
builder.build(&42);
}

Type constructor in trait declaration

I want to pass a reference to a Rusoto SQS client to a WebSocket server struct to push messages onto an SQS queue.
To that end, I have a (naive) struct as follows:
struct MyHandler {
sqsclient: &SqsClient<ProvideAwsCredentials, DispatchSignedRequest>,
}
This produces the error:
error[E0106]: missing lifetime specifier
--> src/main.rs:29:13
|
29 | sqsclient: &SqsClient<ProvideAwsCredentials, DispatchSignedRequest>,
| ^ expected lifetime parameter
I've attempted all sorts of type signatures and lifetime trickery which all fail to varying levels, but I keep coming up against the same error:
error[E0277]: the trait bound `rusoto_core::ProvideAwsCredentials + 'static: std::marker::Sized` is not satisfied
--> src/main.rs:29:2
|
29 | sqsclient: &'static SqsClient<ProvideAwsCredentials, DispatchSignedRequest>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `rusoto_core::ProvideAwsCredentials + 'static` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `rusoto_core::ProvideAwsCredentials + 'static`
= note: required by `rusoto_sqs::SqsClient`
error[E0277]: the trait bound `rusoto_core::DispatchSignedRequest + 'static: std::marker::Sized` is not satisfied
--> src/main.rs:29:2
|
29 | sqsclient: &'static SqsClient<ProvideAwsCredentials, DispatchSignedRequest>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `rusoto_core::DispatchSignedRequest + 'static` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `rusoto_core::DispatchSignedRequest + 'static`
= note: required by `rusoto_sqs::SqsClient`
I've also tried wrapping it in Rc and Box to no avail. I feel like I'm looking in the wrong place with these though.
This happens when giving MyHandler an <'a> lifetime too. What am I misunderstanding about the Rust type system here, and what can I do to be able to pass a reference to an SqsClient<...> (and eventually other stuff from Rusoto) into my own structs? It would be useful to know if what I'm trying to do above is idiomatic Rust. If it's not, what pattern should I use instead?
This is a follow up from How do I pass a struct with type parameters as a function argument?.
Solved it! DispatchSignedRequest and ProvideAwsCredentials (from Rusoto) are traits. I needed to use impls of those traits, i.e. structs, so now the code looks like this:
extern crate rusoto_core;
extern crate hyper;
use hyper::Client;
use rusoto_sqs::{ Sqs, SqsClient };
use rusoto_core::{ DefaultCredentialsProvider };
struct MyHandler<'a> {
sqsclient: &'a SqsClient<DefaultCredentialsProvider, Client>,
}
impl<'a> Handler for MyHandler<'a> {
// ...
}
DefaultCredentialsProvider and Client (from Hyper) are both structs, so now this code compiles fine.
I'm using Hyper 0.10 here. Hyper 0.11 requires a different type signature for Client.

Resources