I'm writing a little Rust terminal crate, and I need to create a struct that has a screen
field, where screen
is a termion::AlternateScreen
. Here is my code:
use std::io::{stdout, Write};
use termion;
use termion::raw::IntoRawMode;
use termion::screen::*;
pub struct Window {
screen: AlternateScreen,
stdout: termion::raw::RawTerminal<std::io::Stdout>,
}
impl Window {
/// Returns the completed [`Window`]; to be called after all the builder functions
pub fn build(self) -> Window {
Window { screen: self.screen, stdout: self.stdout }
}
/// Returns a new [`Window`], which can then be built using the builder functions
pub fn builder() -> Window {
Window { screen: AlternateScreen::from(stdout), stdout: stdout().into_raw_mode().unwrap(), }
}
}
Unfortunately, when I try to compile this, I get an error message:
error[E0107]: missing generics for struct `termion::screen::AlternateScreen`
--> src/widgets.rs:11:13
|
11 | screen: AlternateScreen,
| ^^^^^^^^^^^^^^^ expected 1 generic argument
|
note: struct defined here, with 1 generic parameter: `W`
--> /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/termion-1.5.6/src/lib.rs:49:12
|
49 | pub struct AlternateScreen<W: Write> {
| ^^^^^^^^^^^^^^^ -
help: add missing generic argument
|
11 | screen: AlternateScreen<W>,
| ~~~~~~~~~~~~~~~~~~
When I add <W>
in, as it suggests, I get another error saying that W
is not defined. When I fix that by adding <W>
to the end of pub struct Window
, I get an error message saying that none of the other uses of Window
in the program have the <W>
. When I fix all that (by adding <W>
to the end of every Window
in the code), I get yet another error message:
error[E0277]: the trait bound `W: std::io::Write` is not satisfied
--> src/widgets.rs:11:13
|
11 | screen: AlternateScreen<W>,
| ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `W`
|
note: required by a bound in `termion::screen::AlternateScreen`
--> /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/termion-1.5.6/src/lib.rs:49:31
|
49 | pub struct AlternateScreen<W: Write> {
| ^^^^^ required by this bound in `termion::screen::AlternateScreen`
help: consider restricting type parameter `W`
|
10 | pub struct Window<W: std::io::Write> {
|
For more information about this error, try `rustc --explain E0277`.
When I fix that error by replacing all <W>
s with <W: Write>
s, I get another error message saying that an "associated type is not allowed here". When I fix that (as the compiler suggests) by replacing all <W: Write>
s with <W, W: Write>
s, I get the same error message again, along with this struct takes 2 generic arguments but 1 generic argument was supplied
.
I've searched on here on SO for quite a while, but I didn't find anything that helped. I'm still pretty new to Rust, so I may have missed or misunderstood some answers. Could someone point me in the right direction here? How do I make it so that Window
can have an AlternateScreen
as one of its fields?
CodePudding user response:
In order to properly use a generic type, you need to understand what the generic parameters are for. You don't necessarily need to make your own types generic.
In this case, the reason for <W>
is that AlternateScreen
wraps the Write
able thing you're writing to — in the same kind of way that RawTerminal
already does. So this is what you need:
pub struct Window {
stdout: termion::raw::RawTerminal<AlternateScreen<std::io::Stdout>>,
}
And then you will need to adjust the code that constructs it correspondingly, with AlternateScreen::from()
.