thedes_tui_core/screen/
device.rs1use std::fmt;
2
3use thedes_async_util::dyn_async_trait;
4use thiserror::Error;
5use tokio::io;
6
7use crate::{color::Color, geometry::CoordPair};
8
9pub mod native;
10pub mod null;
11
12#[cfg(feature = "testing")]
13pub mod mock;
14
15#[derive(Debug, Error)]
16pub enum Error {
17 #[error(transparent)]
18 Io(#[from] io::Error),
19 #[error("Failed to format command")]
20 Fmt(
21 #[from]
22 #[source]
23 fmt::Error,
24 ),
25 #[error("Invalid command: {:#?}", .0)]
26 InvalidCommand(Command),
27 #[error(transparent)]
28 Custom(#[from] Box<dyn std::error::Error + Send + Sync>),
29}
30
31#[derive(Debug, Clone, PartialEq)]
32pub enum Command {
33 Enter,
34 Leave,
35 Clear,
36 ResetBackground,
37 ResetForeground,
38 SetBackground(Color),
39 SetForeground(Color),
40 ShowCursor,
41 HideCursor,
42 MoveCursor(CoordPair),
43 Write(char),
44}
45
46#[dyn_async_trait]
47pub trait ScreenDevice: fmt::Debug + Send + Sync {
48 fn send_raw(
49 &mut self,
50 commands: &mut (dyn Iterator<Item = Command> + Send + Sync),
51 ) -> Result<(), Error>;
52
53 async fn flush(&mut self) -> Result<(), Error>;
54
55 fn blocking_get_size(&mut self) -> Result<CoordPair, Error>;
56}
57
58#[dyn_async_trait]
59impl<'a, D> ScreenDevice for &'a mut D
60where
61 D: ScreenDevice + ?Sized,
62{
63 fn send_raw(
64 &mut self,
65 commands: &mut (dyn Iterator<Item = Command> + Send + Sync),
66 ) -> Result<(), Error> {
67 (**self).send_raw(commands)
68 }
69
70 async fn flush(&mut self) -> Result<(), Error> {
71 (**self).flush().await
72 }
73
74 fn blocking_get_size(&mut self) -> Result<CoordPair, Error> {
75 (**self).blocking_get_size()
76 }
77}
78
79#[dyn_async_trait]
80impl<D> ScreenDevice for Box<D>
81where
82 D: ScreenDevice + ?Sized,
83{
84 fn send_raw(
85 &mut self,
86 commands: &mut (dyn Iterator<Item = Command> + Send + Sync),
87 ) -> Result<(), Error> {
88 (**self).send_raw(commands)
89 }
90
91 async fn flush(&mut self) -> Result<(), Error> {
92 (**self).flush().await
93 }
94
95 fn blocking_get_size(&mut self) -> Result<CoordPair, Error> {
96 (**self).blocking_get_size()
97 }
98}
99
100pub trait ScreenDeviceExt: ScreenDevice {
101 fn send<I>(&mut self, iterable: I) -> Result<(), Error>
102 where
103 I: IntoIterator<Item = Command>,
104 I::IntoIter: Send + Sync,
105 {
106 self.send_raw(&mut iterable.into_iter())
107 }
108}
109
110impl<S> ScreenDeviceExt for S where S: ScreenDevice {}