use crate::{Error, Result};
use std::fmt::{self, Display};
use tor_cell::chancell::{
msg::{self as chanmsg, AnyChanMsg},
ChanMsg,
};
#[cfg_attr(docsrs, doc(cfg(feature = "testing")))]
#[derive(Debug)]
#[allow(unreachable_pub)] #[allow(clippy::exhaustive_enums)]
pub enum CreateResponse {
Destroy(chanmsg::Destroy),
CreatedFast(chanmsg::CreatedFast),
Created2(chanmsg::Created2),
}
impl Display for CreateResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use CreateResponse as CR;
match self {
CR::Destroy(destroy) => write!(f, "DESTROY({})", destroy.reason()),
CR::CreatedFast(_) => Display::fmt("CREATED_FAST", f),
CR::Created2(_) => Display::fmt("CREATED2", f),
}
}
}
impl TryFrom<AnyChanMsg> for CreateResponse {
type Error = crate::Error;
fn try_from(m: AnyChanMsg) -> Result<CreateResponse> {
match m {
AnyChanMsg::Destroy(m) => Ok(CreateResponse::Destroy(m)),
AnyChanMsg::CreatedFast(m) => Ok(CreateResponse::CreatedFast(m)),
AnyChanMsg::Created2(m) => Ok(CreateResponse::Created2(m)),
_ => Err(Error::ChanProto(format!(
"Got a {} in response to circuit creation",
m.cmd()
))),
}
}
}
#[derive(Debug)]
#[allow(unreachable_pub)] pub enum ClientCircChanMsg {
Relay(chanmsg::Relay),
Destroy(chanmsg::Destroy),
}
impl TryFrom<AnyChanMsg> for ClientCircChanMsg {
type Error = crate::Error;
fn try_from(m: AnyChanMsg) -> Result<ClientCircChanMsg> {
match m {
AnyChanMsg::Destroy(m) => Ok(ClientCircChanMsg::Destroy(m)),
AnyChanMsg::Relay(m) => Ok(ClientCircChanMsg::Relay(m)),
_ => Err(Error::ChanProto(format!(
"Got a {} cell on an open circuit",
m.cmd()
))),
}
}
}
#[cfg(test)]
mod test {
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::mixed_attributes_style)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::unchecked_duration_subtraction)]
#![allow(clippy::useless_vec)]
#![allow(clippy::needless_pass_by_value)]
use super::*;
#[test]
fn create_response() {
use tor_cell::chancell::msg::{self, AnyChanMsg};
fn good(m: AnyChanMsg) {
assert!(CreateResponse::try_from(m).is_ok());
}
fn bad(m: AnyChanMsg) {
assert!(CreateResponse::try_from(m).is_err());
}
good(msg::Destroy::new(2.into()).into());
good(msg::CreatedFast::new(&b"this offer is unrepeatable"[..]).into());
good(msg::Created2::new(&b"guaranteed guaranteed"[..]).into());
bad(msg::CreateFast::new(&b"for a lifetime or more"[..]).into());
bad(msg::Versions::new([1, 2, 3]).unwrap().into());
}
#[test]
fn client_circ_chan_msg() {
use tor_cell::chancell::msg::{self, AnyChanMsg};
fn good(m: AnyChanMsg) {
assert!(ClientCircChanMsg::try_from(m).is_ok());
}
fn bad(m: AnyChanMsg) {
assert!(ClientCircChanMsg::try_from(m).is_err());
}
good(msg::Destroy::new(2.into()).into());
bad(msg::CreatedFast::new(&b"guaranteed in this world"[..]).into());
bad(msg::Created2::new(&b"and the next"[..]).into());
good(msg::Relay::new(&b"guaranteed guaranteed"[..]).into());
bad(msg::AnyChanMsg::RelayEarly(
msg::Relay::new(&b"for the world and its mother"[..]).into(),
));
bad(msg::Versions::new([1, 2, 3]).unwrap().into());
}
}