dprint_core/communication/
message.rs

1use std::io::ErrorKind;
2use std::io::Write;
3
4use crate::communication::MessageWriter;
5
6pub trait Message: std::fmt::Debug + Send + Sync + 'static {
7  fn write<TWrite: Write + Unpin>(&self, writer: &mut MessageWriter<TWrite>) -> std::io::Result<()>;
8}
9
10struct SingleThreadMessageWriterOptions<TWrite: Write + Unpin> {
11  pub writer: MessageWriter<TWrite>,
12  pub panic_on_write_fail: bool,
13}
14
15/// Writes messages on a separate thread.
16pub struct SingleThreadMessageWriter<TMessage: Message> {
17  tx: crossbeam_channel::Sender<TMessage>,
18}
19
20impl<TMessage: Message> SingleThreadMessageWriter<TMessage> {
21  pub fn for_stdout<TWrite: Write + Unpin + Send + 'static>(writer: MessageWriter<TWrite>) -> Self {
22    Self::new(SingleThreadMessageWriterOptions {
23      writer,
24      panic_on_write_fail: true,
25    })
26  }
27
28  pub fn for_stdin<TWrite: Write + Unpin + Send + 'static>(writer: MessageWriter<TWrite>) -> Self {
29    Self::new(SingleThreadMessageWriterOptions {
30      writer,
31      panic_on_write_fail: false,
32    })
33  }
34
35  fn new<TWrite: Write + Unpin + Send + 'static>(mut opts: SingleThreadMessageWriterOptions<TWrite>) -> Self {
36    let (tx, rx) = crossbeam_channel::unbounded::<TMessage>();
37
38    // use a dedicated thread for writing messages
39    crate::async_runtime::spawn_blocking({
40      move || {
41        while let Ok(result) = rx.recv() {
42          if let Err(err) = result.write(&mut opts.writer) {
43            if opts.panic_on_write_fail {
44              panic!("{:#}", err);
45            } else {
46              break;
47            }
48          }
49        }
50      }
51    });
52
53    Self { tx }
54  }
55
56  pub fn send(&self, message: TMessage) -> std::io::Result<()> {
57    self.tx.send(message).map_err(|err| std::io::Error::new(ErrorKind::BrokenPipe, err))
58  }
59}