#![forbid(unsafe_code)]
use serde::{
de::{Deserializer, EnumAccess, Error, VariantAccess, Visitor},
Deserialize,
};
use std::{fmt, marker::PhantomData};
use super::constants;
#[derive(Clone, Debug)]
pub enum Response {
Hello { version: u32 },
Alive { response_id: u32, server_pid: u32 },
Ok { response_id: u32 },
Failure { response_id: u32, reason: Box<str> },
PermissionDenied { response_id: u32, reason: Box<str> },
SessionOpened { response_id: u32, session_id: u32 },
ExitMessage { session_id: u32, exit_value: u32 },
TtyAllocFail { session_id: u32 },
RemotePort { response_id: u32, remote_port: u32 },
}
impl<'de> Deserialize<'de> for Response {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_enum(
"Response",
&[
"Hello",
"Alive",
"Ok",
"Failure",
"PermissionDenied",
"SessionOpened",
"ExitMessage",
"TtyAllocFail",
"RemotePort",
],
ResponseVisitor,
)
}
}
struct ResponseVisitor;
impl<'de> Visitor<'de> for ResponseVisitor {
type Value = Response;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "expecting Response")
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
use constants::*;
let result: (u32, _) = data.variant()?;
let (index, accessor) = result;
match index {
MUX_MSG_HELLO => {
let version: u32 = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::Hello { version })
}
MUX_S_ALIVE => {
let tup: (u32, u32) = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::Alive {
response_id: tup.0,
server_pid: tup.1,
})
}
MUX_S_OK => {
let response_id: u32 = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::Ok { response_id })
}
MUX_S_FAILURE => {
let tup: (u32, Box<str>) = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::Failure {
response_id: tup.0,
reason: tup.1,
})
}
MUX_S_PERMISSION_DENIED => {
let tup: (u32, Box<str>) = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::PermissionDenied {
response_id: tup.0,
reason: tup.1,
})
}
MUX_S_SESSION_OPENED => {
let tup: (u32, u32) = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::SessionOpened {
response_id: tup.0,
session_id: tup.1,
})
}
MUX_S_EXIT_MESSAGE => {
let tup: (u32, u32) = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::ExitMessage {
session_id: tup.0,
exit_value: tup.1,
})
}
MUX_S_TTY_ALLOC_FAIL => {
let session_id: u32 = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::TtyAllocFail { session_id })
}
MUX_S_REMOTE_PORT => {
let tup: (u32, u32) = accessor.newtype_variant_seed(PhantomData)?;
Ok(Response::RemotePort {
response_id: tup.0,
remote_port: tup.1,
})
}
_ => Err(A::Error::custom("Unexpected packet type")),
}
}
}