Server code

This commit is contained in:
micialware committed 2026-09-15 23:41:39 +03:00
1 parent 4c2cd7130b
commit ec73c54276
6 files changed
+213 -47

No files matched your search

Generated
+7
View File
@@ -170,6 +170,12 @@ dependencies = [
"syn 2.0.119", "syn 2.0.119",
] ]
[[package]]
name = "litemap"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.34" version = "0.4.34"
@@ -261,6 +267,7 @@ name = "remote_marks"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"litemap",
"log", "log",
"minicbor", "minicbor",
] ]
+2 -1
View File
@@ -6,4 +6,5 @@ edition = "2024"
[dependencies] [dependencies]
env_logger = "0.11.11" env_logger = "0.11.11"
log = "0.4.34" log = "0.4.34"
minicbor = "2.3.0" minicbor = "2.3.0"
litemap = "0.8.3"
+39 -7
View File
@@ -1,15 +1,47 @@
mod server; mod server;
use std::any::Any; use crate::server::{Command, NoteContext};
use std::collections::HashMap; use std::io;
use std::io::Read;
use std::net::UdpSocket; use std::net::UdpSocket;
use std::sync::mpsc::*;
const LISTEN: &str = "127.0.0.1:8080"; const LISTEN: &str = "127.0.0.1:8080";
fn main() { fn main() {
let listener = UdpSocket::bind(LISTEN).unwrap(); let (cw, cr) = channel::<Command>();
let mut buffer = [0; 1024];
while let Ok((inbound, outbound)) = listener.recv_from(&mut buffer) {} std::thread::spawn(move || {
let mut context = NoteContext::default();
while let Ok(message) = cr.recv() {
context.execute_command(message);
}
});
let network_cw = cw.clone();
std::thread::spawn(move || {
let listener = UdpSocket::bind(LISTEN).unwrap();
let mut buffer = [0; 1024];
while let Ok((inbound, _outbound)) = listener.recv_from(&mut buffer) {
let command= Command::from(&buffer[..inbound]);
network_cw.send(command).unwrap();
}
});
handle_console_input(cw);
}
fn handle_console_input(command_channel: Sender<Command>) {
let mut key = String::new();
loop {
io::stdin().read_to_string(&mut key).unwrap();
if key == "exit" {
break;
}
if key.is_empty(){
continue;
}
command_channel.send(Command::Display(key.clone())).unwrap();
}
} }
+55
View File
@@ -0,0 +1,55 @@
use crate::server::StoredData::*;
use crate::server::{Command, NoteContext, StoredData};
use litemap::LiteMap;
use std::io::Write;
use std::string::String;
impl NoteContext {
pub fn execute_command(&mut self, command: Command) {
match command {
Command::Unknown => {}
Command::Set(key, value) => self.set(key, value),
Command::Define(key, schema) => self.define(key, schema),
Command::Push(key, value) => self.push(key, value),
Command::Display(key) => self.display(key),
Command::SetOutput(generator) => self.output = generator(),
}
}
fn set(&mut self, key: String, value: StoredData) {
if key.is_empty() {
return;
}
self.entries.insert(key, value);
}
fn push(&mut self, key: String, value: StoredData) {
let mut vectorize: Option<StoredData> = None;
let current = self.entries.get_mut(&key);
if let Some(current) = current {
if let Vec(vec) = current {
vec.push(value);
} else {
vectorize = Some(Vec(vec![current.clone()]));
}
} else {
self.set(key, value);
return;
}
if let Some(vec) = vectorize {
self.set(key, vec);
}
}
fn define(&mut self, _key: String, _value: LiteMap<String, StoredData>) {
todo!()
}
fn display(&mut self, key: String) {
if let Some(data) = self.entries.get(&key) {
writeln!(self.output, "{}", key).unwrap();
_ = self.output.write_all(data.to_string().as_bytes());
}
}
}
+105 -39
View File
@@ -1,29 +1,73 @@
use minicbor::decode::Error; mod handling;
mod testing;
use litemap::LiteMap;
use minicbor::Decoder; use minicbor::Decoder;
use std::any::Any;
use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter};
use minicbor::data::Type; use minicbor::data::Type;
use minicbor::decode::Error;
use std::collections::HashMap;
use std::fmt::{Display, Formatter };
use std::io::Write;
enum Command { pub enum Command {
Unknown, Unknown,
Set(String, Box<dyn Display>), Set(String, StoredData),
Push(String, Box<dyn Display>), Define(String, LiteMap<String, StoredData>),
Push(String, StoredData),
Display(String),
SetOutput(fn() -> Box<dyn Write>),
} }
struct Line{ #[derive(Clone)]
data: Vec<Box<dyn Display>>, pub enum StoredData {
Integer(isize),
Float(f64),
String(String),
Bool(bool),
Line(Line),
Vec(Vec<StoredData>),
} }
impl From<Vec<Box<dyn Display>>> for Line { impl Display for StoredData {
fn from(value: Vec<Box<dyn Display>>) -> Self { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Self{data: value} 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 }
} }
} }
impl Display for Line { impl Display for Line {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}]", self.data.iter().map(|i| i.to_string()).collect::<Vec<String>>().join(", ")) write!(
f,
"[{}]",
self.data
.iter()
.map(|i| i.to_string())
.collect::<Vec<String>>()
.join(", ")
)
} }
} }
@@ -40,7 +84,7 @@ fn parse_command(data: &[u8]) -> Result<Command, Error> {
decoder.array()?; decoder.array()?;
let id = decoder.str()?.to_string(); let id = decoder.str()?.to_string();
let value = decode_value(&mut decoder)?; let value = decode_value(&mut decoder)?;
return Ok(Command::Set(id, value)) return Ok(Command::Set(id, value));
} }
if data.starts_with(b"PUSH:") { if data.starts_with(b"PUSH:") {
let payload = &data[b"PUSH:".len()..]; let payload = &data[b"PUSH:".len()..];
@@ -48,32 +92,41 @@ fn parse_command(data: &[u8]) -> Result<Command, Error> {
decoder.array()?; decoder.array()?;
let id = decoder.str()?.to_string(); let id = decoder.str()?.to_string();
let value = decode_value(&mut decoder)?; let value = decode_value(&mut decoder)?;
return Ok(Command::Push(id, value)) 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));
} }
Ok(Command::Unknown) Ok(Command::Unknown)
} }
fn decode_value(decoder: &mut Decoder) -> Result<Box<dyn Display>, Error> { fn decode_value(decoder: &mut Decoder) -> Result<StoredData, Error> {
Ok(match decoder.datatype()? { Ok(match decoder.datatype()? {
Type::Bool => Box::new(decoder.bool()?), Type::Bool => StoredData::Bool(decoder.bool()?),
Type::U8 => Box::new(decoder.u8()? as isize), Type::U8 => StoredData::Integer(decoder.u8()? as isize),
Type::U16 => Box::new(decoder.u16()? as isize), Type::U16 => StoredData::Integer(decoder.u16()? as isize),
Type::U32 => Box::new(decoder.u32()? as isize), Type::U32 => StoredData::Integer(decoder.u32()? as isize),
Type::U64 => Box::new(decoder.u64()? as isize), Type::U64 => StoredData::Integer(decoder.u64()? as isize),
Type::I8 => Box::new(decoder.i8()? as isize), Type::I8 => StoredData::Integer(decoder.i8()? as isize),
Type::I16 => Box::new(decoder.i16()? as isize), Type::I16 => StoredData::Integer(decoder.i16()? as isize),
Type::I32 => Box::new(decoder.i32()? as isize), Type::I32 => StoredData::Integer(decoder.i32()? as isize),
Type::I64 => Box::new(decoder.i64()? as isize), Type::I64 => StoredData::Integer(decoder.i64()? as isize),
Type::Int => Box::new(decoder.i32()? as isize), Type::Int => StoredData::Integer(decoder.i32()? as isize),
Type::F16 => Box::new(decoder.f32()? as f64), Type::F16 => StoredData::Float(decoder.f32()? as f64),
Type::F32 => Box::new(decoder.f32()? as f64), Type::F32 => StoredData::Float(decoder.f32()? as f64),
Type::F64 => Box::new(decoder.f64()?), Type::F64 => StoredData::Float(decoder.f64()?),
Type::String | Type::String | Type::StringIndef => StoredData::String(decoder.str()?.to_string()),
Type::StringIndef => Box::new(decoder.str()?.to_string()), Type::Array | Type::ArrayIndef => {
Type::Array |
Type::ArrayIndef => {
let len = decoder.array()?; let len = decoder.array()?;
let mut array = if let Some(len) = len { Vec::with_capacity(len as usize) } else { vec![] }; let mut array = if let Some(len) = len {
Vec::with_capacity(len as usize)
} else {
vec![]
};
if array.is_empty() { if array.is_empty() {
loop { loop {
let dt = decoder.datatype()?; let dt = decoder.datatype()?;
@@ -83,12 +136,25 @@ fn decode_value(decoder: &mut Decoder) -> Result<Box<dyn Display>, Error> {
array.push(decode_value(decoder)?); array.push(decode_value(decoder)?);
} }
} }
Box::new(Line::from(array)) StoredData::Line(Line::from(array))
}
_ => {
decoder.skip()?;
StoredData::Bool(false)
} }
_ => { decoder.skip()?; Box::new(false)}
}) })
} }
struct NoteContext { pub struct NoteContext {
entries: HashMap<String, Box<dyn Any>>, entries: HashMap<String, StoredData>,
} output: Box<dyn Write>,
}
impl NoteContext {
pub fn default() -> Self {
Self{
entries: Default::default(),
output: Box::new(std::io::stdout()),
}
}
}
+5
View File
@@ -0,0 +1,5 @@
#[cfg(test)]
mod test {
#[test]
fn x() {}
}