Я создал поле stdout
в своей структуре TermWriter
, потому что хочу иметь возможность использовать внешний стандартный вывод (например, из ящика Termion), а также фиктивный стандартный вывод для тестов (также внешний метод cursor_pos()
и фиктивный для тестов ).
pub struct TermWriter<W: Write> {
pub input: String,
cursor_pos: Position,
stdout: W,
}
impl<W: Write> TermWriter<W> {
pub fn new(input: String, stdout: W) -> Self {
Self {
input,
cursor_pos: Position { x: 1, y: 2 },
stdout,
}
}
pub fn right(&mut self) -> Result<(), InputError> {
if self.cursor_pos.x <= self.input.len() as u16 {
write!(self.stdout, "{}", termion::cursor::Right(1))?;
let cursor_pos = self.stdout.cursor_pos()?;
self.cursor_pos.x = cursor_pos.0;
}
Ok(())
}
}
Таким образом, метод TermWriter new()
принимает стандартный вывод в качестве параметра. Однако здесь есть проблема:
pub fn get_input(
input_keys: impl Iterator<Item = Result<Key, std::io::Error>>,
stdout: &mut impl Write,
) -> Result<Input, InputError> {
let input = String::new();
let mut term_writer = TermWriter::new(input, stdout);
for key in input_keys {
match key.unwrap() {
Key::Right => term_writer.right()?,
_ => {}
}
stdout.flush().unwrap();
}
let input = term_writer.input.trim().to_owned();
Ok(Input::Text(input))
}
stdout
был перемещен сюда: TermWriter::new(input, stdout)
, поэтому stdout.flush().unwrap();
заимствует перемещенное значение.
Как предотвратить эту проблему перемещения стоимости/заимствования?
@PitaJ Спасибо за предложение, но я понимаю cannot borrow `stdout` as mutable more than once at a time
.
term_writer.stdout.flush().unwrap()
?
stdout
доступен из вашего вновь созданного term_writer
, так что это должно работать (то же самое, что вы делаете для input
):
term_writer.stdout.flush().unwrap()
Другое дело, что вместо Write
следует брать &mut Write
, так как любой &mut Write также реализует Write.
pub fn get_input(
...
stdout: impl Write,
)
Спасибо! Такое простое решение. Один вопрос: Итак, здесь я делаю term_writer.stdout.flush().unwrap()
, но везде я делаю stdout.flush()
. Означает ли это, что у меня здесь проблема с дизайном?
@alexchenco ты имеешь в виду отсутствие term_writer
или отсутствие unwrap
?
Я имею в виду отсутствие term_writer
.
@alexchenco Пока вы не создаете несколько stdout
, компилируется только один из них. Так что просто используйте то, что работает.
Попробуйте
TermWriter::new(input, &mut *stdout);