lay_mitouosc/
message.rs

1use std::convert::{From, TryFrom};
2
3use rosc::{OscMessage, OscType};
4use thiserror::Error;
5
6#[derive(Debug, Clone, Error)]
7pub enum MessageError {
8    #[error("Invalid address `{0}`")]
9    InvalidAddr(String),
10    #[error("Invalid arguments")]
11    InvalidArgs,
12}
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum Request {
16    InitZero(i32, i32),
17    X(i32, i32),
18    Y(i32, i32),
19    Z(i32, i32),
20    H(i32, i32),
21    S(i32, i32),
22    Sdg(i32, i32),
23    T(i32, i32),
24    Tdg(i32, i32),
25    CX(i32, i32, i32, i32),
26    Mz(i32, i32),
27}
28
29impl TryFrom<OscMessage> for Request {
30    type Error = anyhow::Error;
31
32    fn try_from(msg: OscMessage) -> anyhow::Result<Request> {
33        let OscMessage { addr, args } = msg;
34        let args = args.into_iter()
35                       .map(|x| x.int().ok_or(MessageError::InvalidArgs))
36                       .collect::<Result<Vec<_>, _>>()?;
37        let get = |n: usize| args.get(n).map(|x| *x).ok_or(MessageError::InvalidArgs);
38        match addr.as_str() {
39            "/InitZero" => Ok(Request::InitZero(get(0)?, get(1)?)),
40            "/X" => Ok(Request::X(get(0)?, get(1)?)),
41            "/Y" => Ok(Request::Y(get(0)?, get(1)?)),
42            "/Z" => Ok(Request::Z(get(0)?, get(1)?)),
43            "/H" => Ok(Request::H(get(0)?, get(1)?)),
44            "/S" => Ok(Request::S(get(0)?, get(1)?)),
45            "/Sdg" => Ok(Request::Sdg(get(0)?, get(1)?)),
46            "/T" => Ok(Request::T(get(0)?, get(1)?)),
47            "/Tdg" => Ok(Request::Tdg(get(0)?, get(1)?)),
48            "/CX" => Ok(Request::CX(get(0)?, get(1)?, get(2)?, get(3)?)),
49            "/Mz" => Ok(Request::Mz(get(0)?, get(1)?)),
50            _ => Err(MessageError::InvalidAddr(addr).into())
51        }
52    }
53}
54
55impl From<&Request> for OscMessage {
56    fn from(msg: &Request) -> OscMessage {
57        match msg {
58            Request::InitZero(n1, n2) => OscMessage { addr: "/InitZero".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
59            Request::X(n1, n2) => OscMessage { addr: "/X".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
60            Request::Y(n1, n2) => OscMessage { addr: "/Y".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
61            Request::Z(n1, n2) => OscMessage { addr: "/Z".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
62            Request::H(n1, n2) => OscMessage { addr: "/H".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
63            Request::S(n1, n2) => OscMessage { addr: "/S".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
64            Request::Sdg(n1, n2) => OscMessage { addr: "/Sdg".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
65            Request::T(n1, n2) => OscMessage { addr: "/T".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
66            Request::Tdg(n1, n2) => OscMessage { addr: "/Tdg".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
67            Request::CX(n1, n2, n3, n4) => OscMessage { addr: "/CX".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2), OscType::Int(*n3), OscType::Int(*n4)] },
68            Request::Mz(n1, n2) => OscMessage { addr: "/Mz".to_owned(), args: vec![OscType::Int(*n1), OscType::Int(*n2)] },
69        }
70    }
71}
72
73#[derive(Debug, Clone, PartialEq)]
74pub enum Response {
75    Mz(i32, f32),
76}
77
78impl TryFrom<OscMessage> for Response {
79    type Error = anyhow::Error;
80
81    fn try_from(msg: OscMessage) -> anyhow::Result<Response> {
82        let OscMessage { addr, args } = msg;
83        match addr.as_str() {
84            "/Mz" => Ok(Response::Mz(args.get(0).and_then(|x| x.clone().int()).ok_or(MessageError::InvalidArgs)?,
85                                     args.get(1).and_then(|x| x.clone().float()).ok_or(MessageError::InvalidArgs)?)),
86            _ => Err(MessageError::InvalidAddr(addr).into())
87        }
88    }
89}
90
91impl From<&Response> for OscMessage {
92    fn from(msg: &Response) -> OscMessage {
93        match msg {
94            Response::Mz(n1, f1) => OscMessage { addr: "/Mz".to_owned(), args: vec![OscType::Int(*n1), OscType::Float(*f1)] },
95        }
96    }
97}