Skip to main content

nil_lua/
stdio.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use jiff::Zoned;
5use serde::{Deserialize, Serialize};
6use std::cmp::Ordering;
7use std::fmt;
8use std::sync::atomic::AtomicU32;
9use std::sync::atomic::Ordering::Relaxed;
10use tokio::sync::mpsc::UnboundedReceiver;
11
12static ID: AtomicU32 = AtomicU32::new(1);
13
14pub struct Stdio {
15  pub(crate) buffer: Vec<StdioMessage>,
16  receiver: UnboundedReceiver<StdioMessage>,
17}
18
19impl Stdio {
20  pub(crate) fn new(receiver: UnboundedReceiver<StdioMessage>) -> Self {
21    Self { buffer: Vec::new(), receiver }
22  }
23
24  pub(crate) fn flush(&mut self) {
25    while let Ok(message) = self.receiver.try_recv() {
26      self.buffer.push(message);
27    }
28  }
29}
30
31#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
32#[serde(rename_all = "camelCase")]
33pub struct StdioMessage {
34  id: u32,
35  content: String,
36  time: Zoned,
37}
38
39impl StdioMessage {
40  pub(crate) fn new(content: String) -> Self {
41    Self {
42      id: ID.fetch_add(1, Relaxed),
43      content,
44      time: Zoned::now(),
45    }
46  }
47}
48
49impl PartialOrd for StdioMessage {
50  fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
51    Some(self.cmp(other))
52  }
53}
54
55impl Ord for StdioMessage {
56  fn cmp(&self, other: &Self) -> Ordering {
57    self
58      .time
59      .cmp(&other.time)
60      .then_with(|| self.id.cmp(&other.id))
61  }
62}
63
64impl fmt::Display for StdioMessage {
65  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66    write!(f, "{}", self.content)
67  }
68}