#![expect(clippy::pub_use, reason = "This seems to come from the `bon` crate")]
pub type Colour = (f32, f32, f32, f32);
#[derive(serde::Serialize, serde::Deserialize, bon::Builder, Clone, Copy, Debug)]
#[non_exhaustive]
pub struct Cell {
pub character: char,
pub coordinates: (u32, u32),
pub bg: Option<Colour>,
pub fg: Option<Colour>,
}
#[derive(serde::Serialize, serde::Deserialize, bon::Builder, Clone, Copy, Debug)]
#[non_exhaustive]
pub struct Pixel {
pub coordinates: (u32, u32),
pub color: Option<Colour>,
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum PluginInputMessages {
#[serde(rename = "pty_update")]
PTYUpdate {
size: (u16, u16),
cells: Vec<Cell>,
cursor: (u16, u16),
},
#[serde(rename = "tty_resize")]
TTYResize {
width: u16,
height: u16,
},
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum PluginOutputMessages {
OutputText {
text: String,
coordinates: (u32, u32),
bg: Option<Colour>,
fg: Option<Colour>,
},
OutputCells(Vec<Cell>),
OutputPixels(Vec<Pixel>),
}
#[expect(clippy::default_numeric_fallback, reason = "Tests aren't so strict")]
#[cfg(test)]
mod test {
use super::*;
#[test]
fn output_text() {
let expected = serde_json::json!(
{
"output_text": {
"text": "foo",
"coordinates": [1, 2],
"bg": null,
"fg": [0.1, 0.2, 0.3, 0.4],
}
}
);
let output = PluginOutputMessages::OutputText {
text: "foo".to_owned(),
coordinates: (1, 2),
bg: None,
fg: Some((0.1, 0.2, 0.3, 0.4)),
};
assert_eq!(
expected.to_string(),
serde_json::to_string(&output).unwrap()
);
}
#[test]
fn output_cells() {
let expected = serde_json::json!(
{
"output_cells": [{
"character": "f",
"coordinates": [1, 2],
"bg": null,
"fg": [0.1, 0.2, 0.3, 0.4],
}]
}
);
let output = PluginOutputMessages::OutputCells(vec![Cell {
character: 'f',
coordinates: (1, 2),
bg: None,
fg: Some((0.1, 0.2, 0.3, 0.4)),
}]);
assert_eq!(
expected.to_string(),
serde_json::to_string(&output).unwrap()
);
}
#[test]
fn output_pixels() {
let expected = serde_json::json!(
{
"output_pixels": [{
"coordinates": [1, 2],
"color": [0.1, 0.2, 0.3, 0.4],
}]
}
);
let output = PluginOutputMessages::OutputPixels(vec![Pixel {
coordinates: (1, 2),
color: Some((0.1, 0.2, 0.3, 0.4)),
}]);
assert_eq!(
expected.to_string(),
serde_json::to_string(&output).unwrap()
);
}
#[test]
fn input_pty_update() {
let expected = serde_json::json!(
{
"pty_update": {
"size": [1, 2],
"cells": [{
"character": "f",
"coordinates": [1, 2],
"bg": null,
"fg": [0.1, 0.2, 0.3, 0.4],
}],
"cursor": [9, 10],
}
}
);
let output = PluginInputMessages::PTYUpdate {
size: (1, 2),
cells: vec![Cell {
character: 'f',
coordinates: (1, 2),
bg: None,
fg: Some((0.1, 0.2, 0.3, 0.4)),
}],
cursor: (9, 10),
};
assert_eq!(
expected.to_string(),
serde_json::to_string(&output).unwrap()
);
}
#[test]
fn input_tty_resize() {
let expected = serde_json::json!(
{
"tty_resize": {
"width": 1,
"height": 2,
}
}
);
let output = PluginInputMessages::TTYResize {
width: 1,
height: 2,
};
assert_eq!(
expected.to_string(),
serde_json::to_string(&output).unwrap()
);
}
}