diff --git a/.gitignore b/.gitignore index 2b918afd..f0a928a7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ # These are backup files generated by rustfmt **/*.rs.bk -.vscode \ No newline at end of file +.vscode + +/local/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 3d5e5ad0..8b33eff5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,42 +2,12 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", -] - [[package]] name = "bitflags" version = "2.9.0" @@ -132,16 +102,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "backtrace", - "version_check", -] - [[package]] name = "getrandom" version = "0.3.2" @@ -154,12 +114,6 @@ dependencies = [ "wasi 0.14.2+wasi-0.2.4", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "libc" version = "0.2.171" @@ -194,21 +148,6 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "miniz_oxide" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" -dependencies = [ - "adler2", -] - [[package]] name = "mio" version = "1.0.3" @@ -221,15 +160,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "parking_lot" version = "0.12.3" @@ -286,12 +216,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustix" version = "1.0.5" @@ -311,9 +235,9 @@ version = "0.10.0" dependencies = [ "byteorder", "crossterm", - "error-chain", "libc", "socket2", + "thiserror", "uuid", ] @@ -380,6 +304,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.18" @@ -401,12 +345,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 5799efb8..85198ebd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,9 +20,9 @@ exclude = [ [dependencies] byteorder = { version = "1.5.0", features = [] } -error-chain = "0.12.4" libc = { version = "0.2.171" } socket2 = { version = "0.5.9", features = ["all"] } +thiserror = "2.0.*" uuid = { version = "1.12", features = ["v4"] } [dev-dependencies] @@ -35,6 +35,18 @@ std = [] [badges] travis-ci = { repository = "Lan2u/RustSacn" } -[[examples]] +[[example]] +name = 'simple-receiver' +path = 'examples/simple-receiver.rs' + +[[example]] +name = 'sine-wave-sender' path = 'examples/sine-wave-sender.rs' -edition = '2024' + +[[example]] +name = 'demo_rcv' +path = 'examples/demo_rcv/src/main.rs' + +[[example]] +name = 'demo_src' +path = 'examples/demo_src/src/main.rs' diff --git a/examples/demo_rcv/Cargo.toml b/examples/demo_rcv/Cargo.toml index 1cec180d..5b39db84 100644 --- a/examples/demo_rcv/Cargo.toml +++ b/examples/demo_rcv/Cargo.toml @@ -8,4 +8,4 @@ edition = "2018" [dependencies] sacn = { path = "../../"} -error-chain = "0.12.2" +thiserror = "2.0.*" \ No newline at end of file diff --git a/examples/demo_rcv/src/error.rs b/examples/demo_rcv/src/error.rs index 62c8dfd9..992d75bb 100644 --- a/examples/demo_rcv/src/error.rs +++ b/examples/demo_rcv/src/error.rs @@ -9,19 +9,23 @@ /// Use the error-chain system to allow handling IO and sACN errors chained together. /// error_chain! macro automatically creates the Error / ErrorKind / Result required to use the Errors/external errors below with error-chain. -/// +/// /// Sacn create errors are wrapped in Sacn(::sacn::error::errors::Error). -/// +/// /// Std io errors are wrapped in Io(::std::io::Error). -/// +/// + pub mod errors { - error_chain! { - foreign_links { - Sacn(::sacn::error::errors::Error); - Io(::std::io::Error); - } - - errors {} + use thiserror::Error; + + #[derive(Error, Debug)] + pub enum DemoError { + #[error(transparent)] + Sacn(#[from] ::sacn::error::errors::SacnError), + + #[error(transparent)] + Io(#[from] ::std::io::Error), } -} + pub type Result = std::result::Result; +} diff --git a/examples/demo_rcv/src/main.rs b/examples/demo_rcv/src/main.rs index 7967434f..7f16c262 100644 --- a/examples/demo_rcv/src/main.rs +++ b/examples/demo_rcv/src/main.rs @@ -1,4 +1,5 @@ -#![recursion_limit="1024"] // Recursion limit for error-chain, value used as recommended by the crates documentation. +#![recursion_limit = "1024"] +// Recursion limit for error-chain, value used as recommended by the crates documentation. // Copyright 2020 sacn Developers // @@ -10,86 +11,84 @@ // This file was created as part of a University of St Andrews Computer Science BSC Senior Honours Dissertation Project. //! An example demo sACN receiver which utilises the sACN library. -//! +//! //! Primarily used for testing the library including real-world conformance, compliance, integration and acceptance tests. //! As a test program the error handling is limited for simplicity. -//! +//! //! Usage instructions are described by either running the receiver and using the help command or by the get_usage_str function //! below. -//! +//! //! The ACTION_... constants describe the various user input strings possible once the program has started, with more details described in get_usage_str within //! the code. The details aren't repeated outside of that to minimise the amount of references that have to be kept upto date and which could diverge over time. -//! -//! Note the lack of top level constant strings used in the place of output format strings is due to a limitation in rust where the format string cannot be a +//! +//! Note the lack of top level constant strings used in the place of output format strings is due to a limitation in rust where the format string cannot be a //! const. -//! - -#[macro_use] -extern crate error_chain; +//! /// The demo itself utilises a small error-chain which wraps the errors from the sACN crate and a few standard crates. pub mod error; -use error::errors::*; +use error::errors::{DemoError, Result}; extern crate sacn; -use sacn::receive::{DMXData, SacnReceiver, DiscoveredSacnSource}; use sacn::packet::ACN_SDT_MULTICAST_PORT; +use sacn::receive::{DMXData, DiscoveredSacnSource, SacnReceiver}; -use std::net::{SocketAddr}; -use std::time::Duration; -use std::io; use std::env; -use std::thread::sleep; use std::fs::File; +use std::io; use std::io::prelude::*; +use std::net::SocketAddr; +use std::thread::sleep; +use std::time::Duration; /// The string given by the user to receive data. -const ACTION_RECV: &str = "r"; +const ACTION_RECV: &str = "r"; /// The string given by the user to receive data continously. -const ACTION_RECV_CONTINUOUS: &str = "c"; +const ACTION_RECV_CONTINUOUS: &str = "c"; /// The string given by the user to cause the receiver to display the sources which have currently been discovered. -const ACTION_PRINT_DISCOVERED_SOURCES: &str = "s"; +const ACTION_PRINT_DISCOVERED_SOURCES: &str = "s"; /// The string given by the user to cause the receiver to display the sources which have been discovered but without checking for timeouts first. This is usually /// used as part of debugging / tests. -const ACTION_PRINT_DISCOVERED_SOURCES_NO_TIMEOUT: &str = "x"; +const ACTION_PRINT_DISCOVERED_SOURCES_NO_TIMEOUT: &str = "x"; -/// The string given by the user to quit the receiver. -const ACTION_QUIT: &str = "q"; +/// The string given by the user to quit the receiver. +const ACTION_QUIT: &str = "q"; /// The string given by the user to display the help. -const ACTION_HELP: &str = "h"; +const ACTION_HELP: &str = "h"; /// The string given by the user to start listening to a specific universe of data. -const ACTION_LISTEN_UNIVERSE: &str = "l"; +const ACTION_LISTEN_UNIVERSE: &str = "l"; /// The string given by the user to terminate listening to a specific universe of data. -const ACTION_STOP_LISTEN_UNIVERSE: &str = "t"; +const ACTION_STOP_LISTEN_UNIVERSE: &str = "t"; /// The string given by the user to cause the receiver to sleep/block for a given time. This is used as part of tests as a way to encourage a specific -/// ordering of concurrent events by having one side way for a period. This is discussed in more detail within the specific tests. -const ACTION_SLEEP: &str = "w"; +/// ordering of concurrent events by having one side way for a period. This is discussed in more detail within the specific tests. +const ACTION_SLEEP: &str = "w"; /// The string given by the user to enable receiving preview data. -const ACTION_PREVIEW: &str = "p"; +const ACTION_PREVIEW: &str = "p"; /// The string given by the user to enable universe discovery packets to be announced when received. -const ACTION_ANNOUNCE_DISCOVERED: &str = "a"; +const ACTION_ANNOUNCE_DISCOVERED: &str = "a"; /// Lines of input starting with this string are ignored. This is commonly used within the automated tests to allow comments within the input files. -const ACTION_IGNORE: &str = "#"; +const ACTION_IGNORE: &str = "#"; /// The string given by the user to cause the receiver to output data to a file. -const ACTION_FILE_OUT: &str = "f"; +const ACTION_FILE_OUT: &str = "f"; /// The string given by the user to cause termination packets to be announced. "e" for end. -const ACTION_ANNOUNCE_TERMINATION: &str = "e"; +const ACTION_ANNOUNCE_TERMINATION: &str = "e"; /// The headers used for the top of the file when the FILE_OUT action is used. -const WRITE_TO_FILE_HEADERS: &str = "Data_ID, Universe, Sync_Addr, Priority, Preview_data?, Payload"; +const WRITE_TO_FILE_HEADERS: &str = + "Data_ID, Universe, Sync_Addr, Priority, Preview_data?, Payload"; /// Describes the various commands / command-line arguments available and what they do. /// Displayed to the user if they ask for help or enter an unrecognised input. @@ -142,7 +141,7 @@ fn get_usage_str() -> String { } /// The entry point of the demo_rcv. Usage is described in get_usage_str or by running the program and typing "h" or "help". -/// +/// /// # Arguments /// Usage: ./main fn main() { @@ -156,7 +155,11 @@ fn main() { let source_limit = None; - let mut dmx_recv = SacnReceiver::with_ip(SocketAddr::new(interface_ip.parse().unwrap(), ACN_SDT_MULTICAST_PORT), source_limit).unwrap(); + let mut dmx_recv = SacnReceiver::with_ip( + SocketAddr::new(interface_ip.parse().unwrap(), ACN_SDT_MULTICAST_PORT), + source_limit, + ) + .unwrap(); println!("Started"); @@ -171,7 +174,7 @@ fn main() { println!("Error: Input data line unusable: {}", e); } } - } + } } /// Handle a line of input on stdin to the program. @@ -197,20 +200,27 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { ACTION_IGNORE => { // Ignore the input, this is usually used for lines that contain comments within test input files. } - ACTION_HELP => { // Display help + ACTION_HELP => { + // Display help display_help(); } - ACTION_RECV => { // Receive data + ACTION_RECV => { + // Receive data if split_input.len() < 2 { display_help(); - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 2 )")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Insufficient parts ( < 2 )", + ) + .into()); } // To learn about how to parse strings to ints. // https://stackoverflow.com/questions/27043268/convert-a-string-to-int-in-rust (03/02/2020) let timeout_secs: u64 = split_input[1].parse().unwrap(); - let timeout = if timeout_secs == 0 { // A timeout value of 0 means no timeout. + let timeout = if timeout_secs == 0 { + // A timeout value of 0 means no timeout. None } else { Some(Duration::from_secs(timeout_secs)) @@ -220,40 +230,50 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { let res = dmx_recv.recv(timeout).map_err(|e| e.into()); print_recv(res); } - ACTION_RECV_CONTINUOUS => { // Receive data continuously. + ACTION_RECV_CONTINUOUS => { + // Receive data continuously. if split_input.len() < 3 { display_help(); - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 3 )")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Insufficient parts ( < 3 )", + ) + .into()); } - let timeout_secs: u64 = split_input[1].parse().unwrap(); + let timeout_secs: u64 = split_input[1].parse().unwrap(); - let count: u64 = split_input[2].parse().unwrap(); + let count: u64 = split_input[2].parse().unwrap(); - let timeout = if timeout_secs == 0 { // A timeout value of 0 means no timeout. - None - } else { - Some(Duration::from_secs(timeout_secs)) - }; + let timeout = if timeout_secs == 0 { + // A timeout value of 0 means no timeout. + None + } else { + Some(Duration::from_secs(timeout_secs)) + }; - for _ in 0 .. count { + for _ in 0..count { let res = dmx_recv.recv(timeout).map_err(|e| e.into()); print_recv(res); } } - ACTION_PRINT_DISCOVERED_SOURCES => { // Print discovered sources, note that no sources will be discovered unless you try and recv first. + ACTION_PRINT_DISCOVERED_SOURCES => { + // Print discovered sources, note that no sources will be discovered unless you try and recv first. print_discovered_sources(&dmx_recv.get_discovered_sources()); } - ACTION_PRINT_DISCOVERED_SOURCES_NO_TIMEOUT => { // Print discovered sources without checking if they are timed out already. + ACTION_PRINT_DISCOVERED_SOURCES_NO_TIMEOUT => { + // Print discovered sources without checking if they are timed out already. print_discovered_sources(&dmx_recv.get_discovered_sources_no_check()); } - ACTION_QUIT => { - return Ok(false) - } + ACTION_QUIT => return Ok(false), ACTION_SLEEP => { if split_input.len() < 2 { display_help(); - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 2 )")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Insufficient parts ( < 2 )", + ) + .into()); } let millisecs: u64 = split_input[1].parse().unwrap(); sleep(Duration::from_millis(millisecs)); @@ -261,7 +281,11 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { ACTION_LISTEN_UNIVERSE => { if split_input.len() < 2 { display_help(); - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 2 )")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Insufficient parts ( < 2 )", + ) + .into()); } let universe: u16 = split_input[1].parse().unwrap(); dmx_recv.listen_universes(&[universe])?; @@ -269,7 +293,11 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { ACTION_STOP_LISTEN_UNIVERSE => { if split_input.len() < 2 { display_help(); - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 2 )")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Insufficient parts ( < 2 )", + ) + .into()); } let universe: u16 = split_input[1].parse().unwrap(); @@ -280,10 +308,10 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { match val { Ok(v) => { dmx_recv.set_process_preview_data(v); - }, + } Err(_e) => { - bail!(std::io::Error::new( - std::io::ErrorKind::InvalidInput, "Preview flag option not 'true'/'false' or otherwise parsable as boolean")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, "Preview flag option not 'true'/'false' or otherwise parsable as boolean").into()); } } } @@ -292,10 +320,10 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { match val { Ok(v) => { dmx_recv.set_announce_source_discovery(v); - }, + } Err(_e) => { - bail!(std::io::Error::new( - std::io::ErrorKind::InvalidInput, "Announce discovery option not 'true'/'false' or otherwise parsable as boolean")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, "Announce discovery option not 'true'/'false' or otherwise parsable as boolean").into()); } } } @@ -304,17 +332,21 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { match val { Ok(v) => { dmx_recv.set_announce_stream_termination(v); - }, + } Err(_e) => { - bail!(std::io::Error::new( - std::io::ErrorKind::InvalidInput, "Announce stream termination option not 'true'/'false' or otherwise parsable as boolean")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, "Announce stream termination option not 'true'/'false' or otherwise parsable as boolean").into()); } } } ACTION_FILE_OUT => { if split_input.len() < 4 { display_help(); - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 3 )")); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Insufficient parts ( < 4 )", + ) + .into()); } let file_path = split_input[1]; @@ -323,7 +355,8 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { let timeout_secs: u64 = split_input[3].parse().unwrap(); - let timeout = if timeout_secs == 0 { // A timeout value of 0 means no timeout. + let timeout = if timeout_secs == 0 { + // A timeout value of 0 means no timeout. None } else { Some(Duration::from_secs(timeout_secs)) @@ -335,49 +368,57 @@ fn handle_input(dmx_recv: &mut SacnReceiver) -> Result { write!(boxed_file, "{}\n", WRITE_TO_FILE_HEADERS)?; - for i in 0 .. count { + for i in 0..count { let res: Vec = dmx_recv.recv(timeout).unwrap(); write_to_file(&mut boxed_file, res, i)?; } } x => { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("Unknown input type: {}", x))); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!("Unknown input type: {}", x), + ) + .into()); } } Ok(true) } Err(e) => { - bail!(e); + return Err(e.into()); } } } /// Writes the given data to the given file (uses the given data_id as first column). /// Uses comma separated values. -/// +/// /// # Arguments /// file: A mutable box reference containing the file to write to. -/// +/// /// data: The data to write to the file. -/// +/// /// data_id: The id used as the first column within the file for the data. -/// +/// fn write_to_file(file: &mut Box, data: Vec, data_id: u64) -> Result<()> { for d in data { let values_str = create_values_str(d.values)?; // Note that the formatting string literal must be here and cannot be subsituted using const. - write!(*file, "{},{},{},{},{},{}\n", data_id, d.universe, d.sync_uni, d.priority, d.preview, values_str)?; + write!( + *file, + "{},{},{},{},{},{}\n", + data_id, d.universe, d.sync_uni, d.priority, d.preview, values_str + )?; } Ok(()) } /// Converts the given array of u8 values into a comma separated string. -/// +/// /// # Arguments /// values: The unsigned 8 bit number values to turn into a string. -/// +/// fn create_values_str(values: Vec) -> Result { let mut res: String = "".to_string(); @@ -390,7 +431,7 @@ fn create_values_str(values: Vec) -> Result { // Adapted from. // https://users.rust-lang.org/t/what-is-right-ways-to-concat-strings/3780/4 (09/04/2020) res.push_str(&format!("{}", iter.next().unwrap())); - + for v in iter { res.push_str(&format!(",{}", v)); } @@ -398,33 +439,21 @@ fn create_values_str(values: Vec) -> Result { Ok(res) } - /// Prints the given output from recv to stdout. -/// Errors are printed using their debug output except for universe terminated which is printed as "Universe x Terminated" where x is the universe. This +/// Errors are printed using their debug output except for universe terminated which is printed as "Universe x Terminated" where x is the universe. This /// is to avoid the CID being printed which changes for every test as it is randomly generated in most tests. -/// +/// /// # Arguments /// res: The data to display. -/// +/// fn print_recv(res: Result>) { match res { - Err(e) => { - match e.kind() { - ErrorKind::Sacn(x) => { - match x.kind() { - sacn::error::errors::ErrorKind::UniverseTerminated(_src_cid, uni) => { - println!("Universe {} Terminated", uni); - } - z => { - println!("Error Encountered: {:?}", z); - } - } - }, - x => { - println!("Error Encountered: {:?}", x); - } - } - }, + Err(DemoError::Sacn(sacn::error::errors::SacnError::UniverseTerminated(_src, uni))) => { + println!("Universe {} Terminated", uni); + } + Err(x) => { + println!("Error Encountered: {:?}", x); + } Ok(d) => { print_data(d); } @@ -433,27 +462,30 @@ fn print_recv(res: Result>) { /// Prints the given data to stdout in the format [{{ Universe(s): x, Sync_Universe: y, Values: z }}, ...] where x is the universe, y is the synchronisation address /// and z is the values. The ... indicates that there may be multiple bits of data to print at once which follows the same format. -/// +/// /// # Arguments /// data: The data to be printed to stdout. -/// +/// fn print_data(mut data: Vec) { print!("["); - // Sort the data with lower universes first, this means that even though the data returned from the waiting data can be in any order this means + // Sort the data with lower universes first, this means that even though the data returned from the waiting data can be in any order this means // that the ordering will be known which makes checking the output using a test script easier. - data.sort(); + data.sort(); for d in data { - print!("{{ Universe(s): {}, Sync_Universe: {}, Values: {:?} }}, ", d.universe, d.sync_uni, d.values); + print!( + "{{ Universe(s): {}, Sync_Universe: {}, Values: {:?} }}, ", + d.universe, d.sync_uni, d.values + ); } println!("]"); } -/// Prints the given array of discovered sources to std out. Uses the format "Name: x, Universes: y" where x is the source name and y is the universes registered to the -/// source. -/// +/// Prints the given array of discovered sources to std out. Uses the format "Name: x, Universes: y" where x is the source name and y is the universes registered to the +/// source. +/// /// # Arguments /// src: The sources to print to standard out. -/// +/// fn print_discovered_sources(srcs: &Vec) { for s in srcs { println!("Name: {}, Universes: {:?}", s.name, s.get_all_universes()); @@ -461,7 +493,7 @@ fn print_discovered_sources(srcs: &Vec) { } /// Displays the usage/help string to stdout. -/// -fn display_help(){ +/// +fn display_help() { println!("{}", get_usage_str()); } diff --git a/examples/demo_src/Cargo.toml b/examples/demo_src/Cargo.toml index baa8f533..f650229f 100644 --- a/examples/demo_src/Cargo.toml +++ b/examples/demo_src/Cargo.toml @@ -6,4 +6,4 @@ edition = "2018" [dependencies] sacn = { path = "../../"} -error-chain = "0.12.2" +thiserror = "2.0.*" \ No newline at end of file diff --git a/examples/demo_src/src/error.rs b/examples/demo_src/src/error.rs index d26fd69c..15dfa71c 100644 --- a/examples/demo_src/src/error.rs +++ b/examples/demo_src/src/error.rs @@ -15,15 +15,22 @@ /// Std io errors are wrapped in Io(::std::io::Error). /// /// Boolean parse errors from Std str ParseBoolError are wrapped in BoolStr(::std::str::ParseBoolError). + pub mod errors { - error_chain! { - foreign_links { - Sacn(::sacn::error::errors::Error); - Io(::std::io::Error); - BoolStr(::std::str::ParseBoolError); - } - - errors {} + use thiserror::Error; + + #[derive(Error, Debug)] + pub enum DemoError { + #[error(transparent)] + Sacn(#[from] ::sacn::error::errors::SacnError), + + #[error(transparent)] + Io(#[from] ::std::io::Error), + + #[error(transparent)] + BoolStr(#[from] ::std::str::ParseBoolError), } + + pub type Result = std::result::Result; } diff --git a/examples/demo_src/src/main.rs b/examples/demo_src/src/main.rs index d9b1d0c3..e8775523 100644 --- a/examples/demo_src/src/main.rs +++ b/examples/demo_src/src/main.rs @@ -26,12 +26,9 @@ //! const. //! -#[macro_use] -extern crate error_chain; - /// The demo itself utilises a small error-chain which wraps the errors from the sACN crate and a few standard crates. pub mod error; -use error::errors::*; +use error::errors::{DemoError, Result}; extern crate sacn; @@ -283,7 +280,7 @@ fn display_help(){ /// fn handle_full_data_option(src: &mut SacnSource, split_input: Vec<&str>) -> Result { if split_input.len() < 4 { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 4 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 4 )").into()); } let universe: u16 = split_input[1].parse().unwrap(); @@ -320,7 +317,7 @@ fn handle_full_data_option(src: &mut SacnSource, split_input: Vec<&str>) -> Resu /// fn handle_all_data_option(src: &mut SacnSource, split_input: Vec<&str>) -> Result { if split_input.len() < 3 { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 3 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 3 )").into()); } let universe: u16 = split_input[1].parse().unwrap(); @@ -355,7 +352,7 @@ fn handle_data_option(src: &mut SacnSource, split_input: Vec<&str>) -> Result) -> Result let universe: u16 = split_input[1].parse().unwrap(); if split_input.len() < 5 { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 5 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 5 )").into()); } let sync_uni: u16 = split_input[2].parse().unwrap(); @@ -439,7 +436,7 @@ fn handle_unicast_option(src: &mut SacnSource, split_input: Vec<&str>) -> Result /// fn handle_data_over_time_option(src: &mut SacnSource, split_input: Vec<&str>) -> Result { if split_input.len() < 4 { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 4 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 4 )").into()); } let universe: u16 = split_input[1].parse().unwrap(); @@ -481,7 +478,7 @@ fn handle_data_over_time_option(src: &mut SacnSource, split_input: Vec<&str>) -> /// fn handle_test_preset_option(src: &mut SacnSource, split_input: Vec<&str>) -> Result { if split_input.len() < 3 { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for test preset option ( < 3 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for test preset option ( < 3 )").into()); } let preset: usize = split_input[1].parse().unwrap(); @@ -499,7 +496,7 @@ fn handle_test_preset_option(src: &mut SacnSource, split_input: Vec<&str>) -> Re }, TEST_PRESET_TWO_UNIVERSE => { if split_input.len() < 4 { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for test preset 2 universes option ( < 4 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for test preset 2 universes option ( < 4 )").into()); } let universe_2: u16 = split_input[3].parse().unwrap(); @@ -508,7 +505,7 @@ fn handle_test_preset_option(src: &mut SacnSource, split_input: Vec<&str>) -> Re }, TEST_PRESET_TWO_UNIVERSE_UNICAST => { if split_input.len() < 5 { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for test preset 2 universes option ( < 4 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for test preset 2 universes option ( < 4 )").into()); } let universe_2: u16 = split_input[3].parse().unwrap(); @@ -520,7 +517,7 @@ fn handle_test_preset_option(src: &mut SacnSource, split_input: Vec<&str>) -> Re run_acceptance_test_demo(src)?; } _ => { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Unrecognised test preset option")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Unrecognised test preset option").into()); } } @@ -940,7 +937,7 @@ fn handle_input(src: &mut SacnSource) -> Result { let split_input: Vec<&str> = input.split_whitespace().collect(); if split_input.len() < 2 { display_help(); - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 2 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 2 )").into()); } match split_input[0] { @@ -967,7 +964,7 @@ fn handle_input(src: &mut SacnSource) -> Result { } ACTION_UNICAST_SYNC_OPTION => { if split_input.len() < 3 { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 3 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts for data line ( < 3 )").into()); } let universe: u16 = split_input[1].parse().unwrap(); @@ -988,7 +985,7 @@ fn handle_input(src: &mut SacnSource) -> Result { src.set_preview_mode(v)?; }, Err(_e) => { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Preview flag option not 'true'/'false' or otherwise parsable as boolean")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Preview flag option not 'true'/'false' or otherwise parsable as boolean").into()); } } Ok(true) @@ -1005,7 +1002,7 @@ fn handle_input(src: &mut SacnSource) -> Result { ACTION_SLEEP_OPTION => { if split_input.len() < 2 { display_help(); - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 2 )")); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, "Insufficient parts ( < 2 )").into()); } let millis: u64 = split_input[1].parse().unwrap(); sleep(Duration::from_millis(millis)); @@ -1018,12 +1015,12 @@ fn handle_input(src: &mut SacnSource) -> Result { handle_test_preset_option(src, split_input) } x => { - bail!(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("Unknown input type: {}", x))); + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("Unknown input type: {}", x)).into()); } } } Err(e) => { - bail!(e); + return Err(e.into()); } } } \ No newline at end of file diff --git a/src/error.rs b/src/error.rs index 19ae4680..5114cffc 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,11 +5,11 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. // -// This file was created as part of a University of St Andrews Computer Science BSC Senior Honours Dissertation Project. +// This file is based on an earlier error.rs created as part of a University of St Andrews Computer Science BSC Senior Honours Dissertation Project. /// The errors used within the SacnLibrary. The ErrorKind subsection of this within the documentation contains details of all the errors. /// -/// Errors from external sources are wrapped within this error-chain. +/// Errors from external sources are wrapped within thiserror. /// /// Io errors from std::io::Error are wrapped within Io(::std::io::Error) /// @@ -17,231 +17,246 @@ /// /// Uuid errors from uuid::ParseError are wrapped within Uuid(uuid::ParseError) /// -/// /// ParsePack related errors come within their own family wrapped inside this error to allow easy matching (can just match for SacnParsePackError rather than a specific). /// /// SacnParsePackError(sacn_parse_pack_error::Error, sacn_parse_pack_error::ErrorKind) /// -/// Uses the error-chain crate to allow errors to allow more informative backtraces through error chaining. -/// https://docs.rs/error-chain/0.12.2/error_chain/ -pub mod errors { - use crate::sacn_parse_pack_error::sacn_parse_pack_error; - /// UUID library used to handle the UUID's used in the CID fields, used here so that error can include the cid in messages. +pub mod errors { + use crate::sacn_parse_pack_error::sacn_parse_pack_error::ParsePacketError; + use thiserror::Error; use uuid::Uuid; - error_chain! { - foreign_links { - Io(::std::io::Error); // Allow IO errors to be used with the error-chain system. - Str(::std::str::Utf8Error); // Allow standard string library errors to be used with the error-chain system. - Uuid(uuid::Error); // Allow UUID library to be used with error-chain system. - } - - links { - // All parse/pack errors live within the same chain ('family') of errors as described in sacn_parse_packet_error. - SacnParsePackError(sacn_parse_pack_error::Error, sacn_parse_pack_error::ErrorKind); - } - - errors { - /// Returned to indicate that an invalid or malformed source name was used. - /// - /// # Arguments - /// msg: A string describing why the source name is malformed. - /// - MalformedSourceName(msg: String) { - description("The given source name was malformed and couldn't be used"), - display("The given source name was malformed and couldn't be used, msg: {}", msg) - } - - /// Attempted to perform an action using a priority value that is invalid. For example sending with a priority > 200. - /// This is distinct from the SacnParsePackError(ParseInvalidPriority) as it is for a local use of an invalid priority - /// rather than receiving an invalid priority from another source. - /// - /// # Arguments - /// msg: A string describing why the priority is invalid. - /// - InvalidPriority(msg: String) { - description("Attempted to perform an action using a priority value that is invalid"), - display("Attempted to perform an action using a priority value that is invalid, msg: {}", msg) - } - - /// Used to indicate that the limit for the number of supported sources has been reached. - /// This is based on unique CID values. - /// as per ANSI E1.31-2018 Section 6.2.3.3. - /// - /// # Arguments - /// msg: A string describing why the sources exceeded error was returned. - /// - SourcesExceededError(msg: String) { - description("Limit for the number of supported sources has been reached"), - display("Limit for the number of supported sources has been reached, msg: {}", msg) - } - - /// A source was discovered by a receiver with the announce_discovery_flag set to true. - /// - /// # Arguments - /// source_name: The name of the source discovered. - /// - SourceDiscovered(source_name: String) { - description("A source was discovered by a receiver with the announce_discovery_flag set to true"), - display("A source was discovered by a receiver with the announce_discovery_flag set to true, source name: {}", source_name) - } - - /// Attempted to exceed the capacity of a single universe (packet::UNIVERSE_CHANNEL_CAPACITY). - /// - /// # Arguments - /// msg: A string describing why/how the universe capacity was exceeded. - /// - ExceedUniverseCapacity(msg: String) { - description("Attempted to exceed the capacity of a single universe"), - display("Attempted to exceed the capacity of a single universe, msg: {}", msg) - } - - /// Attempted to use illegal universe, outwith allowed range of [E131_MIN_MULTICAST_UNIVERSE, E131_MAX_MULTICAST_UNIVERSE] - /// + E131_DISCOVERY_UNIVERSE inclusive - /// - /// # Arguments - /// msg: A string describing why/how the universe is an illegal universe. - /// - IllegalUniverse(msg: String) { - description("Attempted to use illegal universe, outwith allowed range of [E131_MIN_MULTICAST_UNIVERSE - - E131_MAX_MULTICAST_UNIVERSE] + E131_DISCOVERY_UNIVERSE inclusive"), - display("illegal universe used, outwith allowed range, msg: {}", msg) - } - - /// Attempted to use a universe that wasn't first registered for use. - /// To send from a universe with a sender it must first be registered. This allows universe discovery adverts to include the universe. - /// - /// # Arguments - /// msg: A string describing why the error was returned. - /// - UniverseNotRegistered(msg: String) { - description("Attempted to use a universe that wasn't first registered for use"), - display("Attempted to use a universe that wasn't first registered for use, msg: {}", msg) - } - - /// Ip version (ipv4 or ipv6) used when the other is expected. - /// - /// # Arguments - /// msg: A string describing the situation where the wrong IpVersion was encountered. - /// - IpVersionError(msg: String) { - description("Ip version (ipv4 or ipv6) used when the other is expected"), - display("Ip version (ipv4 or ipv6) used when the other is expected, msg: {}", msg) - } - - /// Attempted to use an unsupported (not Ipv4 or Ipv6) IP version. - /// - /// # Arguments - /// msg: A string describing the situation where an unsupported IP version is used. - /// - UnsupportedIpVersion(msg: String) { - description("Attempted to use an unsupported (not Ipv4 or Ipv6) IP version"), - display("Attempted to use an unsupported (not Ipv4 or Ipv6) IP version, msg: {}", msg) - } - - /// Attempted to use a sender which has already been terminated. - /// - /// # Arguments - /// msg: A string describing why the error was returned. - /// - SenderAlreadyTerminated(msg: String) { - description("Attempted to use a sender which has already been terminated"), - display("Attempted to use a sender which has already been terminated, msg: {}", msg) - } - - /// An error was encountered when attempting to merge DMX data together. - /// - /// # Arguments - /// msg: A string describing why the error was returned. - /// - DmxMergeError(msg: String) { - description("Error when merging DMX data"), - display("Error when merging DMX data, msg: {}", msg) - } - - /// Packet was received out of sequence and so should be discarded. - /// - /// # Arguments - /// msg: A string describing why the error was returned. - /// - OutOfSequence(msg: String) { - description("Packet was received out of sequence and so should be discarded"), - display("Packet was received out of sequence and so should be discarded, msg: {}", msg) - } - - /// A source terminated a universe and this was detected when trying to receive data. - /// This is only returned if the announce_stream_termination flag is set to true (default false). - /// - /// # Arguments - /// - /// src_cid: The CID of the source which sent the termination packet. - /// - /// uni: The universe that the termination packet is for. - /// - UniverseTerminated(src_cid: Uuid, uni: u16) { - description("A source terminated a universe and this was detected when trying to receive data"), - display("Source cid: {:?} terminated universe: {}", src_cid, uni) - } - - /// A source universe timed out as no data was received on that universe within E131_NETWORK_DATA_LOSS_TIMEOUT as per ANSI E1.31-2018 Section 6.7.1. - /// - /// # Arguments - /// - /// src_cid: The CID of the source which timed out. - /// - /// uni: The universe that timed out. - /// - UniverseTimeout(src_cid: Uuid, uni: u16) { - description("A source universe timed out as no data was received within E131_NETWORK_DATA_LOSS_TIMEOUT as per ANSI E1.31-2018 Section 6.7.1"), - display("(Source,Universe) timed out: ({},{})", src_cid, uni) - } - - /// When looking for a specific universe it wasn't found. This might happen for example if trying to mute a universe on a receiver that - /// wasn't being listened to. - /// - /// # Arguments - /// msg: A message describing why this error was returned. - /// - UniverseNotFound(msg: String) { - description("When looking for a specific universe it wasn't found"), - display("When looking for a specific universe it wasn't found, msg: {}", msg) - } - - /// Attempted to find a source and failed. This might happen on a receiver for example if trying to remove a source which was never - /// registered or discovered. - /// - /// # Arguments - /// msg: A message describing why this error was returned / when the source was not found. - /// - SourceNotFound(msg: String) { - description("When looking for a specific source it wasn't found"), - display("Source not found, msg: {}", msg) - } - - /// Thrown to indicate that the operation attempted is unsupported on the current OS - /// For example this is used to indicate that multicast-IPv6 isn't supported current on Windows. - /// - /// # Arguments - /// msg: A message describing why this error was returned / the operation that was not supported. - /// - OsOperationUnsupported(msg: String) { - description("Thrown to indicate that the operation attempted is unsupported on the current OS"), - display("Operation attempted is unsupported on the current OS, msg: {}", msg) - } - - /// Thrown to indicate that the source has corrupted for the reason specified by the error chain. - /// This is currently only thrown if the source mutex is poisoned by a thread with access panic-ing. - /// This prevents the panic propagating to the user of this library and allows them to handle it appropriately - /// such as by creating a new source. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the SourceCorrupt error was returned. - /// - SourceCorrupt(msg: String) { - description("The sACN source has corrupted due to an internal panic! and should no longer be used"), - display("The sACN source has corrupted due to an internal panic! and should no longer be used, {}", msg) - } - } + /// A specialized [`Result`] type for sACN operations. + /// + /// This type is used throughout the sACN crate for any operation which + /// can produce an error. + pub type Result = std::result::Result; + + #[derive(Debug, Error)] + pub enum SacnError { + // Allow IO errors to be used with the error system. + #[error("Io error occurred: {0}")] + Io(#[from] std::io::Error), + // Allow standard string library errors to be used with the error system. + #[error("String error occurred: {0}")] + Str(#[from] std::str::Utf8Error), + // Allow UUID library to be used with error system. + #[error("Uuid error occurred: {0}")] + Uuid(#[from] uuid::Error), + + /// Returned to indicate that too many bytes were read to fit into supplied buffer. + /// + /// # Arguments + /// usize: number of bytes read. + /// + /// usize: size of buffer. + /// + #[error("The given buffer fits {0} bytes, but {1} bytes were read.")] + TooManyBytesRead(usize, usize), + + // All parse/pack errors live within the same SacnError group as described in sacn_parse_packet_error. + #[error("SacnParsePack error occurred: {0}")] + SacnParsePackError(#[from] ParsePacketError), + + /// Returned to indicate that an invalid or malformed source name was used. + /// + /// # Arguments + /// String: A string describing why the source name is malformed. + /// + #[error("The given source name was malformed and couldn't be used, msg: {0}")] + MalformedSourceName(String), + + /// Attempted to perform an action using a priority value that is invalid. For example sending with a priority > 200. + /// This is distinct from the SacnParsePackError(ParseInvalidPriority) as it is for a local use of an invalid priority + /// rather than receiving an invalid priority from another source. + /// + /// # Arguments + /// The provided priority + /// + #[error( + "Priority must be within allowed range of [0-E131_MAX_PRIORITY], priority provided: {0}" + )] + InvalidPriority(u8), + + /// Used to indicate that the limit for the number of supported sources has been reached. + /// This is based on unique CID values. + /// as per ANSI E1.31-2018 Section 6.2.3.3. + /// + /// # Arguments + /// Number of sources + /// + #[error("Limit for the number of supported sources has been reached: {0}")] + SourcesExceededError(usize), + + /// A source was discovered by a receiver with the announce_discovery_flag set to true. + /// + /// # Arguments + /// The name of the source discovered. + /// + #[error("Source discovered with announce_discovery_flag set to true: {0}")] + SourceDiscovered(String), + + /// Attempted to exceed the capacity of a single universe (packet::UNIVERSE_CHANNEL_CAPACITY). + /// + /// # Arguments + /// Length of data provided. + /// + #[error("Attempted to exceed the capacity of a single universe, data len: {0}")] + ExceedUniverseCapacity(usize), + + /// Attempted to use illegal universe, outwith allowed range of [E131_MIN_MULTICAST_UNIVERSE, E131_MAX_MULTICAST_UNIVERSE] + /// + E131_DISCOVERY_UNIVERSE inclusive + /// + /// # Arguments + /// u16: The provided universe. + /// + #[error("Attempted to use an illegal universe: {0}")] + IllegalUniverse(u16), + + /// Attempted to use illegal universe as the sync universe, outwith allowed range of [E131_MIN_MULTICAST_UNIVERSE, E131_MAX_MULTICAST_UNIVERSE] + /// + E131_DISCOVERY_UNIVERSE inclusive + /// + /// # Arguments + /// u16: The provided synchronization universe. + /// + #[error("Attempted to use an illegal synchronization universe: {0}")] + IllegalSyncUniverse(u16), + + /// Attempted to use a universe that wasn't first registered for use. + /// To send from a universe with a sender it must first be registered. This allows universe discovery adverts to include the universe. + /// + /// # Arguments + /// u16: The universe that was not registered. + /// + #[error("Attempted to use a universe that wasn't registered: {0}")] + UniverseNotRegistered(u16), + + /// Ip version (ipv4 or ipv6) used when the other is expected. + /// + #[error("Multicast address and interface_addr not same IP version.")] + IpVersionError(), + + /// Attempted to use an unsupported (not Ipv4 or Ipv6) IP version. + /// + /// # Arguments + /// A string describing the situation where an unsupported IP version is used. + /// + #[error("Unsupported IP version used: {0}")] + UnsupportedIpVersion(String), + + /// Attempted to use a sender which has already been terminated. + /// + /// # Arguments + /// Name of terminated sender. + /// + #[error("Attempted to use a sender which has already been terminated: {0}")] + SenderAlreadyTerminated(String), + + /// An error was encountered when attempting to merge DMX data together. + /// + #[error( + "Error when merging DMX data. Attempted DMX merge on dmx data with different universes, synchronisation universes or data with no values" + )] + DmxMergeError(), + + /// Packet was received out of sequence and so should be discarded. + /// + /// # Arguments + /// u8: The sequence number of the packet received. + /// + /// u8: The last sequence number received. + /// + /// isize: The difference between the last and current sequence numbers. + /// + #[error("Packet received with sequence number {0} is out of sequence, last {1}, seq-diff {2}")] + OutOfSequence(u8, u8, isize), + + /// A source terminated a universe and this was detected when trying to receive data. + /// This is only returned if the announce_stream_termination flag is set to true (default false). + /// + /// # Arguments + /// Uuid: The CID of the source which sent the termination packet. + /// + /// u16: The universe that the termination packet is for. + /// + #[error("Source terminated universe, source cid: {0}, universe: {1}")] + UniverseTerminated(Uuid, u16), + + /// A source universe timed out as no data was received on that universe within E131_NETWORK_DATA_LOSS_TIMEOUT as per ANSI E1.31-2018 Section 6.7.1. + /// + /// # Arguments + /// uuid: The CID of the source which timed out. + /// + /// u16: The universe that timed out. + /// + #[error("Source universe timed out, source cid: {0}, universe: {1}")] + UniverseTimeout(Uuid, u16), + + /// When looking for a specific universe it wasn't found. This might happen for example if trying to mute a universe on a receiver that + /// wasn't being listened to. + /// + /// # Arguments + /// u16: The universe that was not found. + /// + #[error("When looking for a specific universe it wasn't found, universe: {0}")] + UniverseNotFound(u16), + + /// Attempted to find a source and failed. This might happen on a receiver for example if trying to remove a source which was never + /// registered or discovered. + /// + /// # Arguments + /// Uuid: The uuid of the source that was not found. + /// + #[error("Source not found: {0}")] + SourceNotFound(Uuid), + + /// Thrown to indicate that the operation attempted is unsupported on the current OS + /// For example this is used to indicate that multicast-IPv6 isn't supported current on Windows. + /// + /// # Arguments + /// String: A message describing why this error was returned / the operation that was not supported. + /// + #[error("Operation attempted is unsupported on the current OS: {0}")] + OsOperationUnsupported(String), + + /// Thrown to indicate that the source has corrupted for the reason specified by the error chain. + /// This is currently only thrown if the source mutex is poisoned by a thread with access panic-ing. + /// This prevents the panic propagating to the user of this library and allows them to handle it appropriately + /// such as by creating a new source. + /// + /// # Arguments + /// String: A message providing further details (if any) as to why the SourceCorrupt error was returned. + /// + #[error( + "The sACN source has corrupted due to an internal panic! and should no longer be used, {0}" + )] + SourceCorrupt(String), + + /// Returned if the data array has length 0 + /// + #[error("Data array has length 0, must provide data to send")] + DataArrayEmpty(), + + /// Returned if the universe list has length 0 + /// + #[error("Universe list has length 0, must provide at least one universe")] + UniverseListEmpty(), + + /// Returned if the receiver has a source limit of 0 + /// + #[error( + "Source_limit has a value of Some(0) which would indicate this receiver can never receive from any source" + )] + SourceLimitZero(), + + /// This indicates that the only universe that can be received is the discovery universe. + /// This means that having no timeout may lead to no data ever being received and so this method blocking forever + /// to prevent this likely unintended behaviour throw a universe not registered error. + /// + #[error( + "Attempting to receive data with no data universes registered, an infinite timeout and no discovery announcements" + )] + NoDataUniversesRegistered(), } } diff --git a/src/lib.rs b/src/lib.rs index 29cf09da..6665ec5d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,8 +77,8 @@ //! // This example will always timeout if run in isolation as there are no sources running on the network. //! match dmx_rcv.recv(TIMEOUT) { //! Err(e) => { -//! match e.kind() { -//! sacn::error::errors::ErrorKind::SourceDiscovered(source_name) => { +//! match e { +//! sacn::error::errors::SacnError::SourceDiscovered(source_name) => { //! println!("Source name: {} discovered!", source_name); //! } //! other => { @@ -188,9 +188,6 @@ // Recursion limit for error_chain. #![recursion_limit = "1024"] -#[macro_use] -extern crate error_chain; - /// The errors within the sACN crate related to parse/pack errors. /// Error-chain is used for errors within the library to allow chaining errors together to provide more informative backtraces. /// This completely replaces the old error system (sACN crate version 0.4.4) which relied on a simple Enum model without proper backtraces. diff --git a/src/packet.rs b/src/packet.rs index f43f7d86..e0d58911 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -52,9 +52,9 @@ //! # }} //! ``` -/// Uses the sACN error-chain errors. -use crate::error::errors::*; -use crate::sacn_parse_pack_error::sacn_parse_pack_error; +/// Uses the sACN errors. +use crate::error::errors::{Result, SacnError}; +use crate::sacn_parse_pack_error::sacn_parse_pack_error::ParsePacketError; /// The core crate is used for string processing during packet parsing/packing as well as to provide access to the Hash trait. use core::hash::{self, Hash}; @@ -376,13 +376,7 @@ pub fn is_universe_in_range(universe: u16) -> Result<()> { if (universe != E131_DISCOVERY_UNIVERSE) && (universe < E131_MIN_MULTICAST_UNIVERSE || universe > E131_MAX_MULTICAST_UNIVERSE) { - bail!(ErrorKind::IllegalUniverse( - format!( - "Universe must be in the range [{} - {}], universe: {}", - E131_MIN_MULTICAST_UNIVERSE, E131_MAX_MULTICAST_UNIVERSE, universe - ) - .to_string() - )); + return Err(SacnError::IllegalUniverse(universe)); } Ok(()) } @@ -401,7 +395,7 @@ fn zeros(buf: &mut [u8], n: usize) { /// buf: The byte buffer to parse into a str. /// /// # Errors -/// SourceNameInvalid: Returned if the source name is not null terminated as required by ANSI E1.31-2018 Section 6.2.2 +/// SourceNameNotNullTerminated: Returned if the source name is not null terminated as required by ANSI E1.31-2018 Section 6.2.2 /// #[inline] fn parse_source_name_str(buf: &[u8]) -> Result<&str> { @@ -414,10 +408,8 @@ fn parse_source_name_str(buf: &[u8]) -> Result<&str> { } if source_name_length == buf.len() && buf[buf.len() - 1] != 0 { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::SourceNameInvalid( - "Packet source name not null terminated".to_string() - ) + return Err(SacnError::SacnParsePackError( + ParsePacketError::SourceNameNotNullTerminated(), )); } @@ -437,22 +429,32 @@ macro_rules! impl_acn_root_layer_protocol { /// Parse the packet from the given buffer. pub fn parse(buf: &[u8]) -> Result { if buf.len() < (E131_PREAMBLE_SIZE as usize) { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData("Insufficient data for ACN root layer preamble".to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInsufficientData( + "Insufficient data for ACN root layer preamble".to_string(), + ), + )); } // Preamble Size if NetworkEndian::read_u16(&buf[0..2]) != E131_PREAMBLE_SIZE { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData("invalid Preamble Size".to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidData("invalid Preamble Size".to_string()), + )); } // Post-amble Size if NetworkEndian::read_u16(&buf[2..4]) != E131_POSTAMBLE_SIZE { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData("invalid Post-amble Size".to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidData("invalid Post-amble Size".to_string()), + )); } // ACN Packet Identifier if &buf[4 .. (E131_PREAMBLE_SIZE as usize)] != E131_ACN_PACKET_IDENTIFIER { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData("invalid ACN packet identifier".to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidData("invalid ACN packet identifier".to_string()), + )); } // PDU block @@ -473,17 +475,16 @@ macro_rules! impl_acn_root_layer_protocol { /// Grows the vector `buf` if necessary. pub fn pack_vec(&self, buf: &mut Vec) -> Result<()> { buf.clear(); - buf.reserve_exact(self.len()); - unsafe { - buf.set_len(self.len()); - } + buf.resize(self.len(), 0); self.pack(buf) } /// Packs the packet into the given buffer. pub fn pack(&self, buf: &mut [u8]) -> Result<()> { if buf.len() < self.len() { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData("invalid ACN packet identifier".to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidData("Invalid ACN packet identifier".to_string()) + )); } // Preamble Size @@ -538,18 +539,18 @@ struct PduInfo { /// fn pdu_info(buf: &[u8], vector_length: usize) -> Result { if buf.len() < E131_PDU_LENGTH_FLAGS_LENGTH + vector_length { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParseInsufficientData( - "Insufficient data when parsing pdu_info, no flags or length field".to_string() - ) + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInsufficientData( + "Insufficient data when parsing pdu_info, no flags or length field".to_string(), + ), )); } // Flags let flags = buf[0] & 0xf0; // Flags are stored in the top 4 bits. if flags != E131_PDU_FLAGS { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParsePduInvalidFlags(flags) + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParsePduInvalidFlags(flags), )); } // Length @@ -599,11 +600,17 @@ macro_rules! impl_e131_root_layer { // Length and Vector let PduInfo { length, vector } = pdu_info(&buf, E131_ROOT_LAYER_VECTOR_LENGTH)?; if buf.len() < length { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData("Buffer contains insufficient data based on ACN root layer pdu length field".to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInsufficientData( + "Buffer contains insufficient data based on ACN root layer pdu length field".to_string(), + ), + )); } if vector != VECTOR_ROOT_E131_DATA && vector != VECTOR_ROOT_E131_EXTENDED { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(vector))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::PduInvalidVector(vector), + )); } // CID @@ -618,7 +625,11 @@ macro_rules! impl_e131_root_layer { let data_buf = &buf[E131_CID_END_INDEX .. length]; let PduInfo { length, vector} = pdu_info(&data_buf, E131_FRAMING_LAYER_VECTOR_LENGTH)?; if buf.len() < length { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData("Buffer contains insufficient data based on E131 framing layer pdu length field".to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInsufficientData( + "Buffer contains insufficient data based on E131 framing layer pdu length field".to_string(), + ), + )); } match vector { @@ -632,10 +643,14 @@ macro_rules! impl_e131_root_layer { UniverseDiscoveryPacketFramingLayer::parse(data_buf)?, ) } - vector => bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(vector))), + vector => return Err(SacnError::SacnParsePackError( + ParsePacketError::PduInvalidVector(vector), + )), } } - vector => bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(vector))), + vector => return Err(SacnError::SacnParsePackError( + ParsePacketError::PduInvalidVector(vector), + )), }; Ok(E131RootLayer { @@ -646,7 +661,9 @@ macro_rules! impl_e131_root_layer { fn pack(&self, buf: &mut [u8]) -> Result<()> { if buf.len() < self.len() { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PackBufferInsufficient("".to_string()))) + return Err(SacnError::SacnParsePackError( + ParsePacketError::PackBufferInsufficient("".to_string()) + )); } // Flags and Length, flags are stored in the top 4 bits. @@ -744,11 +761,11 @@ macro_rules! impl_data_packet_framing_layer { // Length and Vector let PduInfo { length, vector } = pdu_info(&buf, E131_FRAMING_LAYER_VECTOR_LENGTH)?; if buf.len() < length { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData("Buffer contains insufficient data based on data packet framing layer pdu length field".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInsufficientData("Buffer contains insufficient data based on data packet framing layer pdu length field".to_string()))); } if vector != VECTOR_E131_DATA_PACKET { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(vector))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PduInvalidVector(vector))); } // Source Name @@ -761,20 +778,17 @@ macro_rules! impl_data_packet_framing_layer { // Priority let priority = buf[PRIORITY_INDEX]; if priority > E131_MAX_PRIORITY { - bail!( - ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParseInvalidPriority( - format!("Priority value: {} is outwith the allowed range", priority).to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidPriority(priority), + )); } // Synchronization Address let synchronization_address = NetworkEndian::read_u16(&buf[SYNC_ADDR_INDEX .. SEQ_NUM_INDEX]); if synchronization_address > E131_MAX_MULTICAST_UNIVERSE { - bail!( - ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParseInvalidSyncAddr( - format!("Sync_addr value: {} is outwith the allowed range", synchronization_address).to_string())) - ); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidSyncAddr(synchronization_address), + )); } // Sequence Number @@ -789,11 +803,10 @@ macro_rules! impl_data_packet_framing_layer { let universe = NetworkEndian::read_u16(&buf[UNIVERSE_INDEX .. DATA_INDEX]); if universe < E131_MIN_MULTICAST_UNIVERSE || universe > E131_MAX_MULTICAST_UNIVERSE { - bail!( - ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParseInvalidUniverse( - format!("Universe value: {} is outwith the allowed range", universe).to_string())) - ); + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidUniverse(universe), + )); + } // Data layer. @@ -814,7 +827,7 @@ macro_rules! impl_data_packet_framing_layer { fn pack(&self, buf: &mut [u8]) -> Result<()> { if buf.len() < self.len() { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PackBufferInsufficient("".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PackBufferInsufficient("".to_string()))); } // Flags and Length @@ -946,26 +959,26 @@ macro_rules! impl_data_packet_dmp_layer { // Length and Vector let PduInfo { length, vector } = pdu_info(&buf, E131_DATA_PACKET_DMP_LAYER_VECTOR_FIELD_LENGTH)?; if buf.len() < length { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData("Buffer contains insufficient data based on data packet dmp layer pdu length field".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInsufficientData("Buffer contains insufficient data based on data packet dmp layer pdu length field".to_string()))); } if vector != u32::from(VECTOR_DMP_SET_PROPERTY) { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(vector))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PduInvalidVector(vector))); } // Address and Data Type if buf[ADDRESS_DATA_FIELD_INDEX] != E131_DMP_LAYER_ADDRESS_DATA_FIELD { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData("invalid Address and Data Type".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInvalidData("invalid Address and Data Type".to_string()))); } // First Property Address if NetworkEndian::read_u16(&buf[FIRST_PRIORITY_FIELD_INDEX .. ADDRESS_INCREMENT_FIELD_INDEX]) != E131_DATA_PACKET_DMP_LAYER_FIRST_PROPERTY_FIELD { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData("invalid First Property Address".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInvalidData("invalid First Property Address".to_string()))); } // Address Increment if NetworkEndian::read_u16(&buf[ADDRESS_INCREMENT_FIELD_INDEX .. PROPERTY_VALUE_COUNT_FIELD_INDEX]) != E131_DATA_PACKET_DMP_LAYER_ADDRESS_INCREMENT { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData("invalid Address Increment".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInvalidData("invalid Address Increment".to_string()))); } // Property value count @@ -973,8 +986,8 @@ macro_rules! impl_data_packet_dmp_layer { // Check that the property value count matches the expected count based on the pdu length given previously. if property_value_count as usize + PROPERTY_VALUES_FIELD_INDEX != length { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParseInsufficientData( + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInsufficientData( format!("Invalid data packet dmp layer property value count, pdu length indicates {} property values, property value count field indicates {} property values", length , property_value_count) .to_string() @@ -986,7 +999,7 @@ macro_rules! impl_data_packet_dmp_layer { // The property value length is only of the property values and not the headers so start counting at the index that the property values start. let property_values_length = length - PROPERTY_VALUES_FIELD_INDEX; if property_values_length > UNIVERSE_CHANNEL_CAPACITY { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData("only 512 DMX slots allowed".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInvalidData("only 512 DMX slots allowed".to_string()))); } let mut property_values = Vec::with_capacity(property_values_length); @@ -1000,11 +1013,11 @@ macro_rules! impl_data_packet_dmp_layer { fn pack(&self, buf: &mut [u8]) -> Result<()> { if self.property_values.len() > UNIVERSE_CHANNEL_CAPACITY { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PackInvalidData("only 512 DMX values allowed".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PackInvalidData("only 512 DMX values allowed".to_string()))); } if buf.len() < self.len() { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PackBufferInsufficient("DataPacketDmpLayer pack buffer length insufficient".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PackBufferInsufficient("DataPacketDmpLayer pack buffer length insufficient".to_string()))); } // Flags and Length @@ -1097,18 +1110,18 @@ impl Pdu for SynchronizationPacketFramingLayer { // Length and Vector let PduInfo { length, vector } = pdu_info(&buf, E131_FRAMING_LAYER_VECTOR_LENGTH)?; if buf.len() < length { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData("Buffer contains insufficient data based on synchronisation packet framing layer pdu length field".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInsufficientData("Buffer contains insufficient data based on synchronisation packet framing layer pdu length field".to_string()))); } if vector != VECTOR_E131_EXTENDED_SYNCHRONIZATION { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::PduInvalidVector(vector) + return Err(SacnError::SacnParsePackError( + ParsePacketError::PduInvalidVector(vector), )); } if length != E131_UNIVERSE_SYNC_PACKET_FRAMING_LAYER_LENGTH { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::PduInvalidLength(length) + return Err(SacnError::SacnParsePackError( + ParsePacketError::PduInvalidLength(length), )); } @@ -1124,14 +1137,8 @@ impl Pdu for SynchronizationPacketFramingLayer { if synchronization_address > E131_MAX_MULTICAST_UNIVERSE || synchronization_address < E131_MIN_MULTICAST_UNIVERSE { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParseInvalidUniverse( - format!( - "Synchronisation address value: {} is outwith the allowed range", - synchronization_address - ) - .to_string() - ) + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidSyncAddr(synchronization_address), )); } @@ -1146,8 +1153,8 @@ impl Pdu for SynchronizationPacketFramingLayer { fn pack(&self, buf: &mut [u8]) -> Result<()> { if buf.len() < self.len() { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::PackBufferInsufficient( + return Err(SacnError::SacnParsePackError( + ParsePacketError::PackBufferInsufficient( "SynchronizationPacketFramingLayer pack buffer length insufficient".to_string() ) )); @@ -1224,15 +1231,15 @@ macro_rules! impl_universe_discovery_packet_framing_layer { // Length and Vector let PduInfo { length, vector } = pdu_info(&buf, E131_FRAMING_LAYER_VECTOR_LENGTH)?; if buf.len() < length { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData("Buffer contains insufficient data based on universe discovery packet framing layer pdu length field".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInsufficientData("Buffer contains insufficient data based on universe discovery packet framing layer pdu length field".to_string()))); } if vector != VECTOR_E131_EXTENDED_DISCOVERY { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(vector))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PduInvalidVector(vector))); } if length < E131_UNIVERSE_DISCOVERY_FRAMING_LAYER_MIN_LENGTH { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidLength(length))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PduInvalidLength(length))); } // Source Name @@ -1251,7 +1258,7 @@ macro_rules! impl_universe_discovery_packet_framing_layer { fn pack(&self, buf: &mut [u8]) -> Result<()> { if buf.len() < self.len() { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PackBufferInsufficient("UniverseDiscoveryPacketFramingLayer pack buffer length insufficient".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PackBufferInsufficient("UniverseDiscoveryPacketFramingLayer pack buffer length insufficient".to_string()))); } // Flags and Length @@ -1335,17 +1342,17 @@ macro_rules! impl_universe_discovery_packet_universe_discovery_layer { // Length and Vector let PduInfo { length, vector } = pdu_info(&buf, E131_DISCOVERY_LAYER_VECTOR_FIELD_LENGTH)?; if buf.len() != length { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData( + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInsufficientData( format!("Buffer contains incorrect amount of data ({} bytes) based on universe discovery packet universe discovery layer pdu length field ({} bytes)" , buf.len() ,length).to_string()))); } if vector != VECTOR_UNIVERSE_DISCOVERY_UNIVERSE_LIST { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(vector))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PduInvalidVector(vector))); } if length < E131_UNIVERSE_DISCOVERY_LAYER_MIN_LENGTH || length > E131_UNIVERSE_DISCOVERY_LAYER_MAX_LENGTH { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidLength(length))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PduInvalidLength(length))); } // Page @@ -1355,7 +1362,7 @@ macro_rules! impl_universe_discovery_packet_universe_discovery_layer { let last_page = buf[E131_DISCOVERY_LAYER_LAST_PAGE_FIELD_INDEX]; if page > last_page { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidPage("Page value higher than last_page".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::ParseInvalidPage("Page value higher than last_page".to_string()))); } // The number of universes, calculated by dividing the remaining space in the packet by the size of a single universe. @@ -1371,13 +1378,14 @@ macro_rules! impl_universe_discovery_packet_universe_discovery_layer { fn pack(&self, buf: &mut [u8]) -> Result<()> { if self.universes.len() > DISCOVERY_UNI_PER_PAGE { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::PackInvalidData( + return Err(SacnError::SacnParsePackError( + ParsePacketError::PackInvalidData( format!("Maximum {} universes allowed per discovery page", DISCOVERY_UNI_PER_PAGE).to_string()))); } if buf.len() < self.len() { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PackBufferInsufficient("UniverseDiscoveryPacketUniverseDiscoveryLayer pack buffer insufficient".to_string()))); + return Err(SacnError::SacnParsePackError( + ParsePacketError::PackBufferInsufficient("UniverseDiscoveryPacketUniverseDiscoveryLayer pack buffer insufficient".to_string()))); } // Flags and Length @@ -1396,10 +1404,10 @@ macro_rules! impl_universe_discovery_packet_universe_discovery_layer { // Universes for i in 1..self.universes.len() { if self.universes[i] == self.universes[i - 1] { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PackInvalidData("Universes are not unique".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PackInvalidData("Universes are not unique".to_string()))); } if self.universes[i] <= self.universes[i - 1] { - bail!(ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PackInvalidData("Universes are not sorted".to_string()))); + return Err(SacnError::SacnParsePackError(ParsePacketError::PackInvalidData("Universes are not sorted".to_string()))); } } NetworkEndian::write_u16_into( @@ -1468,8 +1476,8 @@ fn parse_universe_list<'a>(buf: &[u8], length: usize) -> Result> let mut last_universe: i32 = -1; if buf.len() < length * E131_UNIVERSE_FIELD_LENGTH { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParseInsufficientData( + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInsufficientData( format!("The given buffer of length {} bytes cannot be parsed into the given number of universes {}", buf.len(), length).to_string()))); } @@ -1482,8 +1490,8 @@ fn parse_universe_list<'a>(buf: &[u8], length: usize) -> Result> last_universe = u as i32; i = i + E131_UNIVERSE_FIELD_LENGTH; // Jump to the next universe. } else { - bail!(ErrorKind::SacnParsePackError( - sacn_parse_pack_error::ErrorKind::ParseInvalidUniverseOrder( + return Err(SacnError::SacnParsePackError( + ParsePacketError::ParseInvalidUniverseOrder( format!("Universe {} is out of order, discovery packet universe list must be in accending order!", u).to_string()))); } } @@ -1576,8 +1584,8 @@ mod test { false, "Universe to ipv4 multicast allowed below minimum allowed universe" ), - Err(e) => match e.kind() { - &ErrorKind::IllegalUniverse(ref _s) => assert!(true), + Err(e) => match e { + SacnError::IllegalUniverse(_) => assert!(true), _ => assert!(false, "Unexpected error type returned"), }, } @@ -1590,8 +1598,8 @@ mod test { false, "Universe to ipv4 multicast allowed above maximum allowed universe" ), - Err(e) => match e.kind() { - &ErrorKind::IllegalUniverse(ref _s) => assert!(true), + Err(e) => match e { + SacnError::IllegalUniverse(_) => assert!(true), _ => assert!(false, "Unexpected error type returned"), }, } @@ -1684,8 +1692,8 @@ mod test { false, "Universe to ipv4 multicast allowed below minimum allowed universe" ), - Err(e) => match e.kind() { - &ErrorKind::IllegalUniverse(ref _s) => assert!(true), + Err(e) => match e { + SacnError::IllegalUniverse(_) => assert!(true), _ => assert!(false, "Unexpected error type returned"), }, } @@ -1698,8 +1706,8 @@ mod test { false, "Universe to ipv4 multicast allowed above maximum allowed universe" ), - Err(e) => match e.kind() { - &ErrorKind::IllegalUniverse(ref _s) => assert!(true), + Err(e) => match e { + SacnError::IllegalUniverse(_) => assert!(true), _ => assert!(false, "Unexpected error type returned"), }, } diff --git a/src/receive.rs b/src/receive.rs index a378206d..93a5bbf3 100644 --- a/src/receive.rs +++ b/src/receive.rs @@ -24,7 +24,7 @@ use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use crate::packet::{E131RootLayerData::*, *}; /// Same reasoning as for packet meaning all sacn errors are imported. -use crate::error::errors::{ErrorKind::*, *}; +use crate::error::errors::*; /// The uuid crate is used for working with/generating UUIDs which sACN uses as part of the cid field in the protocol. /// This is used for uniquely identifying sources when counting sequence numbers. @@ -297,10 +297,7 @@ impl SacnReceiver { match source_limit { Some(x) => { if x == 0 { - bail!(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "Source_limit has a value of Some(0) which would indicate this receiver can never receive from any source" - )); + return Err(SacnError::SourceLimitZero()); } } None => {} @@ -412,7 +409,7 @@ impl SacnReceiver { /// If 1 or more universes in the list are already being listened to this method will have no effect for those universes only. /// /// # Errors - /// Returns an ErrorKind::IllegalUniverse error if the given universe is outwith the allowed range of universes, + /// Returns an SacnError::IllegalUniverse error if the given universe is outwith the allowed range of universes, /// see (is_universe_in_range)[fn.is_universe_in_range.packet]. /// /// @@ -443,7 +440,7 @@ impl SacnReceiver { /// Stops listening to the given universe. /// /// # Errors - /// Returns an ErrorKind::IllegalUniverse error if the given universe is outwith the allowed range of universes, + /// Returns an SacnError::IllegalUniverse error if the given universe is outwith the allowed range of universes, /// see (is_universe_in_range)[fn.is_universe_in_range.packet]. /// /// Returns UniverseNotFound if the given universe wasn't already being listened to. @@ -454,10 +451,7 @@ impl SacnReceiver { match self.universes.binary_search(&universe) { Err(_) => { // Universe isn't found. - bail!(ErrorKind::UniverseNotFound( - "Attempted to mute a universe that wasn't already being listened to" - .to_string() - )); + return Err(SacnError::UniverseNotFound(universe)); } Ok(i) => { // If value found then don't insert to avoid duplicates. @@ -500,7 +494,7 @@ impl SacnReceiver { /// This method will return a WouldBlock (unix) or TimedOut (windows) error if there is no data ready within the given timeout. /// A timeout of duration 0 will do timeout checks but otherwise will return a WouldBlock/TimedOut error without checking for data. /// - /// Will return ErrorKind::SourceDiscovered error if the announce_source_discovery flag is set and a universe discovery + /// Will return SacnError::SourceDiscovered error if the announce_source_discovery flag is set and a universe discovery /// packet is received and a source fully discovered. /// /// Will return a UniverseNotRegistered error if this method is called with an infinite timeout, no @@ -528,7 +522,7 @@ impl SacnReceiver { // This indicates that the only universe that can be received is the discovery universe. // This means that having no timeout may lead to no data ever being received and so this method blocking forever // to prevent this likely unintended behaviour throw a universe not registered error. - bail!(ErrorKind::UniverseNotRegistered("Attempting to receive data with no data universes registered, an infinite timeout and no discovery announcements".to_string())); + return Err(SacnError::NoDataUniversesRegistered()); } self.sequences.check_timeouts(self.announce_timeout)?; @@ -537,15 +531,17 @@ impl SacnReceiver { if timeout == Some(Duration::from_secs(0)) { if cfg!(target_os = "windows") { // Use the right expected error for the operating system. - bail!(std::io::Error::new( + return Err(std::io::Error::new( std::io::ErrorKind::TimedOut, - "No data available in given timeout" - )); + "No data available in given timeout", + ) + .into()); } else { - bail!(std::io::Error::new( + return Err(std::io::Error::new( std::io::ErrorKind::WouldBlock, - "No data available in given timeout" - )); + "No data available in given timeout", + ) + .into()); } } @@ -559,9 +555,7 @@ impl SacnReceiver { Some(E131_NETWORK_DATA_LOSS_TIMEOUT) }; - self.receiver - .set_timeout(actual_timeout) - .chain_err(|| "Failed to sent a timeout value for the receiver")?; + self.receiver.set_timeout(actual_timeout)?; // "Failed to sent a timeout value for the receiver" let start_time = Instant::now(); let mut buf: [u8; RCV_BUF_DEFAULT_SIZE] = [0; RCV_BUF_DEFAULT_SIZE]; @@ -576,7 +570,7 @@ impl SacnReceiver { let discovered_src: Option = self.handle_universe_discovery_packet(u); if discovered_src.is_some() && self.announce_source_discovery { - bail!(ErrorKind::SourceDiscovered(discovered_src.unwrap())); + return Err(SacnError::SourceDiscovered(discovered_src.unwrap())); } else { None } @@ -595,10 +589,11 @@ impl SacnReceiver { match timeout.unwrap().checked_sub(elapsed) { None => { // Indicates that elapsed is bigger than timeout so its time to return. - bail!(std::io::Error::new( + return Err(std::io::Error::new( std::io::ErrorKind::WouldBlock, - "No data available in given timeout" - )); + "No data available in given timeout", + ) + .into()); } Some(new_timeout) => return self.recv(Some(new_timeout)), } @@ -610,8 +605,8 @@ impl SacnReceiver { } } Err(err) => { - match err.kind() { - &ErrorKind::Io(ref s) => { + match err { + SacnError::Io(ref s) => { match s.kind() { // Windows and Unix use different error types (WouldBlock/TimedOut) for the same error. std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => { @@ -622,15 +617,17 @@ impl SacnReceiver { // Indicates that elapsed is bigger than timeout so its time to return. if cfg!(target_os = "windows") { // Use the right expected error for the operating system. - bail!(std::io::Error::new( + return Err(std::io::Error::new( std::io::ErrorKind::TimedOut, - "No data available in given timeout" - )); + "No data available in given timeout", + ) + .into()); } else { - bail!(std::io::Error::new( + return Err(std::io::Error::new( std::io::ErrorKind::WouldBlock, - "No data available in given timeout" - )); + "No data available in given timeout", + ) + .into()); } } Some(new_timeout) => return self.recv(Some(new_timeout)), @@ -756,7 +753,7 @@ impl SacnReceiver { if data_pkt.stream_terminated { self.terminate_stream(cid, data_pkt.source_name, data_pkt.universe); if self.announce_stream_termination { - bail!(ErrorKind::UniverseTerminated(cid, data_pkt.universe)); + return Err(SacnError::UniverseTerminated(cid, data_pkt.universe)); } return Ok(None); } @@ -1118,14 +1115,16 @@ impl SacnNetworkReceiver { let multicast_addr; if self.addr.is_ipv4() { - multicast_addr = universe_to_ipv4_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to IPv4 multicast addr")?; + multicast_addr = universe_to_ipv4_multicast_addr(universe)?; // "Failed to convert universe to IPv4 multicast addr" } else { - multicast_addr = universe_to_ipv6_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to IPv6 multicast addr")?; + multicast_addr = universe_to_ipv6_multicast_addr(universe)?; // "Failed to convert universe to IPv6 multicast addr" } - Ok(join_win_multicast(&self.socket, multicast_addr, self.addr.ip())?) + Ok(join_win_multicast( + &self.socket, + multicast_addr, + self.addr.ip(), + )?) } /// Removes this SacnNetworkReceiver from the multicast group which corresponds to the given universe. @@ -1138,11 +1137,9 @@ impl SacnNetworkReceiver { let multicast_addr; if self.addr.is_ipv4() { - multicast_addr = universe_to_ipv4_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to IPv4 multicast addr")?; + multicast_addr = universe_to_ipv4_multicast_addr(universe)?; // "Failed to convert universe to IPv4 multicast addr" } else { - multicast_addr = universe_to_ipv6_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to IPv6 multicast addr")?; + multicast_addr = universe_to_ipv6_multicast_addr(universe)?; // "Failed to convert universe to IPv6 multicast addr" } Ok(leave_win_multicast(&self.socket, multicast_addr)?) @@ -1162,8 +1159,8 @@ impl SacnNetworkReceiver { /// isn't supported i.e. Ipv6 on Windows. fn set_is_multicast_enabled(&mut self, val: bool) -> Result<()> { if val && self.is_ipv6() { - bail!(ErrorKind::OsOperationUnsupported( - "IPv6 multicast is currently unsupported on Windows".to_string() + return Err(SacnError::OsOperationUnsupported( + "IPv6 multicast is currently unsupported on Windows".to_string(), )); } self.is_multicast_enabled = val; @@ -1181,9 +1178,7 @@ impl SacnNetworkReceiver { /// This will return an error if the SacnReceiver wasn't created using an IPv6 address to bind to. fn set_only_v6(&mut self, val: bool) -> Result<()> { if self.addr.is_ipv4() { - bail!(IpVersionError( - "No data available in given timeout".to_string() - )) + return Err(SacnError::IpVersionError()); } else { Ok(self.socket.set_only_v6(val)?) } @@ -1213,8 +1208,11 @@ impl SacnNetworkReceiver { &mut self, buf: &'a mut [u8; RCV_BUF_DEFAULT_SIZE], ) -> Result> { - self.socket.read_exact(buf)?; - + // use read() for the windows impl, since windows does not like using read_exact() + let n = self.socket.read(buf)?; + if n > RCV_BUF_DEFAULT_SIZE { + return Err(SacnError::TooManyBytesRead(n, buf.len())) + } Ok(AcnRootLayerProtocol::parse(buf)?) } @@ -1269,11 +1267,9 @@ impl SacnNetworkReceiver { let multicast_addr; if self.addr.is_ipv4() { - multicast_addr = universe_to_ipv4_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to IPv4 multicast addr")?; + multicast_addr = universe_to_ipv4_multicast_addr(universe)?; } else { - multicast_addr = universe_to_ipv6_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to IPv6 multicast addr")?; + multicast_addr = universe_to_ipv6_multicast_addr(universe)?; } Ok(join_unix_multicast( @@ -1293,11 +1289,9 @@ impl SacnNetworkReceiver { let multicast_addr; if self.addr.is_ipv4() { - multicast_addr = universe_to_ipv4_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to IPv4 multicast addr")?; + multicast_addr = universe_to_ipv4_multicast_addr(universe)?; } else { - multicast_addr = universe_to_ipv6_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to IPv6 multicast addr")?; + multicast_addr = universe_to_ipv6_multicast_addr(universe)?; } Ok(leave_unix_multicast( @@ -1335,9 +1329,7 @@ impl SacnNetworkReceiver { /// This will return an error if the SacnReceiver wasn't created using an IPv6 address to bind to. fn set_only_v6(&mut self, val: bool) -> Result<()> { if self.addr.is_ipv4() { - bail!(IpVersionError( - "No data available in given timeout".to_string() - )) + return Err(SacnError::IpVersionError()); } else { Ok(self.socket.set_only_v6(val)?) } @@ -1366,8 +1358,11 @@ impl SacnNetworkReceiver { &mut self, buf: &'a mut [u8; RCV_BUF_DEFAULT_SIZE], ) -> Result> { - self.socket.read_exact(buf)?; - + // use read() since read_exact() was not passing the tests. + let n = self.socket.read(buf)?; + if n > RCV_BUF_DEFAULT_SIZE { + return Err(SacnError::TooManyBytesRead(n, buf.len())) + } Ok(AcnRootLayerProtocol::parse(buf)?) } @@ -1526,30 +1521,36 @@ fn join_unix_multicast(socket: &Socket, addr: SockAddr, interface_addr: IpAddr) IpAddr::V4(ref interface_v4) => { socket .join_multicast_v4(a.ip(), &interface_v4) - .chain_err(|| "Failed to join IPv4 multicast")?; + .map_err(|e| { + SacnError::Io(std::io::Error::new( + e.kind(), + "Failed to join IPv4 multicast", + )) + })?; } IpAddr::V6(ref _interface_v6) => { - bail!(ErrorKind::IpVersionError( - "Multicast address and interface_addr not same IP version".to_string() - )); + return Err(SacnError::IpVersionError()); } }, None => { - bail!(ErrorKind::UnsupportedIpVersion("IP version recognised as AF_INET but not actually usable as AF_INET so must be unknown type".to_string())); + return Err(SacnError::UnsupportedIpVersion("IP version recognised as AF_INET but not actually usable as AF_INET so must be unknown type".to_string())); } }, AF_INET6 => match addr.as_socket_ipv6() { Some(a) => { - socket - .join_multicast_v6(a.ip(), 0) - .chain_err(|| "Failed to join IPv6 multicast")?; + socket.join_multicast_v6(a.ip(), 0).map_err(|e| { + SacnError::Io(std::io::Error::new( + e.kind(), + "Failed to join IPv6 multicast", + )) + })?; } None => { - bail!(ErrorKind::UnsupportedIpVersion("IP version recognised as AF_INET6 but not actually usable as AF_INET6 so must be unknown type".to_string())); + return Err(SacnError::UnsupportedIpVersion("IP version recognised as AF_INET6 but not actually usable as AF_INET6 so must be unknown type".to_string())); } }, x => { - bail!(ErrorKind::UnsupportedIpVersion(format!("IP version not recognised as AF_INET (Ipv4) or AF_INET6 (Ipv6) - family value (as i32): {}", x).to_string())); + return Err(SacnError::UnsupportedIpVersion(format!("IP version not recognised as AF_INET (Ipv4) or AF_INET6 (Ipv6) - family value (as i32): {}", x).to_string())); } }; @@ -1577,30 +1578,36 @@ fn leave_unix_multicast(socket: &Socket, addr: SockAddr, interface_addr: IpAddr) IpAddr::V4(ref interface_v4) => { socket .leave_multicast_v4(a.ip(), &interface_v4) - .chain_err(|| "Failed to leave IPv4 multicast")?; + .map_err(|e| { + SacnError::Io(std::io::Error::new( + e.kind(), + "Failed to leave IPv4 multicast", + )) + })?; } IpAddr::V6(ref _interface_v6) => { - bail!(ErrorKind::IpVersionError( - "Multicast address and interface_addr not same IP version".to_string() - )); + return Err(SacnError::IpVersionError()); } }, None => { - bail!(ErrorKind::UnsupportedIpVersion("IP version recognised as AF_INET but not actually usable as AF_INET so must be unknown type".to_string())); + return Err(SacnError::UnsupportedIpVersion("IP version recognised as AF_INET but not actually usable as AF_INET so must be unknown type".to_string())); } }, AF_INET6 => match addr.as_socket_ipv6() { Some(a) => { - socket - .leave_multicast_v6(a.ip(), 0) - .chain_err(|| "Failed to leave IPv6 multicast")?; + socket.leave_multicast_v6(a.ip(), 0).map_err(|e| { + SacnError::Io(std::io::Error::new( + e.kind(), + "Failed to leave IPv6 multicast", + )) + })?; } None => { - bail!(ErrorKind::UnsupportedIpVersion("IP version recognised as AF_INET6 but not actually usable as AF_INET6 so must be unknown type".to_string())); + return Err(SacnError::UnsupportedIpVersion("IP version recognised as AF_INET6 but not actually usable as AF_INET6 so must be unknown type".to_string())); } }, x => { - bail!(ErrorKind::UnsupportedIpVersion(format!("IP version not recognised as AF_INET (Ipv4) or AF_INET6 (Ipv6) - family value (as i32): {}", x).to_string())); + return Err(SacnError::UnsupportedIpVersion(format!("IP version not recognised as AF_INET (Ipv4) or AF_INET6 (Ipv6) - family value (as i32): {}", x).to_string())); } }; @@ -1658,30 +1665,36 @@ fn join_win_multicast(socket: &Socket, addr: SockAddr, interface_addr: IpAddr) - IpAddr::V4(ref interface_v4) => { socket .join_multicast_v4(a.ip(), &interface_v4) - .chain_err(|| "Failed to join IPv4 multicast")?; + .map_err(|e| { + SacnError::Io(std::io::Error::new( + e.kind(), + "Failed to join IPv4 multicast", + )) + })?; } IpAddr::V6(ref _interface_v6) => { - bail!(ErrorKind::IpVersionError( - "Multicast address and interface_addr not same IP version".to_string() - )); + return Err(SacnError::IpVersionError()); } }, None => { - bail!(ErrorKind::UnsupportedIpVersion("IP version recognised as AF_INET but not actually usable as AF_INET so must be unknown type".to_string())); + return Err(SacnError::UnsupportedIpVersion("IP version recognised as AF_INET but not actually usable as AF_INET so must be unknown type".to_string())); } }, AF_INET6 => match addr.as_socket_ipv6() { Some(a) => { - socket - .join_multicast_v6(a.ip(), 0) - .chain_err(|| "Failed to join IPv6 multicast")?; + socket.join_multicast_v6(a.ip(), 0).map_err(|e| { + SacnError::Io(std::io::Error::new( + e.kind(), + "Failed to join IPv6 multicast", + )) + })?; } None => { - bail!(ErrorKind::UnsupportedIpVersion("IP version recognised as AF_INET6 but not actually usable as AF_INET6 so must be unknown type".to_string())); + return Err(SacnError::UnsupportedIpVersion("IP version recognised as AF_INET6 but not actually usable as AF_INET6 so must be unknown type".to_string())); } }, x => { - bail!(ErrorKind::UnsupportedIpVersion(format!("IP version not recognised as AF_INET (Ipv4) or AF_INET6 (Ipv6) - family value (as i32): {}", x).to_string())); + return Err(SacnError::UnsupportedIpVersion(format!("IP version not recognised as AF_INET (Ipv4) or AF_INET6 (Ipv6) - family value (as i32): {}", x).to_string())); } }; @@ -1710,24 +1723,29 @@ fn leave_win_multicast(socket: &Socket, addr: SockAddr) -> Result<()> { Some(a) => { socket .leave_multicast_v4(a.ip(), &Ipv4Addr::new(0, 0, 0, 0)) - .chain_err(|| "Failed to leave IPv4 multicast")?; + .map_err(|e| { + SacnError::Io(std::io::Error::new( + e.kind(), + "Failed to leave IPv4 multicast", + )) + })?; } None => { - bail!(ErrorKind::UnsupportedIpVersion("IP version recognised as AF_INET but not actually usable as AF_INET so must be unknown type".to_string())); + return Err(SacnError::UnsupportedIpVersion("IP version recognised as AF_INET but not actually usable as AF_INET so must be unknown type".to_string())); } }, AF_INET6 => match addr.as_socket_ipv6() { Some(_) => { - bail!(ErrorKind::OsOperationUnsupported( - "IPv6 multicast is currently unsupported on Windows".to_string() + return Err(SacnError::OsOperationUnsupported( + "IPv6 multicast is currently unsupported on Windows".to_string(), )); } None => { - bail!(ErrorKind::UnsupportedIpVersion("IP version recognised as AF_INET6 but not actually usable as AF_INET6 so must be unknown type".to_string())); + return Err(SacnError::UnsupportedIpVersion("IP version recognised as AF_INET6 but not actually usable as AF_INET6 so must be unknown type".to_string())); } }, x => { - bail!(ErrorKind::UnsupportedIpVersion(format!("IP version not recognised as AF_INET (Ipv4) or AF_INET6 (Ipv6) - family value (as i32): {}", x).to_string())); + return Err(SacnError::UnsupportedIpVersion(format!("IP version not recognised as AF_INET (Ipv4) or AF_INET6 (Ipv6) - family value (as i32): {}", x).to_string())); } }; @@ -1948,9 +1966,7 @@ fn check_seq_number( if source_limit.is_none() || src_sequences.len() < source_limit.unwrap() { src_sequences.insert(cid, HashMap::new()); } else { - bail!(ErrorKind::SourcesExceededError( - format!("Already at max sources: {}", src_sequences.len()).to_string() - )); + return Err(SacnError::SourcesExceededError(src_sequences.len())); } } Some(_) => {} @@ -1992,12 +2008,10 @@ fn check_seq_number( if seq_diff <= E131_SEQ_DIFF_DISCARD_UPPER_BOUND && seq_diff > E131_SEQ_DIFF_DISCARD_LOWER_BOUND { // Reject the out of order packet as per ANSI E1.31-2018 Section 6.7.2 Sequence Numbering. - bail!(ErrorKind::OutOfSequence( - format!( - "Packet received with sequence number {} is out of sequence, last {}, seq-diff {}", - sequence_number, expected_seq.sequence_number, seq_diff - ) - .to_string() + return Err(SacnError::OutOfSequence( + sequence_number, + expected_seq.sequence_number, + seq_diff, )); } @@ -2060,9 +2074,9 @@ fn check_timeouts( // Remove source if all its universes have timed out src_sequences.remove(&timedout_src_id.unwrap()); } - bail!(ErrorKind::UniverseTimeout( + return Err(SacnError::UniverseTimeout( timedout_src_id.unwrap(), - timedout_uni.unwrap() + timedout_uni.unwrap(), )); } } @@ -2108,9 +2122,7 @@ fn remove_source_universe_seq( match src_sequences.remove(&src_cid) { Some(_x) => Ok(()), None => { - bail!(ErrorKind::SourceNotFound( - "Could not find the source so could not remove it".to_string() - )); + return Err(SacnError::SourceNotFound(src_cid)); } } } else { @@ -2118,15 +2130,12 @@ fn remove_source_universe_seq( } } None => { - bail!(ErrorKind::UniverseNotFound("Could not find universe within source in sequence numbers so could not remove it".to_string())); + return Err(SacnError::UniverseNotFound(universe)); } } } None => { - bail!(ErrorKind::SourceNotFound( - "Could not find the source in the sequence numbers so could not remove it" - .to_string() - )); + return Err(SacnError::SourceNotFound(src_cid)); } } } @@ -2167,7 +2176,7 @@ pub fn htp_dmx_merge(i: &DMXData, n: &DMXData) -> Result { || i.values[0] != n.values[0] || i.sync_uni != n.sync_uni { - bail!(DmxMergeError("Attempted DMX merge on dmx data with different universes, synchronisation universes or data with no values".to_string())); + return Err(SacnError::DmxMergeError()); } if i.priority > n.priority { @@ -2662,7 +2671,7 @@ mod test { // Check that the third data packet with the low sequence number is rejected correctly with the expected OutOfSequence error. match dmx_rcv.handle_data_packet(src_cid, data_packet3) { - Err(Error(OutOfSequence(_), _)) => { + Err(SacnError::OutOfSequence(..)) => { assert!( true, "Receiver correctly rejected third data packet with correct error" @@ -2751,7 +2760,7 @@ mod test { let diff: i16 = ((i as i16) - (LAST_SEQ_NUM as i16)) as i16; match res { - Err(Error(OutOfSequence(_), _)) => { + Err(SacnError::OutOfSequence(..)) => { // Data packet was rejected due to sequence number. if (diff <= REJECT_RANGE_UPPER_BOUND) && (diff > REJECT_RANGE_LOWER_BOUND) { assert!( @@ -2862,7 +2871,7 @@ mod test { let diff: i16 = ((i as i16) - (LAST_SEQ_NUM as i16)) as i16; match res { - Err(Error(OutOfSequence(_), _)) => { + Err(SacnError::OutOfSequence(..)) => { // Sync packet was rejected due to sequence number. if (diff <= REJECT_RANGE_UPPER_BOUND) && (diff > REJECT_RANGE_LOWER_BOUND) { assert!( @@ -2941,7 +2950,7 @@ mod test { // Check that the third sync packet with the low sequence number is rejected correctly with the expected OutOfSequence error. match dmx_rcv.handle_sync_packet(src_cid, sync_packet3) { - Err(Error(OutOfSequence(_), _)) => { + Err(SacnError::OutOfSequence(..)) => { assert!( true, "Receiver correctly rejected third sync packet with correct error" @@ -3231,15 +3240,10 @@ mod test { let source_limit: Option = Some(0); match SacnReceiver::with_ip(addr, source_limit) { - Err(e) => match e.kind() { - ErrorKind::Io(x) => match x.kind() { - std::io::ErrorKind::InvalidInput => { - assert!(true, "Correct error returned"); - } - _ => { - assert!(false, "Expected error returned"); - } - }, + Err(e) => match e { + SacnError::SourceLimitZero() => { + assert!(true, "Correct error returned"); + } _ => { assert!(false, "Unexpected error type returned"); } diff --git a/src/sacn_parse_pack_error.rs b/src/sacn_parse_pack_error.rs index f87b4fbd..e7e458bf 100644 --- a/src/sacn_parse_pack_error.rs +++ b/src/sacn_parse_pack_error.rs @@ -9,162 +9,141 @@ /// The errors used within the SacnLibrary specifically those related to parsing and packeting packets received/sent on the network. /// + pub mod sacn_parse_pack_error { - error_chain! { - errors { - /// When parsing packet invalid data encountered. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to what data was invalid. - /// - ParseInvalidData(msg: String) { - description("Data provided to parse into a packet is invalid"), - display("Error when parsing data into packet, msg: {}", msg) - } - - /// Attempted to parse a priority value that is outwith the allowed range of [0, E131_MAX_PRIORITY]. - /// As per ANSI E1.31-2018 Section 6.2.3 - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the priority valid was invalid. - /// - ParseInvalidPriority(msg: String) { - description("Attempted to parse a priority value that is outwith the allowed range of [0, 200]"), - display("Attempted to parse a priority value that is outwith the allowed range of [0, 200], msg: {}", msg) - } - - /// Attempted to parse a page value that is invalid - e.g. the page value is higher than the last_page value. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the page was invalid. - /// - ParseInvalidPage(msg: String) { - description("Attempted to parse a page value that is invalid"), - display("Error when parsing page value, msg: {}", msg) - } - - /// Attempted to parse a sync address value that is outwith the allowed range of [0, E131_MAX_MULTICAST_UNIVERSE]. - /// As per ANSI E1.31-2018 Section 9.1.1. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the synchronisation address was invalid. - /// - ParseInvalidSyncAddr(msg: String) { - description("Attempted to parse a sync_addr value that is outwith the allowed range of [0, 63999]"), - display("Attempted to parse a sync_addr value that is outwith the allowed range of [0, 63999], msg: {}", msg) - } - - /// Attempted to parse a universe value that is outwith the allowed range of [1, E131_MAX_MULTICAST_UNIVERSE]. - /// As per ANSI E1.31-2018 Section 9.1.1. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the universe field was invalid. - /// - ParseInvalidUniverse(msg: String) { - description("Attempted to parse a universe value that is outwith the allowed range of [1, 63999]"), - display("Attempted to parse a universe value that is outwith the allowed range of [1, 63999], msg: {}", msg) - } - - /// Attempted to parse a packet with an invalid ordering of universes. - /// For example a discovery packet where the universes aren't correctly ordered in assending order. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the universe ordering was invalid. - /// - ParseInvalidUniverseOrder(msg: String) { - description("Attempted to parse a packet with an invalid ordering of universes"), - display("Attempted to parse a packet with an invalid ordering of universes, msg: {}", msg) - } - - /// When packing a packet into a buffer invalid data encountered. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the data couldn't be packed. - /// - PackInvalidData(msg: String) { - description("When packing a packet into a buffer invalid data encountered"), - display("When packing a packet into a buffer invalid data encountered, msg: {}", msg) - } - - /// Supplied buffer is not large enough to pack packet into. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the pack buffer is insufficient. - /// - PackBufferInsufficient(msg: String) { - description("Supplied buffer is not large enough to pack packet into"), - display("Supplied buffer is not large enough to pack packet into, msg: {}", msg) - } - - /// Supplied buffer does not contain enough data. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why there was insufficient data for parsing. - /// - ParseInsufficientData(msg: String) { - description("Supplied buffer does not contain enough data"), - display("Supplied buffer does not contain enough data, msg: {}", msg) - } - - /// Received PDU flags are invalid for parsing. - /// - /// # Arguments - /// flags: The flags that were found which are invalid. - /// - ParsePduInvalidFlags(flags: u8) { - description("Received PDU flags are invalid"), - display("PDU Flags {:#b} are invalid for parsing", flags) - } - - /// Received PDU length is invalid. - /// - /// # Arguments - /// len: The length provided in the Pdu which is invalid. - /// - PduInvalidLength(len: usize) { - description("Received PDU length is invalid"), - display("PDU Length {} is invalid", len) - } - - /// Received PDU vector is invalid/unsupported by this library. - /// - /// # Arguments - /// vec: The vector parsed which is invalid / cannot be used. - /// - PduInvalidVector(vec: u32) { - description("Received PDU vector is invalid/unsupported by this library"), - display("Vector {:#x} not supported", vec) - } - - /// Error parsing the received UUID. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the uuid (used for CID) couldn't be parsed. - /// - UuidError(msg: String) { - description("Error parsing the received UUID"), - display("Error parsing the received UUID, msg: {}", msg) - } - - /// Error parsing received UTF8 string. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the string couldn't be parsed. - /// - Utf8Error(msg: String) { - description("Error parsing received UTF8 string"), - display("Error parsing received UTF8 string, msg: {}", msg) - } - - /// Source name in packet was invalid, for example due to not being null terminated. - /// - /// # Arguments - /// msg: A message providing further details (if any) as to why the source name was invalid. - /// - SourceNameInvalid(msg: String) { - description("Attempted to parse invalid source name"), - display("Attempted to parse invalid source name, msg: {}", msg) - } - } + use thiserror::Error; + use uuid::Uuid; + + #[derive(Debug, Error)] + pub enum ParsePacketError { + /// When parsing packet invalid data encountered. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to what data was invalid. + /// + #[error("Error when parsing data into packet, msg: {0}")] + ParseInvalidData(String), + + /// Attempted to parse a priority value that is outwith the allowed range of [0, E131_MAX_PRIORITY]. + /// As per ANSI E1.31-2018 Section 6.2.3 + /// + /// # Arguments + /// u8: the priority value that was invalid. + /// + #[error( + "Attempted to parse a priority value that is outwith the allowed range of [0, 200]: {0}" + )] + ParseInvalidPriority(u8), + + /// Attempted to parse a page value that is invalid - e.g. the page value is higher than the last_page value. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to why the page was invalid. + /// + #[error("Error when parsing page value, msg: {0}")] + ParseInvalidPage(String), + + /// Attempted to parse a sync address value that is outwith the allowed range of [0, E131_MAX_MULTICAST_UNIVERSE]. + /// As per ANSI E1.31-2018 Section 9.1.1. + /// + /// # Arguments + /// u16: the synchronisation address that was invalid. + /// + #[error( + "Attempted to parse a sync_addr value that is outwith the allowed range of [0, 63999]: {0}" + )] + ParseInvalidSyncAddr(u16), + + /// Attempted to parse a universe value that is outwith the allowed range of [1, E131_MAX_MULTICAST_UNIVERSE]. + /// As per ANSI E1.31-2018 Section 9.1.1. + /// + /// # Arguments + /// u16: the universe value that was invalid. + /// + #[error( + "Attempted to parse a universe value that is outwith the allowed range of [1, 63999]: {0}" + )] + ParseInvalidUniverse(u16), + + /// Attempted to parse a packet with an invalid ordering of universes. + /// For example a discovery packet where the universes aren't correctly ordered in assending order. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to why the universe ordering was invalid. + /// + #[error("Attempted to parse a packet with an invalid ordering of universes, msg: {0}")] + ParseInvalidUniverseOrder(String), + + /// When packing a packet into a buffer invalid data encountered. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to why the data couldn't be packed. + /// + #[error("When packing a packet into a buffer invalid data encountered, msg: {0}")] + PackInvalidData(String), + + /// Supplied buffer is not large enough to pack packet into. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to why the pack buffer is insufficient. + /// + #[error("Supplied buffer is not large enough to pack packet into, msg: {0}")] + PackBufferInsufficient(String), + + /// Supplied buffer does not contain enough data. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to why there was insufficient data for parsing. + /// + #[error("Supplied buffer does not contain enough data, msg: {0}")] + ParseInsufficientData(String), + + /// Received PDU flags are invalid for parsing. + /// + /// # Arguments + /// flags: The flags that were found which are invalid. + /// + #[error("PDU Flags {0:#b} are invalid for parsing")] + ParsePduInvalidFlags(u8), + + /// Received PDU length is invalid. + /// + /// # Arguments + /// len: The length provided in the Pdu which is invalid. + /// + #[error("PDU Length {0} is invalid")] + PduInvalidLength(usize), + + /// Received PDU vector is invalid/unsupported by this library. + /// + /// # Arguments + /// vec: The vector parsed which is invalid / cannot be used. + /// + #[error("Vector {0:#x} not supported")] + PduInvalidVector(u32), + + /// Error parsing the received UUID. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to why the uuid (used for CID) couldn't be parsed. + /// + #[error("Error parsing the received UUID: {0}")] + UuidError(Uuid), + + /// Error parsing received UTF8 string. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to why the string couldn't be parsed. + /// + #[error("Error parsing received UTF8 string, msg: {0}")] + Utf8Error(String), + + /// Source name in packet was not null terminated. + /// + /// # Arguments + /// msg: A message providing further details (if any) as to why the source name was invalid. + /// + #[error("Source name in packet was not null terminated.")] + SourceNameNotNullTerminated(), } } diff --git a/src/source.rs b/src/source.rs index 06b0a282..cd105280 100644 --- a/src/source.rs +++ b/src/source.rs @@ -196,8 +196,8 @@ impl SacnSource { /// pub fn with_cid_ip(name: &str, cid: Uuid, ip: SocketAddr) -> Result { if name.len() > E131_SOURCE_NAME_FIELD_LENGTH { - bail!(ErrorKind::MalformedSourceName( - "Source name provided is longer than maximum allowed".to_string() + return Err(SacnError::MalformedSourceName( + "Source name provided is longer than maximum allowed".to_string(), )); } @@ -595,8 +595,8 @@ impl SacnSourceInternal { } else if ip.is_ipv6() { Socket::new(Domain::IPV6, Type::DGRAM, None).unwrap() } else { - bail!(ErrorKind::UnsupportedIpVersion( - "Address to create SacnSource is not IPv4 or IPv6".to_string() + return Err(SacnError::UnsupportedIpVersion( + "Address to create SacnSource is not IPv4 or IPv6".to_string(), )); }; @@ -694,9 +694,7 @@ impl SacnSourceInternal { match self.universes.binary_search(&universe) { Err(_i) => { // Value not found - bail!(ErrorKind::UniverseNotFound( - "Attempted to de-register a universe that was never registered".to_string() - )) + return Err(SacnError::UniverseNotFound(universe)); } Ok(i) => { // Value found, i is index. @@ -717,9 +715,7 @@ impl SacnSourceInternal { is_universe_in_range(*u)?; if !self.universes.contains(u) { - bail!(ErrorKind::UniverseNotRegistered( - format!("Attempted to send on unregistered universe : {}", u).to_string() - )); + return Err(SacnError::UniverseNotRegistered(*u)); } Ok(()) @@ -772,16 +768,13 @@ impl SacnSourceInternal { ) -> Result<()> { if self.running == false { // Indicates that this sender has been terminated. - bail!(ErrorKind::SenderAlreadyTerminated( - "Attempted to send".to_string() + return Err(SacnError::SenderAlreadyTerminated( + "Attempted to send".to_string(), )); } if data.len() == 0 { - bail!(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "Must provide data to send, data.len() == 0" - )); + return Err(SacnError::DataArrayEmpty()); } // Check all the given universes are valid before doing any action. @@ -793,7 +786,7 @@ impl SacnSourceInternal { // Check that the synchronisation universe is also valid. if synchronisation_addr.is_some() { self.universe_allowed(&synchronisation_addr.unwrap()) - .chain_err(|| "Synchronisation universe not allowed")?; + .map_err(|_| SacnError::IllegalSyncUniverse(synchronisation_addr.unwrap()))?; } // + 1 as there must be at least 1 universe required as the data isn't empty then additional universes for any more. @@ -801,13 +794,7 @@ impl SacnSourceInternal { (data.len() as f64 / UNIVERSE_CHANNEL_CAPACITY as f64).ceil() as usize; if universes.len() < required_universes { - bail!(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - format!( - "Must provide enough universes to send on, universes provided: {}", - universes.len() - ) - )); + return Err(SacnError::UniverseListEmpty()); } for i in 0..required_universes { @@ -859,17 +846,11 @@ impl SacnSourceInternal { sync_address: u16, ) -> Result<()> { if priority > E131_MAX_PRIORITY { - bail!(ErrorKind::InvalidPriority(format!( - "Priority must be within allowed range of [0-E131_MAX_PRIORITY], priority provided: {}", - priority - ))); + return Err(SacnError::InvalidPriority(priority)); } if data.len() > UNIVERSE_CHANNEL_CAPACITY { - bail!(ErrorKind::ExceedUniverseCapacity(format!( - "Data provided must fit in a single universe, data len: {}", - data.len() - ))); + return Err(SacnError::ExceedUniverseCapacity(data.len())); } let mut sequence = match self.data_sequences.borrow().get(&universe) { @@ -903,21 +884,23 @@ impl SacnSourceInternal { if dst_ip.is_some() { self.socket .send_to(&packet.pack_alloc().unwrap(), &dst_ip.unwrap().into()) - .chain_err(|| "Failed to send data unicast on socket")?; + .map_err(|e| { + std::io::Error::new(e.kind(), "Failed to send data unicast on socket") + })?; } else { let dst; if self.addr.is_ipv6() { - dst = universe_to_ipv6_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to Ipv6 multicast address")?; + dst = universe_to_ipv6_multicast_addr(universe)?; } else { - dst = universe_to_ipv4_multicast_addr(universe) - .chain_err(|| "Failed to convert universe to Ipv4 multicast address")?; + dst = universe_to_ipv4_multicast_addr(universe)?; } self.socket .send_to(&packet.pack_alloc().unwrap(), &dst) - .chain_err(|| "Failed to send data multicast on socket")?; + .map_err(|e| { + std::io::Error::new(e.kind(), "Failed to send data multicast on socket") + })?; } if sequence == 255 { @@ -979,7 +962,7 @@ impl SacnSourceInternal { }; self.socket .send_to(&packet.pack_alloc()?, &ip) - .chain_err(|| "Failed to send sync packet on socket")?; + .map_err(|e| std::io::Error::new(e.kind(), "Failed to send sync packet on socket"))?; if sequence == 255 { sequence = 0; @@ -1213,7 +1196,7 @@ impl SacnSourceInternal { /// fn set_name(&mut self, name: &str) -> Result<()> { if name.len() > E131_SOURCE_NAME_FIELD_LENGTH { - bail!(ErrorKind::MalformedSourceName( + return Err(SacnError::MalformedSourceName( "Source name provided is longer than maximum allowed".to_string() )); } @@ -1321,7 +1304,7 @@ fn unlock_internal( // shouldn't be exposed to the user (as its internal and would have no use). // Cannot directly return the PoisonError due to PoisonError using a different error system to other std modules which doesn't work with // error_chain. - bail!(ErrorKind::SourceCorrupt("Mutex poisoned".to_string())); + return Err(SacnError::SourceCorrupt("Mutex poisoned".to_string())); } Ok(lock) => Ok(lock), } @@ -1349,7 +1332,7 @@ fn unlock_internal_mut( // shouldn't be exposed to the user (as its internal and would have no use). // Cannot directly return the PoisonError due to PoisonError using a different error system to other std modules which doesn't work with // error_chain. - bail!(ErrorKind::SourceCorrupt("Mutex poisoned".to_string())); + return Err(SacnError::SourceCorrupt("Mutex poisoned".to_string())); } Ok(lock) => Ok(lock), } diff --git a/tests/data_parse_tests.rs b/tests/data_parse_tests.rs index 5be366da..5074b22d 100644 --- a/tests/data_parse_tests.rs +++ b/tests/data_parse_tests.rs @@ -3268,8 +3268,8 @@ fn test_data_packet_parse_pack() { fn test_malformed_data_packet_wrong_preample_lower_byte_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_WRONG_PREAMBLE_SIZE_LOWER_BYTE) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidData(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3291,8 +3291,8 @@ fn test_malformed_data_packet_wrong_preample_lower_byte_parse() { fn test_malformed_data_packet_wrong_preample_upper_byte_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_WRONG_PREAMBLE_SIZE_UPPER_BYTE) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidData(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3314,8 +3314,8 @@ fn test_malformed_data_packet_wrong_preample_upper_byte_parse() { fn test_malformed_data_packet_wrong_postample_lower_byte_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_WRONG_POSTAMBLE_SIZE_LOWER_BYTE) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidData(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3337,8 +3337,8 @@ fn test_malformed_data_packet_wrong_postample_lower_byte_parse() { fn test_malformed_data_packet_wrong_postample_upper_byte_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_WRONG_POSTAMBLE_SIZE_UPPER_BYTE) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidData(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3360,8 +3360,8 @@ fn test_malformed_data_packet_wrong_postample_upper_byte_parse() { fn test_malformed_data_packet_root_layer_wrong_flags() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_WRONG_FLAGS) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParsePduInvalidFlags(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParsePduInvalidFlags(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3383,8 +3383,8 @@ fn test_malformed_data_packet_root_layer_wrong_flags() { fn test_malformed_data_packet_root_layer_too_low_length() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_TOO_LOW_LENGTH) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3406,8 +3406,8 @@ fn test_malformed_data_packet_root_layer_too_low_length() { fn test_malformed_data_packet_root_layer_too_high_length() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_TOO_HIGH_LENGTH) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3429,8 +3429,8 @@ fn test_malformed_data_packet_root_layer_too_high_length() { fn test_malformed_data_packet_wrong_acn_identifier_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_WRONG_ACN_IDENTIFIER) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidData(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3452,8 +3452,8 @@ fn test_malformed_data_packet_wrong_acn_identifier_parse() { fn test_malformed_data_packet_unknown_acn_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_UNKNOWN_ACN_VECTOR) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidVector(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -3475,8 +3475,8 @@ fn test_malformed_data_packet_unknown_acn_vector_parse() { fn test_malformed_data_packet_extended_acn_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_ROOT_LAYER_EXTENDED_VECTOR) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // As this is a byzantine type error because the packet is otherwise correct except the vector is the wrong vector type the exact // parse error isn't enforced but the packet must still be rejected. assert!(true, "Malformed packet successfully rejected"); @@ -3500,8 +3500,8 @@ fn test_malformed_data_packet_extended_acn_vector_parse() { fn test_malformed_data_packet_too_long_cid_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_TOO_LONG_CID) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // The exact error in this case is not defined as other fields will be effected as all the data // is shifted, therefore just check for any parse error. assert!(true, "Malformed packet successfully rejected"); @@ -3525,8 +3525,8 @@ fn test_malformed_data_packet_too_long_cid_parse() { fn test_malformed_data_packet_too_short_cid_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_TOO_SHORT_CID) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -3548,8 +3548,8 @@ fn test_malformed_data_packet_too_short_cid_parse() { fn test_malformed_data_packet_framing_layer_wrong_flags_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_FRAMING_LAYER_WRONG_FLAGS) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParsePduInvalidFlags(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParsePduInvalidFlags(_)) => { assert!(true, "Expected error returned"); } x => { @@ -3571,8 +3571,8 @@ fn test_malformed_data_packet_framing_layer_wrong_flags_parse() { fn test_malformed_data_packet_framing_layer_low_length_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_FRAMING_LAYER_LOW_LENGTH) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -3594,8 +3594,8 @@ fn test_malformed_data_packet_framing_layer_low_length_parse() { fn test_malformed_data_packet_framing_layer_high_length_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_FRAMING_LAYER_HIGH_LENGTH) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -3617,8 +3617,8 @@ fn test_malformed_data_packet_framing_layer_high_length_parse() { fn test_malformed_data_packet_framing_layer_wrong_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_FRAMING_LAYER_WRONG_VECTOR) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidVector(_)) => { assert!(true, "Expected error returned"); } x => { @@ -3672,8 +3672,8 @@ fn test_data_packet_max_source_name_length_parse(){ fn test_malformed_data_packet_source_name_not_null_terminated_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_NOT_NULL_TERMINATED_SOURCE_NAME) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::SourceNameInvalid(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::SourceNameNotNullTerminated()) => { assert!(true, "Expected error returned"); } x => { @@ -3695,8 +3695,8 @@ fn test_malformed_data_packet_source_name_not_null_terminated_parse() { fn test_malformed_data_packet_too_high_priority_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_TOO_HIGH_PRIORITY) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidPriority(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidPriority(_)) => { assert!(true, "Expected error returned"); } x => { @@ -3810,8 +3810,8 @@ fn test_data_packet_no_sync_parse() { fn test_malformed_data_packet_too_high_sync_addr_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_TOO_HIGH_SYNC_ADDR_PACKET) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidSyncAddr(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidSyncAddr(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4213,8 +4213,8 @@ fn test_data_packet_options_bit_7_set_parse() { fn test_malformed_data_packet_too_high_universe_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_TOO_HIGH_UNIVERSE) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidUniverse(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidUniverse(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4236,8 +4236,8 @@ fn test_malformed_data_packet_too_high_universe_parse() { fn test_malformed_data_packet_too_low_universe_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_TOO_LOW_UNIVERSE) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidUniverse(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidUniverse(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4259,8 +4259,8 @@ fn test_malformed_data_packet_too_low_universe_parse() { fn test_malformed_data_packet_dmp_layer_too_high_length_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_TOO_HIGH_LENGTH) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4282,8 +4282,8 @@ fn test_malformed_data_packet_dmp_layer_too_high_length_parse() { fn test_malformed_data_packet_dmp_layer_too_low_length_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_TOO_LOW_LENGTH) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4305,8 +4305,8 @@ fn test_malformed_data_packet_dmp_layer_too_low_length_parse() { fn test_malformed_data_packet_dmp_layer_wrong_flags_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_WRONG_FLAGS) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParsePduInvalidFlags(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParsePduInvalidFlags(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4328,8 +4328,8 @@ fn test_malformed_data_packet_dmp_layer_wrong_flags_parse() { fn test_malformed_data_packet_dmp_layer_wrong_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_WRONG_VECTOR) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidVector(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4351,8 +4351,8 @@ fn test_malformed_data_packet_dmp_layer_wrong_vector_parse() { fn test_malformed_data_packet_dmp_layer_wrong_address_data_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_WRONG_ADDRESS_DATA) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4374,8 +4374,8 @@ fn test_malformed_data_packet_dmp_layer_wrong_address_data_parse() { fn test_malformed_data_packet_dmp_layer_wrong_first_property_address_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_WRONG_FIRST_PROPERTY_ADDRESS) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4397,8 +4397,8 @@ fn test_malformed_data_packet_dmp_layer_wrong_first_property_address_parse() { fn test_malformed_data_packet_dmp_layer_wrong_address_increment_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_WRONG_ADDRESS_INCREMENT) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4420,8 +4420,8 @@ fn test_malformed_data_packet_dmp_layer_wrong_address_increment_parse() { fn test_malformed_data_packet_dmp_layer_too_high_property_count_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_TOO_HIGH_PROPERTY_COUNT) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -4443,8 +4443,8 @@ fn test_malformed_data_packet_dmp_layer_too_high_property_count_parse() { fn test_malformed_data_packet_dmp_layer_too_low_property_count_parse() { match AcnRootLayerProtocol::parse(&TEST_DATA_PACKET_DMP_LAYER_TOO_LOW_PROPERTY_COUNT) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { diff --git a/tests/discovery_parse_tests.rs b/tests/discovery_parse_tests.rs index 1eea3a5c..494ecd7b 100644 --- a/tests/discovery_parse_tests.rs +++ b/tests/discovery_parse_tests.rs @@ -812,8 +812,8 @@ fn test_discovery_packet_parse_pack() { fn test_discovery_packet_root_layer_unknown_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_ROOT_LAYER_UNKNOWN_VECTOR) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidVector(_)) => { assert!(true, "Expected error returned"); } x => { @@ -835,8 +835,8 @@ fn test_discovery_packet_root_layer_unknown_vector_parse() { fn test_discovery_packet_root_layer_data_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_ROOT_LAYER_DATA_VECTOR) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // As the packet will be treated as a data packet it is unclear where the parse will fail so only assert that it must fail // with a parse type error rather than a specific error. assert!(true, "Expected error family returned"); @@ -860,8 +860,8 @@ fn test_discovery_packet_root_layer_data_vector_parse() { fn test_discovery_packet_too_short_cid_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_TOO_SHORT_CID) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -883,8 +883,8 @@ fn test_discovery_packet_too_short_cid_parse() { fn test_discovery_packet_too_long_cid_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_TOO_LONG_CID) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // Difficult to predict / assert what error should be caused by a field being too long as all // other fields will be shifted and no clear way to know the true end of the CID field. // Therefore just assert that the packet was detected as malformed rather than a specific error. @@ -909,8 +909,8 @@ fn test_discovery_packet_too_long_cid_parse() { fn test_discovery_packet_wrong_flags_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_WRONG_FLAGS) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParsePduInvalidFlags(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParsePduInvalidFlags(_)) => { assert!(true, "Expected error returned"); } x => { @@ -932,8 +932,8 @@ fn test_discovery_packet_wrong_flags_parse() { fn test_discovery_packet_framing_layer_length_too_long_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_FRAMING_LAYER_LENGTH_TOO_LONG) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -955,8 +955,8 @@ fn test_discovery_packet_framing_layer_length_too_long_parse() { fn test_discovery_packet_framing_layer_length_too_short_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_FRAMING_LAYER_LENGTH_TOO_SHORT) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -978,8 +978,8 @@ fn test_discovery_packet_framing_layer_length_too_short_parse() { fn test_discovery_packet_framing_layer_wrong_flags_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_FRAMING_LAYER_WRONG_FLAGS) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParsePduInvalidFlags(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParsePduInvalidFlags(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1001,8 +1001,8 @@ fn test_discovery_packet_framing_layer_wrong_flags_parse() { fn test_discovery_packet_sync_framing_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_SYNC_FRAMING_VECTOR) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // Difficult to assert the exact error caused by using the sync vector as the packet will then // be parsed as a sync packet and could be rejected for multiple reasons. // The key part is that it is rejected successfully for a parse error. @@ -1027,8 +1027,8 @@ fn test_discovery_packet_sync_framing_vector_parse() { fn test_discovery_packet_unknown_framing_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_UNKNOWN_FRAMING_VECTOR) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidVector(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1072,8 +1072,8 @@ fn test_discovery_packet_arbitrary_reserved_parse() { fn test_discovery_packet_discovery_layer_wrong_flags_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_DISCOVERY_LAYER_WRONG_FLAGS) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParsePduInvalidFlags(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParsePduInvalidFlags(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1095,8 +1095,8 @@ fn test_discovery_packet_discovery_layer_wrong_flags_parse() { fn test_discovery_packet_discovery_layer_length_too_short_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_DISCOVERY_LAYER_LENGTH_TOO_SHORT) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1118,8 +1118,8 @@ fn test_discovery_packet_discovery_layer_length_too_short_parse() { fn test_discovery_packet_discovery_layer_length_too_long_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_DISCOVERY_LAYER_LENGTH_TOO_LONG) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1141,8 +1141,8 @@ fn test_discovery_packet_discovery_layer_length_too_long_parse() { fn test_discovery_packet_discovery_layer_vector_unknown_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_DISCOVERY_LAYER_VECTOR_UNKNOWN) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidVector(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1164,8 +1164,8 @@ fn test_discovery_packet_discovery_layer_vector_unknown_parse() { fn test_discovery_packet_page_higher_than_last_page_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_PAGE_HIGHER_THAN_LAST_PAGE) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidPage(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidPage(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1187,8 +1187,8 @@ fn test_discovery_packet_page_higher_than_last_page_parse() { fn test_discovery_packet_decending_order_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_DECENDING_ORDER) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidUniverseOrder(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidUniverseOrder(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1210,8 +1210,8 @@ fn test_discovery_packet_decending_order_parse() { fn test_discovery_packet_random_order_parse() { match AcnRootLayerProtocol::parse(&TEST_UNIVERSE_DISCOVERY_PACKET_RANDOM_ORDER) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidUniverseOrder(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidUniverseOrder(_)) => { assert!(true, "Expected error returned"); } x => { @@ -1367,8 +1367,8 @@ fn test_discovery_packet_max_universe_capacity() { fn test_discovery_packet_above_max_universe_capacity() { match AcnRootLayerProtocol::parse(&generate_test_universe_discovery_packet((DISCOVERY_UNI_PER_PAGE as u16) + 1)) { Err(e) => { - match e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidLength(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidLength(_)) => { assert!(true, "Expected error returned"); } x => { diff --git a/tests/ipv4_tests.rs b/tests/ipv4_tests.rs index 59de5cca..e26eadb5 100644 --- a/tests/ipv4_tests.rs +++ b/tests/ipv4_tests.rs @@ -764,8 +764,8 @@ fn test_send_recv_sync_then_nosync_packet_same_universe_multicast_ipv4() { match second_received_result { Err(e) => { - match e.kind() { - ErrorKind::Io(s) => { + match e { + SacnError::Io(s) => { match s.kind() { std::io::ErrorKind::WouldBlock => { // Expected to timeout. @@ -1666,8 +1666,8 @@ fn test_universe_discovery_one_universe_one_source_ipv4(){ let result = dmx_recv.recv(Some(Duration::from_secs(2))); match result { Err(e) => { - match e.kind() { - &ErrorKind::Io(ref s) => { + match e { + SacnError::Io(ref s) => { match s.kind() { std::io::ErrorKind::WouldBlock => { // Expected to timeout / would block. @@ -1749,8 +1749,8 @@ fn test_universe_discovery_interval_ipv4(){ match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::SourceDiscovered(_) => { + match e { + SacnError::SourceDiscovered(_) => { // Measure the time between the first and second discovery packets, this removes the uncertainty in the time taken for the sender to start. interval_start = Instant::now(); } @@ -1766,8 +1766,8 @@ fn test_universe_discovery_interval_ipv4(){ match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::SourceDiscovered(_) => { + match e { + SacnError::SourceDiscovered(_) => { let interval = interval_start.elapsed(); let interval_millis = interval.as_millis(); assert!(interval_millis > (INTERVAL_EXPECTED_MILLIS - INTERVAL_TOLERANCE_MILLIS), "Discovery interval is shorter than expected, {} ms", interval_millis); @@ -1833,8 +1833,8 @@ fn test_universe_discovery_interval_with_updates_ipv4(){ match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::SourceDiscovered(_) => { + match e { + SacnError::SourceDiscovered(_) => { // Measure the time between the first and second discovery packets, this removes the uncertainty in the time taken for the sender to start. interval_start = Instant::now(); } @@ -1850,8 +1850,8 @@ fn test_universe_discovery_interval_with_updates_ipv4(){ match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::SourceDiscovered(_) => { + match e { + SacnError::SourceDiscovered(_) => { let interval = interval_start.elapsed(); let interval_millis = interval.as_millis(); assert!(interval_millis > (INTERVAL_EXPECTED_MILLIS - INTERVAL_TOLERANCE_MILLIS), "Discovery interval is shorter than expected, {} ms", interval_millis); @@ -1907,8 +1907,8 @@ fn test_universe_discovery_multiple_universe_one_source_ipv4(){ let result = dmx_recv.recv(Some(Duration::from_secs(2))); match result { Err(e) => { - match e.kind() { - &ErrorKind::Io(ref s) => { + match e { + SacnError::Io(ref s) => { match s.kind() { std::io::ErrorKind::WouldBlock => { // Expected to timeout / would block. @@ -1994,8 +1994,8 @@ fn test_universe_discovery_multiple_pages_one_source_ipv4(){ match result { Err(e) => { - match e.kind() { - &ErrorKind::Io(ref s) => { + match e { + SacnError::Io(ref s) => { match s.kind() { std::io::ErrorKind::WouldBlock => { // Expected to timeout / would block. @@ -2076,8 +2076,8 @@ fn test_universe_discovery_no_universes_ipv4(){ match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::SourceDiscovered(src_name) => { + match e { + SacnError::SourceDiscovered(src_name) => { assert_eq!(src_name, SOURCE_NAMES[0], "Name of source discovered doesn't match expected"); let sources = dmx_recv.get_discovered_sources(); assert_eq!(sources.len(), 1, "Number of sources discovered doesn't match expected (1)"); @@ -2159,8 +2159,8 @@ fn test_receiver_sources_exceeded_3() { // On receiving the third time from the third source the sources exceeded error should be thrown. match dmx_recv.recv(TIMEOUT) { Err(e) => { - match *e.kind() { - ErrorKind::SourcesExceededError(_) => { + match e { + SacnError::SourcesExceededError(_) => { assert!(true, "Expected error returned"); } _ => { @@ -2392,8 +2392,8 @@ fn test_preview_data_2_receiver_1_sender() { // The other receiver should not. match dmx_recv.recv(TIMEOUT) { Err(e) => { - match e.kind() { - &ErrorKind::Io(ref s) => { + match e { + SacnError::Io(ref s) => { match s.kind() { std::io::ErrorKind::WouldBlock => { // Expected to timeout / would block. @@ -2495,15 +2495,15 @@ fn test_source_1_universe_timeout(){ let start_time: Instant = Instant::now(); match dmx_recv.recv(Some(acceptable_upper_bound)) { // This will return a WouldBlock/Timedout error if the timeout takes too long. Err(e) => { - match e.kind() { - ErrorKind::UniverseTimeout(_src_cid, timedout_uni) => { + match e { + SacnError::UniverseTimeout(_src_cid, timedout_uni) => { if start_time.elapsed() < acceptable_lower_bound{ assert!(false, "Timeout came quicker than expected"); } - assert_eq!(*timedout_uni, universe, "Timed out universe doesn't match expected"); + assert_eq!(timedout_uni, universe, "Timed out universe doesn't match expected"); assert!(true, "Universe timed out as expected"); } - ErrorKind::Io(s) => { + SacnError::Io(s) => { match s.kind() { std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => { assert!(false, "Timeout took too long to come through"); @@ -2633,20 +2633,20 @@ fn test_source_2_universe_1_timeout(){ loop { // Loop till a timeout happens, ignoring the data packets send to the non-timeout uni. match dmx_recv.recv(Some(acceptable_upper_bound)) { // This will return a WouldBlock/Timedout error if the timeout takes too long. Err(e) => { - match e.kind() { - ErrorKind::UniverseTimeout(_src_cid, universe) => { + match e { + SacnError::UniverseTimeout(_src_cid, universe) => { if start_time.elapsed() < acceptable_lower_bound{ assert!(false, "Timeout came quicker than expected"); } - assert_eq!(*universe, universe_timeout, "Unexpected universe timed out"); + assert_eq!(universe, universe_timeout, "Unexpected universe timed out"); assert!(true, "Universe timed out as expected"); // Know that the timeout universe timed out as expected so check that the other universe hasn't timed out. // Makes use of a timeout of 0 which should check the source timeouts without actually receiving any data as it times out instantly. match dmx_recv.recv(Some(Duration::from_millis(0))) { Err(e) => { - match e.kind() { - ErrorKind::Io(s) => { + match e { + SacnError::Io(s) => { match s.kind() { std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => { assert!(true, "Other universe hasn't timedout as expected"); @@ -2667,7 +2667,7 @@ fn test_source_2_universe_1_timeout(){ } break; } - ErrorKind::Io(s) => { + SacnError::Io(s) => { match s.kind() { std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => { assert!(false, "Timeout took too long to come through: {:?}", start_time.elapsed()); @@ -2867,8 +2867,8 @@ fn test_send_sync_timeout(){ // Data should never be passed up because the data packet should have timed-out before the sync packet is processed. match dmx_recv.recv(TIMEOUT) { Err(e) => { - match e.kind() { - ErrorKind::Io(s) => { + match e { + SacnError::Io(s) => { match s.kind() { std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => { // Timeout as expected because the data packet that is awaiting a sync packet has timed out. @@ -3083,8 +3083,8 @@ fn test_discover_recv_sync_runthrough_ipv4() { let universes: Vec = match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::SourceDiscovered(_name) => { + match e { + SacnError::SourceDiscovered(_name) => { let discovered_sources = dmx_recv.get_discovered_sources(); assert_eq!(discovered_sources.len(), 1); @@ -3113,8 +3113,8 @@ fn test_discover_recv_sync_runthrough_ipv4() { loop { match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::UniverseTerminated(_src_cid, _universe) => { + match e { + SacnError::UniverseTerminated(_src_cid, _universe) => { // A real use-case may also want to not terminate when the source does and instead remain waiting but in this // case the for the test the receiver terminates with the source. break; @@ -3883,8 +3883,8 @@ fn test_terminate_universe_no_register() { match src.terminate_stream(universe, 0) { Err(e) => { - match e.kind() { - ErrorKind::UniverseNotRegistered(_) => { + match e { + SacnError::UniverseNotRegistered(_) => { assert!(true, "Expected error returned"); }, _ => { @@ -3909,16 +3909,9 @@ fn test_send_empty() { match src.send(&[UNIVERSE], &[], None, None, None) { Err(e) => { - match e.kind() { - ErrorKind::Io(x) => { - match x.kind() { - std::io::ErrorKind::InvalidInput => { - assert!(true, "Unexpected error returned"); - }, - _ => { - assert!(false, "Unexpected error returned"); - } - } + match e { + SacnError::DataArrayEmpty() => { + assert!(true, "Expected error returned"); }, _ => { assert!(false, "Unexpected error returned"); diff --git a/tests/ipv6_tests.rs b/tests/ipv6_tests.rs index cd71ce93..c6c6bc95 100644 --- a/tests/ipv6_tests.rs +++ b/tests/ipv6_tests.rs @@ -615,8 +615,8 @@ fn test_universe_discovery_one_universe_one_source_ipv6(){ let result = dmx_recv.recv(Some(Duration::from_secs(2))); match result { Err(e) => { - match e.kind() { - &ErrorKind::Io(ref s) => { + match e { + SacnError::Io(ref s) => { match s.kind() { std::io::ErrorKind::WouldBlock => { // Expected to timeout / would block. @@ -696,8 +696,8 @@ fn test_universe_discovery_multiple_universe_one_source_ipv6(){ let result = dmx_recv.recv(Some(Duration::from_secs(2))); match result { Err(e) => { - match e.kind() { - &ErrorKind::Io(ref s) => { + match e { + SacnError::Io(ref s) => { match s.kind() { std::io::ErrorKind::WouldBlock => { // Expected to timeout / would block. @@ -783,8 +783,8 @@ fn test_universe_discovery_multiple_pages_one_source_ipv6(){ match result { Err(e) => { - match e.kind() { - &ErrorKind::Io(ref s) => { + match e { + SacnError::Io(ref s) => { match s.kind() { std::io::ErrorKind::WouldBlock => { // Expected to timeout / would block. @@ -1129,8 +1129,8 @@ fn test_discover_recv_sync_runthrough_ipv6() { let universes: Vec = match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::SourceDiscovered(_name) => { + match e { + SacnError::SourceDiscovered(_name) => { let discovered_sources = dmx_recv.get_discovered_sources(); assert_eq!(discovered_sources.len(), 1); @@ -1159,8 +1159,8 @@ fn test_discover_recv_sync_runthrough_ipv6() { loop { match dmx_recv.recv(None) { Err(e) => { - match e.kind() { - ErrorKind::UniverseTerminated(_src_cid, _universe) => { + match e { + SacnError::UniverseTerminated(_src_cid, _universe) => { // A real use-case may also want to not terminate when the source does and instead remain waiting but in this // case the for the test the receiver terminates with the source. break; diff --git a/tests/src_tests.rs b/tests/src_tests.rs index cf38b618..3374726f 100644 --- a/tests/src_tests.rs +++ b/tests/src_tests.rs @@ -27,8 +27,8 @@ fn test_new_ipv4_one_too_long_source_name() { const SRC_NAME: &str = "01234567890123456789012345678901234567890123456789012345678901234"; match SacnSource::new_v4(SRC_NAME) { Err(e) => { - match e.kind() { - ErrorKind::MalformedSourceName(_) => { + match e { + SacnError::MalformedSourceName(_) => { assert!(true, "Expected error returned"); } _ => { @@ -47,8 +47,8 @@ fn test_new_ipv6_one_too_long_source_name() { const SRC_NAME: &str = "01234567890123456789012345678901234567890123456789012345678901234"; match SacnSource::new_v6(SRC_NAME) { Err(e) => { - match e.kind() { - ErrorKind::MalformedSourceName(_) => { + match e { + SacnError::MalformedSourceName(_) => { assert!(true, "Expected error returned"); } _ => { @@ -67,8 +67,8 @@ fn test_new_with_cid_ip_too_long_source_name() { const SRC_NAME: &str = "01234567890123456789012345678901234567890123456789012345678901234"; match SacnSource::with_cid_ip(SRC_NAME, Uuid::new_v4(), SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), ACN_SDT_MULTICAST_PORT)) { Err(e) => { - match e.kind() { - ErrorKind::MalformedSourceName(_) => { + match e { + SacnError::MalformedSourceName(_) => { assert!(true, "Expected error returned"); } _ => { @@ -87,8 +87,8 @@ fn test_new_with_cid_ip_v4_too_long_source_name() { const SRC_NAME: &str = "01234567890123456789012345678901234567890123456789012345678901234"; match SacnSource::with_cid_v4(SRC_NAME, Uuid::new_v4()) { Err(e) => { - match e.kind() { - ErrorKind::MalformedSourceName(_) => { + match e { + SacnError::MalformedSourceName(_) => { assert!(true, "Expected error returned"); } _ => { @@ -107,8 +107,8 @@ fn test_new_with_cid_ip_v6_too_long_source_name() { const SRC_NAME: &str = "01234567890123456789012345678901234567890123456789012345678901234"; match SacnSource::with_cid_v6(SRC_NAME, Uuid::new_v4()) { Err(e) => { - match e.kind() { - ErrorKind::MalformedSourceName(_) => { + match e { + SacnError::MalformedSourceName(_) => { assert!(true, "Expected error returned"); } _ => { @@ -127,8 +127,8 @@ fn test_new_with_ip_too_long_source_name() { const SRC_NAME: &str = "01234567890123456789012345678901234567890123456789012345678901234"; match SacnSource::with_ip(SRC_NAME, SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), ACN_SDT_MULTICAST_PORT)) { Err(e) => { - match e.kind() { - ErrorKind::MalformedSourceName(_) => { + match e { + SacnError::MalformedSourceName(_) => { assert!(true, "Expected error returned"); } _ => { @@ -149,8 +149,8 @@ fn test_set_name_too_long_source_name() { match src.set_name(SRC_NAME) { Err(e) => { - match e.kind() { - ErrorKind::MalformedSourceName(_) => { + match e { + SacnError::MalformedSourceName(_) => { assert!(true, "Expected error returned"); } _ => { @@ -267,9 +267,9 @@ fn test_send_without_registering(){ match src.send(&[1], &TEST_DATA_SINGLE_UNIVERSE, Some(priority), None, None) { Ok(_) => {assert!(false, "Source didn't prevent sending without registering")}, Err(e) => - match e.kind() { - &ErrorKind::UniverseNotRegistered(ref _s) => assert!(true), - _ => assert!(false, "Unexpected error type returned, {}", e.kind()) + match e { + SacnError::UniverseNotRegistered(ref _s) => assert!(true), + _ => assert!(false, "Unexpected error type returned, {}", e) } } } @@ -285,8 +285,8 @@ fn test_send_above_priority(){ match src.send(&[universe], &TEST_DATA_SINGLE_UNIVERSE, Some(priority), None, None) { Err(e) => { - match e.kind() { - ErrorKind::InvalidPriority(_) => { + match e { + SacnError::InvalidPriority(_) => { assert!(true, "Expected error returned"); } x => { @@ -342,8 +342,8 @@ fn test_register_below_min_universe() { match src.register_universes(&[UNIVERSE]) { Err(e) => { - match e.kind() { - ErrorKind::IllegalUniverse(_) => { + match e { + SacnError::IllegalUniverse(_) => { assert!(true, "Expected error returned"); } _ => { @@ -366,8 +366,8 @@ fn test_register_above_max_universe() { match src.register_universes(&[UNIVERSE]) { Err(e) => { - match e.kind() { - ErrorKind::IllegalUniverse(_) => { + match e { + SacnError::IllegalUniverse(_) => { assert!(true, "Expected error returned"); } _ => { @@ -434,8 +434,8 @@ fn test_sync_addr_0() { match src.send_sync_packet(SYNC_UNI, None) { Err(e) => { - match e.kind() { - ErrorKind::IllegalUniverse(_) => { + match e { + SacnError::IllegalUniverse(_) => { assert!(true, "Expected error returned"); } _ => { diff --git a/tests/sync_parse_tests.rs b/tests/sync_parse_tests.rs index 4ac0c35d..63d4b846 100644 --- a/tests/sync_parse_tests.rs +++ b/tests/sync_parse_tests.rs @@ -415,8 +415,8 @@ fn test_synchronization_packet_parse_pack() { fn test_sync_packet_root_layer_data_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_ROOT_LAYER_DATA_VECTOR) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // As the packet will be treated as a data packet it is unclear where the parse will fail so only assert that it must fail // with a parse type error rather than a specific error. assert!(true, "Expected error family returned"); @@ -440,8 +440,8 @@ fn test_sync_packet_root_layer_data_vector_parse() { fn test_sync_packet_root_layer_unknown_vector_parse() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_ROOT_LAYER_UNKNOWN_VECTOR) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidVector(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -463,8 +463,8 @@ fn test_sync_packet_root_layer_unknown_vector_parse() { fn test_sync_packet_too_short_cid_parse() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_TOO_SHORT_CID) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // As packet is too short it is unclear exactly what error will occur, just need to assert // that the packet is successfully rejected as malformed. assert!(true, "Expected error family returned"); @@ -488,8 +488,8 @@ fn test_sync_packet_too_short_cid_parse() { fn test_sync_packet_too_long_cid_parse() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_TOO_LONG_CID) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // As packet is too long it is unclear exactly what error will occur, just need to assert // that the packet is successfully rejected as malformed. assert!(true, "Expected error family returned"); @@ -513,8 +513,8 @@ fn test_sync_packet_too_long_cid_parse() { fn test_sync_packet_framing_layer_wrong_flags_parse() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_FRAMING_LAYER_WRONG_FLAGS) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParsePduInvalidFlags(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParsePduInvalidFlags(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -536,8 +536,8 @@ fn test_sync_packet_framing_layer_wrong_flags_parse() { fn test_sync_packet_framing_layer_length_too_long_parse() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_FRAMING_LAYER_LENGTH_TOO_LONG) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInsufficientData(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInsufficientData(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -559,8 +559,8 @@ fn test_sync_packet_framing_layer_length_too_long_parse() { fn test_sync_packet_framing_layer_length_too_short_parse() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_FRAMING_LAYER_LENGTH_TOO_SHORT) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidLength(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidLength(_)) => { assert!(true, "Expected error returned"); } _ => { @@ -582,8 +582,8 @@ fn test_sync_packet_framing_layer_length_too_short_parse() { fn test_sync_packet_framing_layer_discovery_vector() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_FRAMING_LAYER_DISCOVERY_VECTOR) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(_) => { + match e { + SacnError::SacnParsePackError(_) => { // The packet will be parsed as if it was a discovery packet which means that the parsing might fail // for a number of reasons with it being hard to assert which one ahead of time. // Therefore just assert that the parsing fails / the packet is rejected. @@ -608,8 +608,8 @@ fn test_sync_packet_framing_layer_discovery_vector() { fn test_sync_packet_framing_layer_unknown_vector() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_FRAMING_LAYER_UNKNOWN_VECTOR) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::PduInvalidVector(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::PduInvalidVector(_)) => { assert!(true, "Expected error family returned"); } _ => { @@ -631,15 +631,14 @@ fn test_sync_packet_framing_layer_unknown_vector() { fn test_sync_packet_too_high_sync_addr() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_TOO_HIGH_SYNC_ADDRESS) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidUniverse(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidSyncAddr(_)) => { assert!(true, "Expected error family returned"); } _ => { assert!(false, "Unexpected error type returned"); } } - } Ok(_) => { assert!( @@ -654,8 +653,8 @@ fn test_sync_packet_too_high_sync_addr() { fn test_sync_packet_too_low_sync_addr() { match AcnRootLayerProtocol::parse(&TEST_SYNCHRONIZATION_PACKET_TOO_LOW_SYNC_ADDRESS) { Err(e) => { - match *e.kind() { - ErrorKind::SacnParsePackError(sacn_parse_pack_error::ErrorKind::ParseInvalidUniverse(_)) => { + match e { + SacnError::SacnParsePackError(sacn_parse_pack_error::ParsePacketError::ParseInvalidSyncAddr(_)) => { assert!(true, "Expected error family returned"); } _ => {