diff options
Diffstat (limited to 'console/src/lib.rs')
| -rw-r--r-- | console/src/lib.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/console/src/lib.rs b/console/src/lib.rs new file mode 100644 index 0000000..afab4af --- /dev/null +++ b/console/src/lib.rs @@ -0,0 +1,100 @@ +use std::net::Ipv6Addr; + +use log::Level; +use pollster::FutureExt; +use smol::channel::{Receiver, Sender}; +use smol::io::AsyncWriteExt; +use smol::net::{TcpListener, TcpStream}; + +pub struct Console { + tcp_socket: TcpStream, + messages: Receiver<ConsoleMessage>, + sender: Sender<ConsoleMessage>, +} + +pub enum ConsoleMessage { + RuntimeLog { + message: String, + level: Level, + file: String, + line: u32, + }, + ScriptLog { + message: String, + level: Level, + file: String, + line: u32, + }, +} + +pub struct ConsoleLogger(Sender<ConsoleMessage>); + +impl Console { + pub async fn new(port: u16) -> Result<Self, std::io::Error> { + let tcp_listener = TcpListener::bind((Ipv6Addr::LOCALHOST, port)).await?; + let tcp_socket = tcp_listener.accept().await?.0; + let (sender, reciever) = smol::channel::unbounded(); + Ok(Self { + tcp_socket, + messages: reciever, + sender, + }) + } + + pub fn sender(&self) -> Sender<ConsoleMessage> { + self.sender.clone() + } + + pub fn logger(&self) -> ConsoleLogger { + ConsoleLogger(self.sender()) + } + + pub async fn flush(&mut self) -> std::io::Result<()> { + while let Ok(message) = self.messages.try_recv() { + match message { + ConsoleMessage::RuntimeLog { + message, + level, + file, + line, + } => { + let msg = format!("runtimelog {level} {file}:{line} {message}\n"); + self.tcp_socket.write(msg.as_bytes()).await?; + } + ConsoleMessage::ScriptLog { + message, + level, + file, + line, + } => { + let msg = format!("scriptlog {level} {file}:{line} {message}\n"); + self.tcp_socket.write(msg.as_bytes()).await?; + } + } + } + + self.tcp_socket.flush().await?; + + Ok(()) + } +} + +impl log::Log for ConsoleLogger { + fn enabled(&self, _: &log::Metadata) -> bool { + true + } + + fn log(&self, record: &log::Record) { + let _ = self + .0 + .send(ConsoleMessage::RuntimeLog { + message: record.args().to_string(), + level: record.level(), + file: record.file().map(str::to_string).unwrap_or_default(), + line: record.line().unwrap_or_default(), + }) + .block_on(); + } + + fn flush(&self) {} +} |
