2026-09-15 23:41:39 +03:00
|
|
|
mod handling;
|
|
|
|
|
mod testing;
|
|
|
|
|
|
|
|
|
|
use litemap::LiteMap;
|
2026-09-15 10:38:03 +03:00
|
|
|
use minicbor::data::Type;
|
2026-09-15 23:41:39 +03:00
|
|
|
use minicbor::decode::Error;
|
2026-09-16 11:03:43 +03:00
|
|
|
use minicbor::Decoder;
|
2026-09-15 23:41:39 +03:00
|
|
|
use std::collections::HashMap;
|
2026-09-16 11:03:43 +03:00
|
|
|
use std::fmt::{Display, Formatter};
|
2026-09-15 23:41:39 +03:00
|
|
|
use std::io::Write;
|
2026-09-15 10:38:03 +03:00
|
|
|
|
2026-09-15 23:41:39 +03:00
|
|
|
pub enum Command {
|
2026-09-15 10:38:03 +03:00
|
|
|
Unknown,
|
2026-09-15 23:41:39 +03:00
|
|
|
Set(String, StoredData),
|
|
|
|
|
Define(String, LiteMap<String, StoredData>),
|
|
|
|
|
Push(String, StoredData),
|
|
|
|
|
Display(String),
|
|
|
|
|
SetOutput(fn() -> Box<dyn Write>),
|
2026-09-15 10:38:03 +03:00
|
|
|
}
|
|
|
|
|
|
2026-09-15 23:41:39 +03:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub enum StoredData {
|
|
|
|
|
Integer(isize),
|
|
|
|
|
Float(f64),
|
|
|
|
|
String(String),
|
|
|
|
|
Bool(bool),
|
|
|
|
|
Line(Line),
|
|
|
|
|
Vec(Vec<StoredData>),
|
2026-09-15 10:38:03 +03:00
|
|
|
}
|
|
|
|
|
|
2026-09-15 23:41:39 +03:00
|
|
|
impl Display for StoredData {
|
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
match self {
|
|
|
|
|
StoredData::Integer(v) => v.fmt(f),
|
|
|
|
|
StoredData::Float(v) => v.fmt(f),
|
|
|
|
|
StoredData::String(v) => v.fmt(f),
|
|
|
|
|
StoredData::Bool(v) => v.fmt(f),
|
|
|
|
|
StoredData::Line(v) => v.fmt(f),
|
|
|
|
|
StoredData::Vec(vec) => {
|
|
|
|
|
vec.iter().for_each(|d| {
|
|
|
|
|
_ = write!(f, "{}\n", d);
|
|
|
|
|
});
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct Line {
|
|
|
|
|
data: Vec<StoredData>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<Vec<StoredData>> for Line {
|
|
|
|
|
fn from(value: Vec<StoredData>) -> Self {
|
|
|
|
|
Self { data: value }
|
2026-09-15 10:38:03 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Display for Line {
|
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
2026-09-15 23:41:39 +03:00
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"[{}]",
|
|
|
|
|
self.data
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|i| i.to_string())
|
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
|
.join(", ")
|
|
|
|
|
)
|
2026-09-15 10:38:03 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<&[u8]> for Command {
|
|
|
|
|
fn from(value: &[u8]) -> Self {
|
2026-09-16 11:03:43 +03:00
|
|
|
parse_command(value).unwrap_or_else(|e| {
|
|
|
|
|
println!("{}", e);
|
|
|
|
|
Command::Unknown
|
|
|
|
|
})
|
2026-09-15 10:38:03 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn parse_command(data: &[u8]) -> Result<Command, Error> {
|
|
|
|
|
if data.starts_with(b"SET:") {
|
|
|
|
|
let payload = &data[b"SET:".len()..];
|
|
|
|
|
let mut decoder = Decoder::new(&payload);
|
|
|
|
|
decoder.array()?;
|
|
|
|
|
let id = decoder.str()?.to_string();
|
|
|
|
|
let value = decode_value(&mut decoder)?;
|
2026-09-15 23:41:39 +03:00
|
|
|
return Ok(Command::Set(id, value));
|
2026-09-15 22:35:36 +03:00
|
|
|
}
|
|
|
|
|
if data.starts_with(b"PUSH:") {
|
2026-09-16 11:03:43 +03:00
|
|
|
println!("{}", String::from_utf8_lossy(data));
|
2026-09-15 22:35:36 +03:00
|
|
|
let payload = &data[b"PUSH:".len()..];
|
|
|
|
|
let mut decoder = Decoder::new(&payload);
|
|
|
|
|
decoder.array()?;
|
|
|
|
|
let id = decoder.str()?.to_string();
|
|
|
|
|
let value = decode_value(&mut decoder)?;
|
2026-09-15 23:41:39 +03:00
|
|
|
return Ok(Command::Push(id, value));
|
|
|
|
|
}
|
|
|
|
|
if data.starts_with(b"DISPLAY:") {
|
|
|
|
|
let payload = &data[b"DISPLAY:".len()..];
|
|
|
|
|
let mut decoder = Decoder::new(&payload);
|
|
|
|
|
decoder.array()?;
|
|
|
|
|
let id = decoder.str()?.to_string();
|
|
|
|
|
return Ok(Command::Display(id));
|
2026-09-15 10:38:03 +03:00
|
|
|
}
|
|
|
|
|
Ok(Command::Unknown)
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-15 23:41:39 +03:00
|
|
|
fn decode_value(decoder: &mut Decoder) -> Result<StoredData, Error> {
|
2026-09-15 10:38:03 +03:00
|
|
|
Ok(match decoder.datatype()? {
|
2026-09-15 23:41:39 +03:00
|
|
|
Type::Bool => StoredData::Bool(decoder.bool()?),
|
|
|
|
|
Type::U8 => StoredData::Integer(decoder.u8()? as isize),
|
|
|
|
|
Type::U16 => StoredData::Integer(decoder.u16()? as isize),
|
|
|
|
|
Type::U32 => StoredData::Integer(decoder.u32()? as isize),
|
|
|
|
|
Type::U64 => StoredData::Integer(decoder.u64()? as isize),
|
|
|
|
|
Type::I8 => StoredData::Integer(decoder.i8()? as isize),
|
|
|
|
|
Type::I16 => StoredData::Integer(decoder.i16()? as isize),
|
|
|
|
|
Type::I32 => StoredData::Integer(decoder.i32()? as isize),
|
|
|
|
|
Type::I64 => StoredData::Integer(decoder.i64()? as isize),
|
|
|
|
|
Type::Int => StoredData::Integer(decoder.i32()? as isize),
|
|
|
|
|
Type::F16 => StoredData::Float(decoder.f32()? as f64),
|
|
|
|
|
Type::F32 => StoredData::Float(decoder.f32()? as f64),
|
|
|
|
|
Type::F64 => StoredData::Float(decoder.f64()?),
|
|
|
|
|
Type::String | Type::StringIndef => StoredData::String(decoder.str()?.to_string()),
|
|
|
|
|
Type::Array | Type::ArrayIndef => {
|
2026-09-15 10:38:03 +03:00
|
|
|
let len = decoder.array()?;
|
2026-09-15 23:41:39 +03:00
|
|
|
let mut array = if let Some(len) = len {
|
|
|
|
|
Vec::with_capacity(len as usize)
|
|
|
|
|
} else {
|
|
|
|
|
vec![]
|
|
|
|
|
};
|
2026-09-15 10:38:03 +03:00
|
|
|
if array.is_empty() {
|
|
|
|
|
loop {
|
|
|
|
|
let dt = decoder.datatype()?;
|
|
|
|
|
if let Type::Break = dt {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
array.push(decode_value(decoder)?);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-09-15 23:41:39 +03:00
|
|
|
StoredData::Line(Line::from(array))
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
decoder.skip()?;
|
|
|
|
|
StoredData::Bool(false)
|
2026-09-15 10:38:03 +03:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-15 23:41:39 +03:00
|
|
|
pub struct NoteContext {
|
|
|
|
|
entries: HashMap<String, StoredData>,
|
|
|
|
|
output: Box<dyn Write>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NoteContext {
|
|
|
|
|
pub fn default() -> Self {
|
2026-09-16 11:03:43 +03:00
|
|
|
Self {
|
2026-09-15 23:41:39 +03:00
|
|
|
entries: Default::default(),
|
|
|
|
|
output: Box::new(std::io::stdout()),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|