diff --git a/Cargo.lock b/Cargo.lock index e43db3f..4a9358a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,6 +149,11 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "custom_error" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "digest" version = "0.8.1" @@ -1197,6 +1202,7 @@ version = "0.2.0" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "custom_error 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1265,6 +1271,7 @@ dependencies = [ "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" +"checksum custom_error 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c189751d60563837f66c7ebf87f6a6e4c101e937d54521e88620e89c79b8a2ad" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" diff --git a/Cargo.toml b/Cargo.toml index 8f42920..cce806f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] bytes = "0.4.12" clap = "2.33.0" +custom_error = "1.6.0" futures = "0.1.28" http = "0.1.17" hyper = "0.12.31" diff --git a/src/commands/filter.rs b/src/commands/filter.rs index 41fc9ee..55c9ee4 100644 --- a/src/commands/filter.rs +++ b/src/commands/filter.rs @@ -39,6 +39,6 @@ pub fn run(args: &ArgMatches) -> Result<(), WebmetroError> { } Runtime::new().unwrap().block_on(chunk_stream.for_each(|chunk| { - io::stdout().write_all(chunk.as_ref()).map_err(WebmetroError::IoError) + io::stdout().write_all(chunk.as_ref()).map_err(WebmetroError::from) })) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index e6decf5..3acf871 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -23,5 +23,5 @@ pub mod send; pub fn stdin_stream() -> impl Stream { FramedRead::new(AllowStdIo::new(stdin()), BytesCodec::new()) .map(|bytes| bytes.into_buf()) - .map_err(WebmetroError::IoError) + .map_err(WebmetroError::from) } diff --git a/src/commands/relay.rs b/src/commands/relay.rs index ca49d7b..bae0a6e 100644 --- a/src/commands/relay.rs +++ b/src/commands/relay.rs @@ -1,4 +1,3 @@ -use std::error::Error; use std::net::ToSocketAddrs; use std::sync::{ Arc, @@ -53,9 +52,9 @@ fn get_stream(channel: Handle) -> impl Stream) -> impl Stream { +fn post_stream(channel: Handle, stream: impl Stream) -> impl Stream { let source = stream - .map_err(WebmetroError::from_err) + .map_err(WebmetroError::from) .parse_ebml().with_soft_limit(BUFFER_LIMIT) .chunk_webm().with_soft_limit(BUFFER_LIMIT); let sink = Transmitter::new(channel); diff --git a/src/commands/send.rs b/src/commands/send.rs index 148e9ad..a16adee 100644 --- a/src/commands/send.rs +++ b/src/commands/send.rs @@ -46,7 +46,7 @@ pub fn run(args: &ArgMatches) -> Result<(), WebmetroError> { let url_str = match args.value_of("url") { Some(url) => String::from(url), - _ => return Err(WebmetroError::from_str("Listen address wasn't provided")) + _ => return Err("Listen address wasn't provided".into()) }; if args.is_present("throttle") { @@ -63,7 +63,7 @@ pub fn run(args: &ArgMatches) -> Result<(), WebmetroError> { let request = Request::put(url_str) .body(request_payload) - .map_err(WebmetroError::from_err)?; + .map_err(WebmetroError::from)?; let client = Client::builder().build(HttpConnector::new(1)); let future = client.request(request) @@ -72,7 +72,7 @@ pub fn run(args: &ArgMatches) -> Result<(), WebmetroError> { Ok(()) }) }) - .map_err(WebmetroError::from_err); + .map_err(WebmetroError::from); Runtime::new().unwrap().block_on(future) } diff --git a/src/ebml.rs b/src/ebml.rs index 0d15f05..a896ec2 100644 --- a/src/ebml.rs +++ b/src/ebml.rs @@ -1,6 +1,5 @@ use bytes::{BigEndian, ByteOrder, BufMut}; -use std::error::Error as ErrorTrait; -use std::fmt::{Display, Formatter, Result as FmtResult}; +use custom_error::custom_error; use std::io::{Cursor, Error as IoError, ErrorKind, Result as IoResult, Write, Seek, SeekFrom}; use futures::Async; @@ -8,46 +7,15 @@ pub const EBML_HEAD_ID: u64 = 0x0A45DFA3; pub const DOC_TYPE_ID: u64 = 0x0282; pub const VOID_ID: u64 = 0x6C; -#[derive(Debug, PartialEq)] -pub enum EbmlError { - CorruptVarint, - UnknownElementId, - UnknownElementLength, - CorruptPayload, -} -impl Display for EbmlError { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - write!(f, "{}", self.description()) - } -} -impl ErrorTrait for EbmlError { - fn description(&self) -> &str { - match self { - &EbmlError::CorruptVarint => "EBML Varint could not be parsed", - &EbmlError::UnknownElementId => "EBML element ID was \"unknown\"", - &EbmlError::UnknownElementLength => "EBML element length was \"unknown\" for an element not allowing that", - &EbmlError::CorruptPayload => "EBML element payload could not be parsed", - } - } +custom_error!{pub EbmlError + CorruptVarint = r#"EBML Varint could not be parsed"#, + UnknownElementId = r#"EBML element ID was "unknown"#, + UnknownElementLength = r#"EBML element length was "unknown" for an element not allowing that"#, + CorruptPayload = r#"EBML element payload could not be parsed"#, } -#[derive(Debug, PartialEq)] -pub enum WriteError { - OutOfRange -} -impl Display for WriteError { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - match self { - &WriteError::OutOfRange => write!(f, "EBML Varint out of range") - } - } -} -impl ErrorTrait for WriteError { - fn description(&self) -> &str { - match self { - &WriteError::OutOfRange => "EBML Varint out of range" - } - } +custom_error!{pub WriteError + OutOfRange = "EBML Varint out of range" } #[derive(Debug, PartialEq)] @@ -313,27 +281,27 @@ mod tests { #[test] fn fail_corrupted_varints() { - assert_eq!(decode_varint(&[0]), Err(CorruptVarint)); - assert_eq!(decode_varint(&[0, 0, 0]), Err(CorruptVarint)); + if let Err(CorruptVarint) = decode_varint(&[0]) {} else {assert!(false)} + if let Err(CorruptVarint) = decode_varint(&[0, 0, 0]) {} else {assert!(false)} } #[test] fn incomplete_varints() { - assert_eq!(decode_varint(&[]), Ok(None)); - assert_eq!(decode_varint(&[0x40]), Ok(None)); - assert_eq!(decode_varint(&[0x01, 0, 0]), Ok(None)); + assert!(decode_varint(&[]).unwrap().is_none()); + assert!(decode_varint(&[0x40]).unwrap().is_none()); + assert!(decode_varint(&[0x01, 0, 0]).unwrap().is_none()); } #[test] fn parse_varints() { - assert_eq!(decode_varint(&[0xFF]), Ok(Some((Unknown, 1)))); - assert_eq!(decode_varint(&[0x7F, 0xFF]), Ok(Some((Unknown, 2)))); - assert_eq!(decode_varint(&[0x80]), Ok(Some((Value(0), 1)))); - assert_eq!(decode_varint(&[0x81]), Ok(Some((Value(1), 1)))); - assert_eq!(decode_varint(&[0x40, 52]), Ok(Some((Value(52), 2)))); + if let Ok(Some((Unknown, 1))) = decode_varint(&[0xFF]) {} else {assert!(false)} + if let Ok(Some((Unknown, 2))) = decode_varint(&[0x7F, 0xFF]) {} else {assert!(false)} + if let Ok(Some((Value(0), 1))) = decode_varint(&[0x80]) {} else {assert!(false)} + if let Ok(Some((Value(1), 1))) = decode_varint(&[0x81]) {} else {assert!(false)} + if let Ok(Some((Value(52), 2))) = decode_varint(&[0x40, 52]) {} else {assert!(false)} // test extra data in buffer - assert_eq!(decode_varint(&[0x83, 0x11]), Ok(Some((Value(3), 1)))); + if let Ok(Some((Value(3), 1))) = decode_varint(&[0x83, 0x11]) {} else {assert!(false)} } #[test] @@ -405,45 +373,45 @@ mod tests { #[test] fn fail_corrupted_tags() { - assert_eq!(decode_tag(&[0]), Err(CorruptVarint)); - assert_eq!(decode_tag(&[0x80, 0]), Err(CorruptVarint)); - assert_eq!(decode_tag(&[0xFF, 0x80]), Err(UnknownElementId)); - assert_eq!(decode_tag(&[0x7F, 0xFF, 0x40, 0]), Err(UnknownElementId)); + if let Err(CorruptVarint) = decode_tag(&[0]) {} else {assert!(false)} + if let Err(CorruptVarint) = decode_tag(&[0x80, 0]) {} else {assert!(false)} + if let Err(UnknownElementId) = decode_tag(&[0xFF, 0x80]) {} else {assert!(false)} + if let Err(UnknownElementId) = decode_tag(&[0x7F, 0xFF, 0x40, 0]) {} else {assert!(false)} } #[test] fn incomplete_tags() { - assert_eq!(decode_tag(&[]), Ok(None)); - assert_eq!(decode_tag(&[0x80]), Ok(None)); - assert_eq!(decode_tag(&[0x40, 0, 0x40]), Ok(None)); + assert!(decode_tag(&[]).unwrap().is_none()); + assert!(decode_tag(&[0x80]).unwrap().is_none()); + assert!(decode_tag(&[0x40, 0, 0x40]).unwrap().is_none()); } #[test] fn parse_tags() { - assert_eq!(decode_tag(&[0x80, 0x80]), Ok(Some((0, Value(0), 2)))); - assert_eq!(decode_tag(&[0x81, 0x85]), Ok(Some((1, Value(5), 2)))); - assert_eq!(decode_tag(&[0x80, 0xFF]), Ok(Some((0, Unknown, 2)))); - assert_eq!(decode_tag(&[0x80, 0x7F, 0xFF]), Ok(Some((0, Unknown, 3)))); - assert_eq!(decode_tag(&[0x85, 0x40, 52]), Ok(Some((5, Value(52), 3)))); + if let Ok(Some((0, Value(0), 2))) = decode_tag(&[0x80, 0x80]) {} else {assert!(false)} + if let Ok(Some((1, Value(5), 2))) = decode_tag(&[0x81, 0x85]) {} else {assert!(false)} + if let Ok(Some((0, Unknown, 2))) = decode_tag(&[0x80, 0xFF]) {} else {assert!(false)} + if let Ok(Some((0, Unknown, 3))) = decode_tag(&[0x80, 0x7F, 0xFF]) {} else {assert!(false)} + if let Ok(Some((5, Value(52), 3))) = decode_tag(&[0x85, 0x40, 52]) {} else {assert!(false)} } #[test] fn bad_uints() { - assert_eq!(decode_uint(&[]), Err(EbmlError::CorruptPayload)); - assert_eq!(decode_uint(&[0; 9]), Err(EbmlError::CorruptPayload)); + if let Err(EbmlError::CorruptPayload) = decode_uint(&[]) {} else {assert!(false)} + if let Err(EbmlError::CorruptPayload) = decode_uint(&[0; 9]) {} else {assert!(false)} } #[test] fn parse_uints() { - assert_eq!(decode_uint(&[0]), Ok(0)); - assert_eq!(decode_uint(&[0; 8]), Ok(0)); - assert_eq!(decode_uint(&[1]), Ok(1)); - assert_eq!(decode_uint(&[0,0,0,0,0,0,0,1]), Ok(1)); - assert_eq!(decode_uint(&[38]), Ok(38)); - assert_eq!(decode_uint(&[0,0,0,0,0,0,0,38]), Ok(38)); - assert_eq!(decode_uint(&[0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]), Ok(9223372036854775807)); - assert_eq!(decode_uint(&[0x80,0,0,0,0,0,0,0]), Ok(9223372036854775808)); - assert_eq!(decode_uint(&[0x80,0,0,0,0,0,0,1]), Ok(9223372036854775809)); + assert_eq!(decode_uint(&[0]).unwrap(), 0); + assert_eq!(decode_uint(&[0; 8]).unwrap(), 0); + assert_eq!(decode_uint(&[1]).unwrap(), 1); + assert_eq!(decode_uint(&[0,0,0,0,0,0,0,1]).unwrap(), 1); + assert_eq!(decode_uint(&[38]).unwrap(), 38); + assert_eq!(decode_uint(&[0,0,0,0,0,0,0,38]).unwrap(), 38); + assert_eq!(decode_uint(&[0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]).unwrap(), 9223372036854775807); + assert_eq!(decode_uint(&[0x80,0,0,0,0,0,0,0]).unwrap(), 9223372036854775808); + assert_eq!(decode_uint(&[0x80,0,0,0,0,0,0,1]).unwrap(), 9223372036854775809); } #[derive(Debug, PartialEq)] @@ -466,6 +434,6 @@ mod tests { #[test] fn decode_sanity_test() { let decoded = GenericElement::decode_element(TEST_FILE); - assert_eq!(decoded, Ok(Some((GenericElement(0x0A45DFA3, 31), 43)))); + if let Ok(Some((GenericElement(0x0A45DFA3, 31), 43))) = decoded {} else {assert!(false)} } } diff --git a/src/error.rs b/src/error.rs index 7a0ca38..9d29a86 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,75 +1,19 @@ -use std::{ - error::Error, - fmt::{ - Display, - Formatter, - Result as FmtResult - }, - io::Error as IoError -}; -use crate::ebml::EbmlError; +use custom_error::custom_error; -#[derive(Debug)] -pub enum WebmetroError { - ResourcesExceeded, - EbmlError(EbmlError), - IoError(IoError), - Unknown(Box) +custom_error!{pub WebmetroError + ResourcesExceeded = "resources exceeded", + EbmlError{source: crate::ebml::EbmlError} = "EBML error", + HttpError{source: http::Error} = "HTTP error", + HyperError{source: hyper::Error} = "Hyper error", + IoError{source: std::io::Error} = "IO error", + TimerError{source: tokio::timer::Error} = "Timer error", + WarpError{source: warp::Error} = "Warp error", + ApplicationError{message: String} = "{message}" } -impl WebmetroError { - pub fn from_str(string: &str) -> WebmetroError { - string.into() - } - - pub fn from_err(err: E) -> WebmetroError { - WebmetroError::Unknown(Box::new(err)) - } -} - -impl Display for WebmetroError { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - match self { - &WebmetroError::ResourcesExceeded => write!(f, "resources exceeded"), - &WebmetroError::EbmlError(ref err) => err.fmt(f), - &WebmetroError::IoError(ref err) => err.fmt(f), - &WebmetroError::Unknown(ref err) => err.fmt(f), - } - } -} -impl Error for WebmetroError { - fn description(&self) -> &str { - match self { - &WebmetroError::ResourcesExceeded => "resources exceeded", - &WebmetroError::EbmlError(ref err) => err.description(), - &WebmetroError::IoError(ref err) => err.description(), - &WebmetroError::Unknown(ref err) => err.description(), - } - } -} - -impl From for WebmetroError { - fn from(err: EbmlError) -> WebmetroError { - WebmetroError::EbmlError(err) - } -} - -impl From for WebmetroError { - fn from(err: IoError) -> WebmetroError { - WebmetroError::IoError(err) - } -} - -impl From> for WebmetroError { - fn from(err: Box) -> WebmetroError { - WebmetroError::Unknown(err) - } -} - -impl<'a> From<&'a str> for WebmetroError { - fn from(err: &'a str) -> WebmetroError { - let error: Box = err.into(); - WebmetroError::Unknown(error) +impl From<&str> for WebmetroError { + fn from(message: &str) -> WebmetroError { + WebmetroError::ApplicationError{message: message.into()} } } diff --git a/src/fixers.rs b/src/fixers.rs index ed0df2c..aeac505 100644 --- a/src/fixers.rs +++ b/src/fixers.rs @@ -98,7 +98,7 @@ impl> Stream for Throttle fn poll(&mut self) -> Result>, WebmetroError> { match self.sleep.poll() { - Err(err) => return Err(WebmetroError::Unknown(Box::new(err))), + Err(err) => return Err(err.into()), Ok(Async::NotReady) => return Ok(Async::NotReady), Ok(Async::Ready(())) => { /* can continue */ } } diff --git a/src/stream_parser.rs b/src/stream_parser.rs index 388f89c..d9e4d0a 100644 --- a/src/stream_parser.rs +++ b/src/stream_parser.rs @@ -55,9 +55,9 @@ impl> EbmlStreamingParser Ok(None) => { // need to refill buffer, below }, - other => return other.map_err(WebmetroError::EbmlError).and_then(move |_| { + other => return other.map_err(WebmetroError::from).and_then(move |_| { match T::decode_element(&self.buffer) { - Err(err) => Err(WebmetroError::EbmlError(err)), + Err(err) => Err(err.into()), Ok(None) => panic!("Buffer was supposed to have enough data to parse element, somehow did not."), Ok(Some((element, element_size))) => { self.last_read = element_size;