libhans 0.1.11

Rust bindings for the Hans robot
Documentation
use std::{any::type_name, default};

use robot_behavior::{RobotException, RobotResult, deserialize_error};

use crate::robot_error::RobotError;

pub trait CommandSerde: Sized {
    fn to_string(&self) -> String;
    fn from_str(data: &str) -> RobotResult<Self>;
    fn try_default() -> Self;
    fn num_args() -> usize {
        1
    }
}

impl CommandSerde for RobotError {
    fn to_string(&self) -> String {
        serde_json::to_string(self).unwrap()
    }
    fn from_str(data: &str) -> RobotResult<Self> {
        serde_json::from_str(data).map_err(deserialize_error::<RobotError, _>(data))
    }
    fn try_default() -> Self {
        Self::default()
    }
}

impl CommandSerde for () {
    fn to_string(&self) -> String {
        String::new()
    }
    fn from_str(_: &str) -> RobotResult<Self> {
        Ok(())
    }
    fn try_default() -> Self {}
    fn num_args() -> usize {
        0
    }
}

impl CommandSerde for bool {
    fn to_string(&self) -> String {
        format!("{}", i32::from(*self))
    }

    fn from_str(data: &str) -> RobotResult<Self> {
        match data {
            "0" => Ok(false),
            "1" => Ok(true),
            _ => Err(deserialize_error::<bool, _>(data)(())),
        }
    }

    fn try_default() -> Self {
        false
    }
}

impl CommandSerde for u8 {
    fn to_string(&self) -> String {
        format!("{self}")
    }
    fn from_str(data: &str) -> RobotResult<Self> {
        data.parse().map_err(deserialize_error::<u8, _>(data))
    }
    fn try_default() -> Self {
        0
    }
}

impl CommandSerde for u16 {
    fn to_string(&self) -> String {
        format!("{self}")
    }
    fn from_str(data: &str) -> RobotResult<Self> {
        data.parse().map_err(deserialize_error::<u16, _>(data))
    }
    fn try_default() -> Self {
        0
    }
}

impl CommandSerde for f64 {
    fn to_string(&self) -> String {
        format!("{self}")
    }
    fn from_str(data: &str) -> RobotResult<Self> {
        data.parse().map_err(deserialize_error::<f64, _>(data))
    }
    fn try_default() -> Self {
        0.0
    }
}

impl<T1, T2> CommandSerde for (T1, T2)
where
    T1: CommandSerde,
    T2: CommandSerde,
{
    fn to_string(&self) -> String {
        format!("{},{}", self.0.to_string(), self.1.to_string())
    }
    fn from_str(data: &str) -> RobotResult<Self> {
        let mut data = data.split(',');
        Ok((
            T1::from_str(data.next().unwrap())?,
            T2::from_str(data.next().unwrap())?,
        ))
    }
    fn try_default() -> Self {
        (T1::try_default(), T2::try_default())
    }
    fn num_args() -> usize {
        2
    }
}

impl<T1, T2, T3> CommandSerde for (T1, T2, T3)
where
    T1: CommandSerde,
    T2: CommandSerde,
    T3: CommandSerde,
{
    fn to_string(&self) -> String {
        format!(
            "{},{},{}",
            self.0.to_string(),
            self.1.to_string(),
            self.2.to_string()
        )
    }
    fn from_str(data: &str) -> RobotResult<Self> {
        let mut data = data.split(',');
        Ok((
            T1::from_str(data.next().unwrap())?,
            T2::from_str(data.next().unwrap())?,
            T3::from_str(data.next().unwrap())?,
        ))
    }
    fn try_default() -> Self {
        (T1::try_default(), T2::try_default(), T3::try_default())
    }
    fn num_args() -> usize {
        3
    }
}

impl<const N: usize, T> CommandSerde for [T; N]
where
    T: CommandSerde + Copy,
{
    fn to_string(&self) -> String {
        self.iter()
            .map(CommandSerde::to_string)
            .collect::<Vec<_>>()
            .join(",")
    }
    fn from_str(data: &str) -> RobotResult<Self> {
        let try_data = data
            .split(',')
            .map(|x| T::from_str(x).unwrap())
            .collect::<Vec<T>>()
            .try_into()
            .map_err(deserialize_error::<[T; N], _>(data))?;
        Ok(try_data)
    }
    fn try_default() -> Self {
        [T::try_default(); N]
    }
    fn num_args() -> usize {
        N
    }
}

impl CommandSerde for String {
    fn to_string(&self) -> String {
        self.clone()
    }
    fn from_str(data: &str) -> RobotResult<Self> {
        Ok(data.to_string())
    }
    fn try_default() -> Self {
        String::new()
    }
}