From 7e67f6bfa895005bb819ab9982765fa86d03ea05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20B=C3=A1cskai?= <45177246+Kris030@users.noreply.github.com> Date: Thu, 27 Jul 2023 08:50:08 +0200 Subject: [PATCH] Dump Concr --- client/src/transports/http.rs | 73 +------- client/src/transports/tcp.rs | 4 +- client/src/transports/udp.rs | 4 +- roblib/src/cmd/concrete.rs | 319 ++------------------------------ roblib/src/text_format/error.rs | 6 + roblib/src/text_format/ser.rs | 11 ++ server/src/transports/udp.rs | 3 +- 7 files changed, 41 insertions(+), 379 deletions(-) diff --git a/client/src/transports/http.rs b/client/src/transports/http.rs index aebffc3..40625a5 100644 --- a/client/src/transports/http.rs +++ b/client/src/transports/http.rs @@ -24,13 +24,13 @@ impl Transport for Http { C: Command, C::Return: Send + 'static, { - let concrete: cmd::Concrete = cmd.into(); + let cmd = cmd::concrete::Concr::new(cmd.into()); let body = self.runtime.block_on(async { let req = self .client .post(&self.base_url) - .send_body(concrete.to_string()) + .send_body(cmd.to_string()) .await; let mut res = match req { @@ -50,72 +50,3 @@ impl Transport for Http { Ok(roblib::text_format::de::from_str(&body)?) } } - -// #[cfg(feature = "async")] -// pub struct HttpAsync { -// handle: futures::lock::Mutex>>>, -// tx_cmd: futures::lock::Mutex>, -// rx_res: futures::lock::Mutex>, -// } - -// #[cfg(feature = "async")] -// impl HttpAsync { -// pub async fn new(base_url: &str) -> anyhow::Result { -// let url = format!("{base_url}/cmd"); - -// let (tx_cmd, rx_cmd) = futures::channel::mpsc::unbounded(); -// let (tx_res, rx_res) = futures::channel::mpsc::unbounded(); - -// Ok(Self { -// handle: Some(actix_rt::spawn(Self::run(url, rx_cmd, tx_res))).into(), -// tx_cmd: tx_cmd.into(), -// rx_res: rx_res.into(), -// }) -// } - -// async fn run( -// url: String, -// mut rx_cmd: futures::channel::mpsc::UnboundedReceiver, -// mut tx_res: futures::channel::mpsc::UnboundedSender, -// ) -> anyhow::Result<()> { -// use futures_util::{SinkExt, StreamExt}; - -// let client = Client::default(); - -// while let Some(cmd) = rx_cmd.next().await { -// let req = client.post(&url).send_body(cmd.to_string()); -// let mut res = match req.await { -// Ok(r) => r, -// Err(e) => return Err(anyhow::Error::msg(e.to_string())), -// }; - -// let body = res.body().await?; -// let body = String::from_utf8(body.to_vec())?; - -// tx_res.send(body).await?; -// } - -// Ok(()) -// } -// } - -// #[cfg(feature = "async")] -// #[cfg_attr(feature = "async", async_trait::async_trait)] -// impl<'a> super::TransportAsync<'a> for HttpAsync { -// async fn cmd_async + Send>(&self, cmd: C) -> anyhow::Result { -// use futures_util::{SinkExt, StreamExt}; - -// self.tx_cmd.lock().await.send(cmd.into()).await?; - -// let Some(res) = self.rx_res.lock().await.next().await else { -// if let Some(r) = self.handle.lock().await.take() { -// r.await??; -// unreachable!("HTTP client terminated without error???") -// } else { -// return Err(anyhow::Error::msg("HTTP client already terminated")); -// } -// }; - -// Ok(roblib::text_format::de::from_str(&res)?) -// } -// } diff --git a/client/src/transports/tcp.rs b/client/src/transports/tcp.rs index 1af4dfd..d24f40a 100644 --- a/client/src/transports/tcp.rs +++ b/client/src/transports/tcp.rs @@ -72,10 +72,10 @@ impl Transport for Tcp { C: roblib::cmd::Command, C::Return: Send + 'static, { - let concrete: cmd::Concrete = cmd.into(); + let cmd = cmd::concrete::Concr::new(cmd.into()); let mut id_handle = self.id.lock().unwrap(); - bincode::serialize_into(&self.socket, &(*id_handle, concrete))?; + bincode::serialize_into(&self.socket, &(*id_handle, cmd))?; *id_handle += 1; diff --git a/client/src/transports/udp.rs b/client/src/transports/udp.rs index bddfc99..1ca4a4d 100644 --- a/client/src/transports/udp.rs +++ b/client/src/transports/udp.rs @@ -82,8 +82,8 @@ impl Transport for Udp { let id = *id_handle; *id_handle = id + 1; - let concrete: cmd::Concrete = cmd.into(); - self.sock.send(&bincode::serialize(&(id, concrete))?)?; + let cmd = cmd::concrete::Concr::new(cmd.into()); + self.sock.send(&bincode::serialize(&(id, cmd))?)?; Ok(if has_return::() { let (tx, rx) = std::sync::mpsc::sync_channel(1); diff --git a/roblib/src/cmd/concrete.rs b/roblib/src/cmd/concrete.rs index 4417f14..ae58d14 100644 --- a/roblib/src/cmd/concrete.rs +++ b/roblib/src/cmd/concrete.rs @@ -1,19 +1,26 @@ use std::fmt::Display; -use serde::{ - de::{self, SeqAccess, Visitor}, - ser::SerializeStruct, - Deserialize, Serialize, -}; +use serde::{Deserialize, Serialize}; use crate::cmd::{self, Command}; #[derive(Serialize, Deserialize)] pub struct Concr { - pub id: u32, + pub prefix: char, pub cmd: Concrete, } +impl Concr { + pub fn new(cmd: Concrete) -> Self { + Self { + prefix: cmd.get_prefix(), + cmd, + } + } +} + +#[derive(Serialize, Deserialize)] +#[serde(untagged)] pub enum Concrete { #[cfg(feature = "roland")] MoveRobot(cmd::MoveRobot), @@ -137,302 +144,8 @@ impl Concrete { } } -impl Serialize for Concrete { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self { - #[cfg(feature = "roland")] - Self::MoveRobot(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::MoveRobot::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "roland")] - Self::MoveRobotByAngle(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::MoveRobotByAngle::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "roland")] - Self::StopRobot(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::StopRobot::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "roland")] - Self::Led(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::Led::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "roland")] - Self::RolandServo(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::RolandServo::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "roland")] - Self::Buzzer(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::Buzzer::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "roland")] - Self::TrackSensor(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::TrackSensor::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "roland")] - Self::UltraSensor(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::UltraSensor::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - - #[cfg(feature = "gpio")] - Self::PinMode(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::PinMode::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "gpio")] - Self::ReadPin(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::ReadPin::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "gpio")] - Self::WritePin(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::WritePin::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "gpio")] - Self::Pwm(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::Pwm::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - #[cfg(feature = "gpio")] - Self::Servo(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::Servo::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - - #[cfg(feature = "camloc")] - Self::GetPosition(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::GetPosition::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - - Self::Subscribe(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::Subscribe::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - Self::Unsubscribe(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::Unsubscribe::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - Self::Nop(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::Nop::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - Self::GetUptime(c) => { - let mut s = serializer.serialize_struct("Concrete", 2)?; - s.serialize_field("prefix", &cmd::GetUptime::PREFIX)?; - s.serialize_field("cmd", &c)?; - s.end() - } - } - } -} -impl<'de> Deserialize<'de> for Concrete { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - struct ConcreteVisitor; - impl<'de> Visitor<'de> for ConcreteVisitor { - type Value = Concrete; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a prefix and a command body") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - let prefix: char = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - - match prefix { - #[cfg(feature = "roland")] - cmd::MoveRobot::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::MoveRobot(cmd)) - } - #[cfg(feature = "roland")] - cmd::MoveRobotByAngle::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::MoveRobotByAngle(cmd)) - } - #[cfg(feature = "roland")] - cmd::StopRobot::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::StopRobot(cmd)) - } - #[cfg(feature = "roland")] - cmd::Led::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::Led(cmd)) - } - #[cfg(feature = "roland")] - cmd::RolandServo::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::RolandServo(cmd)) - } - #[cfg(feature = "roland")] - cmd::Buzzer::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::Buzzer(cmd)) - } - #[cfg(feature = "roland")] - cmd::TrackSensor::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::TrackSensor(cmd)) - } - #[cfg(feature = "roland")] - cmd::UltraSensor::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::UltraSensor(cmd)) - } - - #[cfg(feature = "gpio")] - cmd::PinMode::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::PinMode(cmd)) - } - #[cfg(feature = "gpio")] - cmd::ReadPin::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::ReadPin(cmd)) - } - #[cfg(feature = "gpio")] - cmd::WritePin::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::WritePin(cmd)) - } - #[cfg(feature = "gpio")] - cmd::Pwm::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::Pwm(cmd)) - } - #[cfg(feature = "gpio")] - cmd::Servo::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::Servo(cmd)) - } - - #[cfg(feature = "camloc")] - cmd::GetPosition::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::GetPosition(cmd)) - } - - cmd::Subscribe::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::Subscribe(cmd)) - } - cmd::Unsubscribe::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::Unsubscribe(cmd)) - } - cmd::Nop::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::Nop(cmd)) - } - cmd::GetUptime::PREFIX => { - let cmd = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(Concrete::GetUptime(cmd)) - } - - _ => Err(de::Error::invalid_value( - de::Unexpected::Char(prefix), - &"a command prefix", - )), - } - } - } - - deserializer.deserialize_struct("Concrete", &["prefix", "cmd"], ConcreteVisitor) - } -} - -impl Display for Concrete { - fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - todo!() +impl Display for Concr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + crate::text_format::ser::write(self, f) } } diff --git a/roblib/src/text_format/error.rs b/roblib/src/text_format/error.rs index ed3681f..84c8063 100644 --- a/roblib/src/text_format/error.rs +++ b/roblib/src/text_format/error.rs @@ -56,3 +56,9 @@ impl From for Error { Self::FormatterError(value) } } + +impl From for fmt::Error { + fn from(_: Error) -> Self { + Self + } +} diff --git a/roblib/src/text_format/ser.rs b/roblib/src/text_format/ser.rs index 789ea37..45ca4b3 100644 --- a/roblib/src/text_format/ser.rs +++ b/roblib/src/text_format/ser.rs @@ -7,6 +7,17 @@ use serde::{ }; use std::fmt::{self, Write}; +pub fn to_string(val: impl Serialize) -> Result { + let mut s = String::new(); + val.serialize(&mut Serializer::new(&mut s))?; + Ok(s) +} + +pub fn write(val: impl Serialize, w: impl Write) -> fmt::Result { + val.serialize(&mut Serializer::new(w))?; + Ok(()) +} + pub struct Serializer { first: bool, writer: W, diff --git a/server/src/transports/udp.rs b/server/src/transports/udp.rs index 49ac1b5..3db2ec3 100644 --- a/server/src/transports/udp.rs +++ b/server/src/transports/udp.rs @@ -37,7 +37,8 @@ async fn run(server: UdpSocket, robot: Arc) -> Result<()> { loop { let (len, addr) = server.recv_from(&mut buf).await?; - let (id, cmd): (u32, cmd::Concrete) = bincode::deserialize(&buf[..len])?; + let (id, cmd): (u32, cmd::concrete::Concr) = bincode::deserialize(&buf[..len])?; + let cmd = cmd.cmd; match cmd { cmd::Concrete::Subscribe(c) => {