From ca555f119d2b5d1844ea08a8f4891529f7fbe1fc Mon Sep 17 00:00:00 2001 From: Louis Kureuil Person Date: Thu, 22 Nov 2018 23:28:31 +0100 Subject: [PATCH 1/2] Convert lapin-async's Error type to failure Uses the same hack as lapin-futures' ErrorKind type to prevent exhaustive matching against the different kinds of errors. --- async/Cargo.toml | 1 + async/src/api.rs | 246 ++++++++++++++++++++-------------------- async/src/connection.rs | 8 +- async/src/error.rs | 86 ++++++++++++-- async/src/lib.rs | 2 + futures/src/error.rs | 6 +- 6 files changed, 207 insertions(+), 142 deletions(-) diff --git a/async/Cargo.toml b/async/Cargo.toml index 57d214d6..a8893b4d 100644 --- a/async/Cargo.toml +++ b/async/Cargo.toml @@ -15,6 +15,7 @@ log = "^0.4" nom = "^4.0" cookie-factory = "^0.2.4" amq-protocol = "^0.23" +failure = "^0.1" [dependencies.sasl] version= "^0.4" diff --git a/async/src/api.rs b/async/src/api.rs index aa328d8e..38299310 100644 --- a/async/src/api.rs +++ b/async/src/api.rs @@ -133,7 +133,7 @@ impl Connection { m => { error!("the client should not receive this method: {:?}", m); - return Err(Error::InvalidMethod); + return Err(ErrorKind::InvalidMethod(m).into()); } } } @@ -144,7 +144,7 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if let Err(err) = self.check_state(_channel_id, ChannelState::Initial) { @@ -170,7 +170,7 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if let Err(err) = self.check_state(_channel_id, ChannelState::Initial) { @@ -184,7 +184,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } @@ -195,11 +195,11 @@ impl Connection { pub fn channel_flow(&mut self, _channel_id: u16, active: Boolean) -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Channel(channel::AMQPMethod::Flow(channel::Flow { active: active })); @@ -218,11 +218,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } self.channels.get_mut(&_channel_id).map(|c| c.send_flow = method.active); @@ -232,11 +232,11 @@ impl Connection { pub fn channel_flow_ok(&mut self, _channel_id: u16, active: Boolean) -> Result<(), Error> { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Channel(channel::AMQPMethod::FlowOk(channel::FlowOk { active: active })); @@ -250,11 +250,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -264,7 +264,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } @@ -280,11 +280,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Channel(channel::AMQPMethod::Close(channel::Close { @@ -308,11 +308,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } //FIXME: log the error if there is one @@ -326,11 +326,11 @@ impl Connection { pub fn channel_close_ok(&mut self, _channel_id: u16) -> Result<(), Error> { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if ! self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Channel(channel::AMQPMethod::CloseOk(channel::CloseOk {})); @@ -344,11 +344,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if ! self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -358,7 +358,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } @@ -377,11 +377,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if ! self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Access(access::AMQPMethod::Request(access::Request { @@ -411,11 +411,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -425,7 +425,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -444,11 +444,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Exchange(exchange::AMQPMethod::Declare(exchange::Declare { @@ -480,11 +480,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -494,7 +494,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -509,11 +509,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Exchange(exchange::AMQPMethod::Delete(exchange::Delete { @@ -540,11 +540,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -554,7 +554,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -571,11 +571,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Exchange(exchange::AMQPMethod::Bind(exchange::Bind { @@ -604,11 +604,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -618,7 +618,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -635,11 +635,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Exchange(exchange::AMQPMethod::Unbind(exchange::Unbind { @@ -668,11 +668,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -682,7 +682,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -700,11 +700,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Queue(queue::AMQPMethod::Declare(queue::Declare { @@ -735,11 +735,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -754,7 +754,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -770,11 +770,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Queue(queue::AMQPMethod::Bind(queue::Bind { @@ -808,11 +808,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -828,7 +828,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -841,11 +841,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Queue(queue::AMQPMethod::Purge(queue::Purge { @@ -871,11 +871,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } @@ -886,7 +886,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -901,11 +901,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Queue(queue::AMQPMethod::Delete(queue::Delete { @@ -933,11 +933,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -948,7 +948,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -963,11 +963,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Queue(queue::AMQPMethod::Unbind(queue::Unbind { @@ -995,11 +995,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1015,7 +1015,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1028,11 +1028,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Qos(basic::Qos { @@ -1058,11 +1058,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1081,7 +1081,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1100,11 +1100,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Consume(basic::Consume { @@ -1137,11 +1137,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1161,7 +1161,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1173,11 +1173,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Cancel(basic::Cancel { @@ -1202,11 +1202,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1221,7 +1221,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1236,11 +1236,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Publish(basic::Publish { @@ -1274,11 +1274,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } self.channels.get_mut(&_channel_id).map(|c| { @@ -1306,11 +1306,11 @@ impl Connection { -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Get(basic::Get { @@ -1336,11 +1336,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1364,7 +1364,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1376,11 +1376,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1390,7 +1390,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1402,11 +1402,11 @@ impl Connection { -> Result<(), Error> { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Ack(basic::Ack { @@ -1423,11 +1423,11 @@ impl Connection { -> Result<(), Error> { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Reject(basic::Reject { @@ -1440,11 +1440,11 @@ impl Connection { pub fn basic_recover_async(&mut self, _channel_id: u16, requeue: Boolean) -> Result<(), Error> { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = @@ -1455,11 +1455,11 @@ impl Connection { pub fn basic_recover(&mut self, _channel_id: u16, requeue: Boolean) -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Recover(basic::Recover { requeue: requeue })); @@ -1481,11 +1481,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1496,7 +1496,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1509,11 +1509,11 @@ impl Connection { -> Result<(), Error> { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Basic(basic::AMQPMethod::Nack(basic::Nack { @@ -1526,11 +1526,11 @@ impl Connection { pub fn confirm_select(&mut self, _channel_id: u16, nowait: Boolean) -> Result { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } let method = AMQPClass::Confirm(confirm::AMQPMethod::Select(confirm::Select { nowait: nowait })); @@ -1552,11 +1552,11 @@ impl Connection { if !self.channels.contains_key(&_channel_id) { trace!("key {} not in channels {:?}", _channel_id, self.channels); - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1570,7 +1570,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1581,11 +1581,11 @@ impl Connection { -> Result<(), Error> { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1610,7 +1610,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } @@ -1621,11 +1621,11 @@ impl Connection { -> Result<(), Error> { if !self.channels.contains_key(&_channel_id) { - return Err(Error::InvalidChannel); + return Err(ErrorKind::InvalidChannel(_channel_id).into()); } if !self.is_connected(_channel_id) { - return Err(Error::NotConnected); + return Err(ErrorKind::NotConnected.into()); } match self.get_next_answer(_channel_id) { @@ -1650,7 +1650,7 @@ impl Connection { }, _ => { self.set_channel_state(_channel_id, ChannelState::Error); - return Err(Error::UnexpectedAnswer); + return Err(ErrorKind::UnexpectedAnswer.into()); } } } diff --git a/async/src/connection.rs b/async/src/connection.rs index 4ef96d4a..ce907be7 100644 --- a/async/src/connection.rs +++ b/async/src/connection.rs @@ -15,7 +15,7 @@ use channel::{Channel, BasicProperties}; use message::*; use api::{Answer,ChannelState,RequestId}; use types::{AMQPValue,FieldTable}; -use error::{self, InvalidState}; +use error; #[derive(Clone,Copy,Debug,PartialEq,Eq)] pub enum ConnectionState { @@ -186,14 +186,14 @@ impl Connection { pub fn check_state(&self, channel_id: u16, state: ChannelState) -> result::Result<(), error::Error> { self.channels .get(&channel_id) - .map_or(Err(error::Error::InvalidChannel), |c| { + .map_or(Err(error::ErrorKind::InvalidChannel(channel_id).into()), |c| { if c.state == state { Ok(()) } else { - Err(error::Error::InvalidState(InvalidState { + Err(error::ErrorKind::InvalidState { expected: state, actual: c.state.clone(), - })) + }.into()) } }) } diff --git a/async/src/error.rs b/async/src/error.rs index 739125a1..d6675439 100644 --- a/async/src/error.rs +++ b/async/src/error.rs @@ -1,20 +1,84 @@ +use amq_protocol::protocol::AMQPClass; +use failure::{Backtrace, Context, Fail}; +use std::fmt; + use api::ChannelState; -#[derive(Clone,Debug,PartialEq)] -pub enum Error { +/// The type of error that can be returned in this crate. +/// +/// Instead of implementing the `Error` trait provided by the standard library, +/// it implemented the `Fail` trait provided by the `failure` crate. Doing so +/// means that this type guaranteed to be both sendable and usable across +/// threads, and that you'll be able to use the downcasting feature of the +/// `failure::Error` type. +#[derive(Debug)] +pub struct Error { + inner: Context, +} + +/// The different kinds of errors that can be reported. +/// +/// Event though we expose the complete enumeration of possible error variants, it is not +/// considered stable to exhaustively match on this enumeration: do it at your own risk. +#[derive(Debug, PartialEq, Fail)] +pub enum ErrorKind { + #[fail(display = "output buffer is too small")] SendBufferTooSmall, + #[fail(display = "input buffer is too small")] ReceiveBufferTooSmall, - GeneratorError, - ParserError, - InvalidState(InvalidState), - InvalidMethod, - InvalidChannel, + #[fail(display = "invalid channel state, expected {:?}, got {:?}", expected, actual)] + InvalidState { expected: ChannelState, actual: ChannelState }, + #[fail(display = "invalid protocol method: {:?}", _0)] + InvalidMethod(AMQPClass), + #[fail(display = "invalid channel: {}", _0)] + InvalidChannel(u16), + #[fail(display = "not connected")] NotConnected, + #[fail(display = "unexpected answer")] UnexpectedAnswer, + /// A hack to prevent developers from exhaustively match on the enum's variants + /// + /// The purpose of this variant is to let the `ErrorKind` enumeration grow more variants + /// without it being a breaking change for users. It is planned for the language to provide + /// this functionnality out of the box, though it has not been [stabilized] yet. + /// + /// [stabilized]: https://github.com/rust-lang/rust/issues/44109 + #[doc(hidden)] + #[fail(display = "lapin_async::error::ErrorKind::__Nonexhaustive: this should not be printed")] + __Nonexhaustive, +} + +impl Error { + /// Return the underlying `ErrorKind` + pub fn kind(&self) -> &ErrorKind { + self.inner.get_context() + } +} + +impl Fail for Error { + fn cause(&self) -> Option<&Fail> { + self.inner.cause() + } + + fn backtrace(&self) -> Option<&Backtrace> { + self.inner.backtrace() + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.inner, f) + } +} + +impl From for Error { + fn from(kind: ErrorKind) -> Error { + Error { inner: Context::new(kind) } + } } -#[derive(Clone,Debug,PartialEq)] -pub struct InvalidState { - pub expected: ChannelState, - pub actual: ChannelState, +impl From> for Error { + fn from(inner: Context) -> Error { + Error { inner: inner } + } } diff --git a/async/src/lib.rs b/async/src/lib.rs index 1f49f392..0bd0bc92 100644 --- a/async/src/lib.rs +++ b/async/src/lib.rs @@ -117,6 +117,8 @@ extern crate amq_protocol; #[macro_use] +extern crate failure; +#[macro_use] extern crate log; extern crate nom; extern crate cookie_factory; diff --git a/futures/src/error.rs b/futures/src/error.rs index be13bcfb..dd67fa96 100644 --- a/futures/src/error.rs +++ b/futures/src/error.rs @@ -41,15 +41,13 @@ pub enum ErrorKind { #[fail(display = "The timer of the heartbeat encountered an error: {}", _0)] HeartbeatTimer(#[fail(cause)] tokio_timer::Error), #[fail(display = "Failed to handle incoming frame: {:?}", _0)] - // FIXME: mark lapin_async's Error as cause once it implements Fail - InvalidFrame(lapin_async::error::Error), + InvalidFrame(#[fail(cause)] lapin_async::error::Error), #[fail(display = "Couldn't parse URI: {}", _0)] InvalidUri(String), #[fail(display = "Transport mutex is poisoned")] PoisonedMutex, #[fail(display = "{}: {:?}", _0, _1)] - // FIXME: mark lapin_async's Error as cause once it implements Fail - ProtocolError(String, lapin_async::error::Error), + ProtocolError(String, #[fail(cause)] lapin_async::error::Error), /// A hack to prevent developers from exhaustively match on the enum's variants /// /// The purpose of this variant is to let the `ErrorKind` enumeration grow more variants From 67f929adf2320ea765253f5be6941b6a450d21d5 Mon Sep 17 00:00:00 2001 From: Louis Kureuil Person Date: Fri, 23 Nov 2018 00:34:33 +0100 Subject: [PATCH 2/2] Increase type length limit to more than 16 millions characters I suppose this means we're writing Good Code (tm) --- futures/examples/client.rs | 3 +++ futures/tests/connection.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/futures/examples/client.rs b/futures/examples/client.rs index bb56d92f..d1376ad0 100644 --- a/futures/examples/client.rs +++ b/futures/examples/client.rs @@ -1,3 +1,6 @@ +// Long and nested future chains can quickly result in large generic types. +#![type_length_limit="16777216"] + #[macro_use] extern crate log; extern crate lapin_futures as lapin; extern crate failure; diff --git a/futures/tests/connection.rs b/futures/tests/connection.rs index d3f98855..02c96f36 100644 --- a/futures/tests/connection.rs +++ b/futures/tests/connection.rs @@ -1,3 +1,6 @@ +// Long and nested future chains can quickly result in large generic types. +#![type_length_limit="2097152"] + #[macro_use] extern crate log; extern crate lapin_futures as lapin; extern crate failure;