microsoft/openvmm

Public

mirrored from https://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
release/1.7.2511

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

hyperv/tools/hypestv/src/windows/rustyline_printer.rs

59lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Implements a `Write` adapter for `rustyline::ExternalPrinter`. This allows
5//! writing to the console while there is an active rustyline prompt, without it
6//! overwriting the prompt.
7//!
8//! Ideally `rustyline` would just provide this facility natively.
9
10use parking_lot::Mutex;
11use std::io::LineWriter;
12use std::io::Write;
13use std::sync::Arc;
14
15#[derive(Clone)]
16pub struct Printer(Arc<Mutex<LineWriter<PrinterInner>>>);
17
18pub struct PrinterWriter<'a>(
19 parking_lot::lock_api::MutexGuard<'a, parking_lot::RawMutex, LineWriter<PrinterInner>>,
20);
21
22impl PrinterWriter<'_> {
23 pub fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
24 self.0.write_fmt(args)
25 }
26}
27
28pub struct PrinterInner<T: ?Sized = dyn rustyline::ExternalPrinter + Send>(T);
29
30impl Printer {
31 /// Makes a new printer.
32 pub fn new(printer: impl rustyline::ExternalPrinter + Send + 'static) -> Self {
33 // Use a `LineWriter` internally because each printer `print` call will
34 // write a full line. This way, as long as no line gets too long and no
35 // one calls `flush` (which is not exposed), we will always write at
36 // least one full line to the printer at a time.
37 Self(Arc::new(Mutex::new(LineWriter::new(PrinterInner(printer)))))
38 }
39
40 /// Gets the writer. Internally, this takes a lock to ensure that the line
41 /// is not split across multiple threads, so don't hold it for a long time
42 /// or across `await`s.
43 pub fn out(&self) -> PrinterWriter<'_> {
44 PrinterWriter(self.0.lock())
45 }
46}
47
48impl<T: rustyline::ExternalPrinter + ?Sized> Write for PrinterInner<T> {
49 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
50 let s = String::from_utf8_lossy(buf).into_owned();
51 self.0.print(s).map_err(std::io::Error::other)?;
52
53 Ok(buf.len())
54 }
55
56 fn flush(&mut self) -> std::io::Result<()> {
57 Ok(())
58 }
59}
60