From 8749cbdad7e7492d878542c17b7762b618c30ba6 Mon Sep 17 00:00:00 2001 From: scbj Date: Mon, 8 Sep 2025 16:13:23 +0200 Subject: [PATCH] (rust) macaddress type tests --- rust/src/main.rs | 257 +++++++++++------------------------------------ 1 file changed, 57 insertions(+), 200 deletions(-) diff --git a/rust/src/main.rs b/rust/src/main.rs index ee233a7..66ec266 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,224 +1,81 @@ #![allow(dead_code, unused)] -use std::{num, path::PathBuf, str::FromStr}; - -use chrono::{DateTime, Local, Utc}; -use ciborium::ser; -use dirs::{config_dir, home_dir}; use serde::{Deserialize, Serialize}; -use tokio::{ - fs, - io::{AsyncReadExt, AsyncWriteExt}, - net::{TcpListener, TcpStream}, - sync::{ - mpsc::{channel, Receiver, Sender}, - Mutex, - }, - time::{sleep, Duration}, -}; -#[tokio::main] -async fn main() -> anyhow::Result<()> { - let (running, mut stop) = channel::(1); +fn main() -> anyhow::Result<()> { + let test_address: MacAddress = MacAddress::from_array([0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F]); - let send_handle = tokio::spawn(sender_process(running.clone())); - let recv_handle = tokio::spawn(receiver_process()); - - _ = recv_handle.await??; - stop.close(); - _ = send_handle.await??; + println!("as string: {}", test_address.to_string()); Ok(()) } -async fn sender_process(running: Sender) -> anyhow::Result<()> { - const BLOCK_SIZE: usize = 128; - const FILE_PATH: &str = "repositories/test-projects/"; - const FILE_NAME: &str = "small-lorem.md"; - - let listener: TcpListener = TcpListener::bind("127.0.0.1:9090").await?; - let mut connection = match listener.accept().await { - Ok((mut stream, address)) => { - println!("accepted connection request from {}", address); - stream - } - Err(error) => { - println!("this is unexpected.. {}", error.to_string()); - return Err(std::io::Error::other("failed to open tcp connection").try_into()?); - } - }; - - let mut filepath: PathBuf = home_dir().expect("failed to determine home directory"); - let mut buffer: Vec = Vec::new(); - - filepath.push(FILE_PATH); - filepath.push(FILE_NAME); - - let mut file: Vec = match fs::read(filepath).await { - Ok(value) => value, - Err(error) => { - println!("{}", error.to_string()); - panic!("failed to read file"); - } - }; - let length: usize = file.len(); - let blocks: usize = if length % BLOCK_SIZE == 0 { - length / BLOCK_SIZE - } else { - (length / BLOCK_SIZE) + 1 - }; - let mut index: usize = 0; - - connection.writable().await; - while index < blocks { - if index >= blocks { - panic!("index >= blocks !@#$!%"); - } - let end_index: usize = if file.len() < BLOCK_SIZE { - file.len() - } else { - BLOCK_SIZE - }; - let message: Message = Message::FileSection(FileSection { - name: "lorem.md".to_owned(), - size: length as u64, - sections: blocks as u64, - index: index as u64, - data: file.drain(0..end_index).collect(), - }); - let serialised: Vec = message.to_vec(); - connection.try_write(&serialised[..]); - index += 1; - - sleep(Duration::from_millis(20)).await; - } - println!("send loop done"); - - while !running.is_closed() { - sleep(Duration::from_millis(20)).await; - } - - println!("send loop exiting -> dropping connection"); - - Ok(()) +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct MacAddress { + bytes: [u8;6], } -async fn receiver_process() -> anyhow::Result<()> { - let mut connection = TcpStream::connect("127.0.0.1:9090").await?; - let mut buffer: Vec = Vec::with_capacity(8192); - let mut file: Vec = Vec::new(); - let mut index: usize = 0; - let mut blocks: usize = 0; - let mut name: String = "".to_owned(); - let mut counter: usize = 3; +impl MacAddress { + pub fn new() -> Self { + Self { + bytes: [0u8;6], + } + } - 'receive: loop { - sleep(Duration::from_millis(20)).await; - if counter > 0 || buffer.is_empty() { - connection.readable().await; - let num_bytes: usize = match connection.read_buf(&mut buffer).await { - Ok(0) => { - println!("connection dropped ........."); - break 'receive; - } + pub fn from_array(bytes: [u8;6]) -> Self { + Self { + bytes: bytes, + } + } + + pub fn from_str(string: &str) -> std::io::Result { + let mut address: Self = Self::new(); + let bytes: Vec<&str> = string.split(":").collect(); + + if bytes.len() != address.bytes.len() { + return Err(std::io::Error::other("invalid length or format for mac address")); + } + + for (index, byte) in bytes.iter().enumerate() { + address.bytes[index] = match u8::from_str_radix(byte, 16) { Ok(value) => value, - Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => continue 'receive, - Err(_) => panic!("fuck you!"), + Err(error) => return Err(std::io::Error::other(error.to_string())), }; } - if counter > 0 { - counter -= 1; - continue 'receive; - } - - let message: FileSection = match Message::from_vec(&mut buffer) { - Ok(Message::FileSection(value)) => value, - Ok(unexpected) => panic!(".. {:#?}", unexpected), - Err(Error::IncompleteFrame) => continue 'receive, - Err(Error::EmptyBuffer) => panic!("don't be stupid!"), - Err(error) => panic!(".. {:#?}", error), - }; - - if blocks == 0 { - blocks = message.sections as usize; - name = message.name; - } - index = message.index as usize; - - file.extend(message.data); - - if index >= blocks - 1 { - break 'receive; - }; - } - println!("decoding done"); - println!("receive loop done"); - - fs::write("./received.md", file).await; - - Ok(()) -} - -type FileName = String; - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum Message { - Acknowledge(bool), - FileRequest(FileName), - FileSection(FileSection), -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct FileSection { - pub name: String, - pub size: u64, - pub sections: u64, - pub index: u64, - pub data: Vec, -} - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("serialisation with cbor failed")] - Serialisation(#[from] ciborium::de::Error), - - #[error("framing with cobs failed")] - Framing(#[from] cobs::DecodeError), - - #[error("can't deserialise from an empty buffer")] - EmptyBuffer, - - #[error("no framedelimiter found, the frame is probably not fully received yet")] - IncompleteFrame, -} - -impl Message { - /// serialises the message and returns a vector of `u8` - pub fn to_vec(&self) -> Vec { - let mut serialised: Vec = Vec::with_capacity(1024); - _ = ciborium::into_writer(self, &mut serialised); - let mut framed: Vec = cobs::encode_vec(&serialised); - framed.push(0x00u8); - framed + Ok(address) } - /// deserialises a message from a vector - pub fn from_vec(buffer: &mut Vec) -> Result { - if buffer.is_empty() { return Err(Error::EmptyBuffer); } - if !buffer.contains(&0u8) { return Err(Error::IncompleteFrame); } + pub fn from_string(string: &String) -> std::io::Result { + let mut address: Self = Self::new(); + let bytes: Vec<&str> = string.split(":").collect(); - let mut index: usize = 0; - for (n, byte) in buffer.iter().enumerate() { - if byte == &0u8 { - index = n; - break; + println!("debug: {:#?}", bytes); + + if bytes.len() != address.bytes.len() { + return Err(std::io::Error::other("invalid length or format for mac address")); + } + + for (index, byte) in bytes.iter().enumerate() { + address.bytes[index] = match u8::from_str_radix(byte, 16) { + Ok(value) => value, + Err(error) => return Err(std::io::Error::other(error.to_string())), + }; + } + + Ok(address) + } + + pub fn to_string(&self) -> String { + let mut string: String = String::new(); + + for (index, byte) in self.bytes.iter().enumerate() { + string.push_str(&format!("{:02x?}", byte)); + if index < self.bytes.len() - 1 { + string.push_str(":"); } } - let serialised: Vec = cobs::decode_vec(&buffer.drain(0..=index).collect::>())?; - let message: Message = ciborium::from_reader(&serialised[..])?; - - Ok(message) + string } }