diff options
-rw-r--r-- | core/Cargo.toml | 1 | ||||
-rw-r--r-- | core/src/lib.rs | 83 | ||||
-rw-r--r-- | net/Cargo.toml | 1 | ||||
-rw-r--r-- | net/src/lib.rs | 87 | ||||
-rw-r--r-- | openpgp/Cargo.toml | 1 | ||||
-rw-r--r-- | openpgp/src/lib.rs | 3 | ||||
-rw-r--r-- | openpgp/src/tpk.rs | 33 | ||||
-rw-r--r-- | store/Cargo.toml | 1 | ||||
-rw-r--r-- | store/src/backend/mod.rs | 13 | ||||
-rw-r--r-- | store/src/lib.rs | 89 | ||||
-rw-r--r-- | store/src/macros.rs | 24 | ||||
-rw-r--r-- | tool/Cargo.toml | 1 | ||||
-rw-r--r-- | tool/src/main.rs | 127 |
13 files changed, 222 insertions, 242 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml index caafe03c..1bfb5222 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" authors = ["Justus Winter <justus@pep-project.org>"] [dependencies] +failure = "0.1.1" tempdir = "0.3.5" diff --git a/core/src/lib.rs b/core/src/lib.rs index 72de3de3..ed2452ce 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -19,8 +19,11 @@ /// ``` extern crate tempdir; +#[macro_use] +extern crate failure; use std::env; +use std::fmt; use std::fs; use std::io; use std::path::{Path, PathBuf}; @@ -244,21 +247,18 @@ impl Config { /* Error handling. */ /// Result type for Sequoia. -pub type Result<T> = ::std::result::Result<T, Error>; +pub type Result<T> = ::std::result::Result<T, failure::Error>; +#[derive(Fail, Debug)] /// Errors for Sequoia. -#[derive(Debug)] pub enum Error { /// The network policy was violated by the given action. + #[fail(display = "Unmet network policy requirement: {}", _0)] NetworkPolicyViolation(NetworkPolicy), - /// An `io::Error` occured. - IoError(io::Error), -} - -impl From<io::Error> for Error { - fn from(error: io::Error) -> Self { - Error::IoError(error) - } + #[fail(display = "IO error: {}", error)] + IoError { error: io::Error }, + #[fail(display = "An unknown error has occurred.")] + UnknownError, } /* Network policy. */ @@ -284,10 +284,21 @@ pub enum NetworkPolicy { Insecure, } +impl fmt::Display for NetworkPolicy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", match self { + &NetworkPolicy::Offline => "Offline", + &NetworkPolicy::Anonymized => "Anonymized", + &NetworkPolicy::Encrypted => "Encrypted", + &NetworkPolicy::Insecure => "Insecure", + }) + } +} + impl NetworkPolicy { pub fn assert(&self, action: NetworkPolicy) -> Result<()> { if action > *self { - Err(Error::NetworkPolicyViolation(action)) + Err(Error::NetworkPolicyViolation(action).into()) } else { Ok(()) } @@ -412,47 +423,49 @@ macro_rules! assert_match { mod network_policy_test { use super::{Error, NetworkPolicy}; + fn ok(policy: NetworkPolicy, required: NetworkPolicy) { + assert!(policy.assert(required).is_ok()); + } + + fn fail(policy: NetworkPolicy, required: NetworkPolicy) { + assert_match!(Error::NetworkPolicyViolation(_) + = policy.assert(required) + .err().unwrap().downcast::<Error>().unwrap()); + } + #[test] fn offline() { let p = NetworkPolicy::Offline; - assert_match!( - Err(Error::NetworkPolicyViolation(_)) = p.assert(NetworkPolicy::Anonymized)); - assert_match!( - Err(Error::NetworkPolicyViolation(_)) = p.assert(NetworkPolicy::Encrypted)); - assert_match!( - Err(Error::NetworkPolicyViolation(_)) = p.assert(NetworkPolicy::Insecure)); + ok(p, NetworkPolicy::Offline); + fail(p, NetworkPolicy::Anonymized); + fail(p, NetworkPolicy::Encrypted); + fail(p, NetworkPolicy::Insecure); } #[test] fn anonymized() { let p = NetworkPolicy::Anonymized; - assert_match!( - Ok(()) = p.assert(NetworkPolicy::Anonymized)); - assert_match!( - Err(Error::NetworkPolicyViolation(_)) = p.assert(NetworkPolicy::Encrypted)); - assert_match!( - Err(Error::NetworkPolicyViolation(_)) = p.assert(NetworkPolicy::Insecure)); + ok(p, NetworkPolicy::Offline); + ok(p, NetworkPolicy::Anonymized); + fail(p, NetworkPolicy::Encrypted); + fail(p, NetworkPolicy::Insecure); } #[test] fn encrypted() { let p = NetworkPolicy::Encrypted; - assert_match!( - Ok(()) = p.assert(NetworkPolicy::Anonymized)); - assert_match!( - Ok(()) = p.assert(NetworkPolicy::Encrypted)); - assert_match!( - Err(Error::NetworkPolicyViolation(_)) = p.assert(NetworkPolicy::Insecure)); + ok(p, NetworkPolicy::Offline); + ok(p, NetworkPolicy::Anonymized); + ok(p, NetworkPolicy::Encrypted); + fail(p, NetworkPolicy::Insecure); } #[test] fn insecure() { let p = NetworkPolicy::Insecure; - assert_match!( - Ok(()) = p.assert(NetworkPolicy::Anonymized)); - assert_match!( - Ok(()) = p.assert(NetworkPolicy::Encrypted)); - assert_match!( - Ok(()) = p.assert(NetworkPolicy::Insecure)); + ok(p, NetworkPolicy::Offline); + ok(p, NetworkPolicy::Anonymized); + ok(p, NetworkPolicy::Encrypted); + ok(p, NetworkPolicy::Insecure); } } diff --git a/net/Cargo.toml b/net/Cargo.toml index 91775697..06a3ad72 100644 --- a/net/Cargo.toml +++ b/net/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Justus Winter <justus@pep-project.org>"] openpgp = { path = "../openpgp" } sequoia-core = { path = "../core" } +failure = "0.1.1" fs2 = "0.4.2" futures = "0.1" hyper = "0.11" diff --git a/net/src/lib.rs b/net/src/lib.rs index 0e5497b5..52a43a60 100644 --- a/net/src/lib.rs +++ b/net/src/lib.rs @@ -33,6 +33,8 @@ extern crate openpgp; extern crate sequoia_core; +#[macro_use] +extern crate failure; extern crate futures; extern crate hyper; extern crate hyper_tls; @@ -54,10 +56,9 @@ use self::native_tls::{Certificate, TlsConnector}; use self::tokio_core::reactor::Core; use std::convert::From; use std::io::{Cursor, Read}; -use std::io; use sequoia_core::{Context, NetworkPolicy}; -use openpgp::tpk::{self, TPK}; +use openpgp::tpk::TPK; use openpgp::{Message, KeyID, armor}; pub mod ipc; @@ -93,7 +94,7 @@ impl KeyServer { &core.handle())?) .build(&core.handle())) }, - _ => return Err(Error::MalformedUri), + _ => return Err(Error::MalformedUri.into()), }; Self::make(ctx, core, client, uri) @@ -174,14 +175,14 @@ impl KeyServer { r.read_to_end(&mut key)?; Ok(key) }, - StatusCode::NotFound => Err(Error::NotFound), - n => Err(Error::from(n)), + StatusCode::NotFound => Err(Error::NotFound.into()), + n => Err(Error::HttpStatus(n).into()), } - Err(e) => Err(Error::HyperError(e)), + Err(e) => Err(Error::HyperError(e).into()), }; let m = Message::from_bytes(&key?)?; - TPK::from_message(m).map_err(|e| Error::KeysError(e)) + TPK::from_message(m) } /// Sends the given key to the server. @@ -216,10 +217,10 @@ impl KeyServer { Ok((status, _body)) => match status { StatusCode::Ok => Ok(()), - StatusCode::NotFound => Err(Error::ProtocolViolation), - n => Err(Error::from(n)), + StatusCode::NotFound => Err(Error::ProtocolViolation.into()), + n => Err(Error::HttpStatus(n).into()), } - Err(e) => Err(Error::HyperError(e)), + Err(e) => Err(Error::HyperError(e).into()), } } } @@ -248,73 +249,33 @@ impl AClient for Client<HttpsConnector<HttpConnector>> { } /// Results for sequoia-net. -pub type Result<T> = ::std::result::Result<T, Error>; +pub type Result<T> = ::std::result::Result<T, failure::Error>; +#[derive(Fail, Debug)] /// Errors returned from the network routines. -#[derive(Debug)] pub enum Error { /// A requested key was not found. + #[fail(display = "Key not found")] NotFound, /// A given keyserver URI was malformed. + #[fail(display = "Malformed URI")] MalformedUri, /// The server provided malformed data. + #[fail(display = "Malformed response from server")] MalformedResponse, /// A communication partner violated the protocol. + #[fail(display = "Protocol violation")] ProtocolViolation, - /// There was an error parsing the key. - KeysError(tpk::Error), - /// A `sequoia_core::Error` occured. - CoreError(sequoia_core::Error), /// Encountered an unexpected low-level http status. + #[fail(display = "Error communicating with server")] HttpStatus(hyper::StatusCode), - /// An `io::Error` occured. - IoError(io::Error), - /// A `hyper::error::UriError` occured. + /// A `hyper::error::UriError` occurred. + #[fail(display = "URI Error")] UriError(hyper::error::UriError), - /// A `hyper::Error` occured. + /// A `hyper::Error` occurred. + #[fail(display = "Hyper Error")] HyperError(hyper::Error), - /// A `native_tls::Error` occured. + /// A `native_tls::Error` occurred. + #[fail(display = "TLS Error")] TlsError(native_tls::Error), } - -impl From<tpk::Error> for Error { - fn from(e: tpk::Error) -> Self { - Error::KeysError(e) - } -} - -impl From<sequoia_core::Error> for Error { - fn from(e: sequoia_core::Error) -> Self { - Error::CoreError(e) - } -} - -impl From<hyper::StatusCode> for Error { - fn from(status: hyper::StatusCode) -> Self { - Error::HttpStatus(status) - } -} - -impl From<io::Error> for Error { - fn from(error: io::Error) -> Self { - Error::IoError(error) - } -} - -impl From<hyper::Error> for Error { - fn from(error: hyper::Error) -> Self { - Error::HyperError(error) - } -} - -impl From<hyper::error::UriError> for Error { - fn from(error: hyper::error::UriError) -> Self { - Error::UriError(error) - } -} - -impl From<native_tls::Error> for Error { - fn from(error: native_tls::Error) -> Self { - Error::TlsError(error) - } -} diff --git a/openpgp/Cargo.toml b/openpgp/Cargo.toml index 9e41958f..175f8285 100644 --- a/openpgp/Cargo.toml +++ b/openpgp/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Neal H. Walfield <neal@gnu.org>"] buffered-reader = { path = "../buffered-reader" } base64 = "0.8.0" bzip2 = "0.3.2" +failure = "0.1.1" flate2 = "0.2" nettle = { git = "https://gitlab.com/sequoia-pgp/nettle-rs.git" } num = "0.1.40" diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs index ca66a356..9c623069 100644 --- a/openpgp/src/lib.rs +++ b/openpgp/src/lib.rs @@ -36,6 +36,9 @@ //! [unhashed signature subpackets]: https://tools.ietf.org/html/rfc4880#section-5.2.3.2 //! [sequoia-core]: ../sequoia_core +#[macro_use] +extern crate failure; + extern crate buffered_reader; // For #[derive(FromPrimitive)] diff --git a/openpgp/src/tpk.rs b/openpgp/src/tpk.rs index 0c3d810e..47054c9b 100644 --- a/openpgp/src/tpk.rs +++ b/openpgp/src/tpk.rs @@ -1,5 +1,6 @@ //! Transferable public keys. +use failure; use std::io; use std::cmp::Ordering; use std::path::Path; @@ -370,7 +371,7 @@ impl TPKParser { subkeys: self.subkeys } } else { - return Err(Error::NoKeyFound); + return Err(Error::NoKeyFound.into()); }; match self.state { @@ -387,7 +388,7 @@ impl TPKParser { Ok(tpk) }, TPKParserState::End => Ok(tpk), - _ => Err(Error::NoKeyFound), + _ => Err(Error::NoKeyFound.into()), }.and_then(|tpk| tpk.canonicalize()) } } @@ -431,8 +432,7 @@ impl TPK { /// Returns the first TPK encountered in the reader. pub fn from_reader<R: io::Read>(reader: R) -> Result<Self> { - let ppo = PacketParser::from_reader(reader) - .map_err(|e| Error::IoError(e))?; + let ppo = PacketParser::from_reader(reader)?; if let Some(pp) = ppo { TPK::from_packet_parser(pp) } else { @@ -463,8 +463,7 @@ impl TPK { /// /// `buf` must be an OpenPGP encoded message. pub fn from_bytes(buf: &[u8]) -> Result<Self> { - let ppo = PacketParser::from_bytes(buf) - .map_err(|e| Error::IoError(e))?; + let ppo = PacketParser::from_bytes(buf)?; if let Some(pp) = ppo { TPK::from_packet_parser(pp) } else { @@ -491,7 +490,7 @@ impl TPK { // - One or more User ID packets. if self.userids.len() == 0 { - return Err(Error::NoUserId); + return Err(Error::NoUserId.into()); } // Drop invalid user ids. @@ -848,23 +847,17 @@ impl TPK { } /// Results for TPK. -pub type Result<T> = ::std::result::Result<T, Error>; +pub type Result<T> = ::std::result::Result<T, failure::Error>; +#[derive(Fail, Debug)] /// Errors returned from the key routines. -#[derive(Debug)] pub enum Error { + #[fail(display = "No key found")] /// No key found in OpenPGP message. NoKeyFound, + #[fail(display = "No UID found")] /// No user id found. NoUserId, - /// An `io::Error` occured. - IoError(io::Error), -} - -impl From<io::Error> for Error { - fn from(error: io::Error) -> Self { - Error::IoError(error) - } } #[cfg(test)] @@ -900,11 +893,13 @@ mod test { for i in 0..2 { let tpk = parse_tpk(bytes!("testy-broken-no-pk.pgp"), i == 0); - assert_match!(Err(Error::NoKeyFound) = tpk); + assert_match!(Error::NoKeyFound + = tpk.err().unwrap().downcast::<Error>().unwrap()); let tpk = parse_tpk(bytes!("testy-broken-no-uid.pgp"), i == 0); - assert_match!(Err(Error::NoUserId) = tpk); + assert_match!(Error::NoUserId + = tpk.err().unwrap().downcast::<Error>().unwrap()); // We have: // diff --git a/store/Cargo.toml b/store/Cargo.toml index 47fbd373..cca0dc15 100644 --- a/store/Cargo.toml +++ b/store/Cargo.toml @@ -14,6 +14,7 @@ sequoia-core = { path = "../core" } sequoia-net = { path = "../net" } capnp = "0.8" capnp-rpc = "0.8" +failure = "0.1.1" futures = "0.1.17" rand = "0.3" rusqlite = "0.12.0" diff --git a/store/src/backend/mod.rs b/store/src/backend/mod.rs index 6037c15c..10afe15a 100644 --- a/store/src/backend/mod.rs +++ b/store/src/backend/mod.rs @@ -1,5 +1,6 @@ //! Storage backend. +use failure; use std::cmp; use std::fmt; use std::io; @@ -1060,6 +1061,18 @@ impl From<rusqlite::Error> for node::Error { } } +impl From<failure::Error> for node::Error { + fn from(e: failure::Error) -> Self { + let e = e.downcast::<tpk::Error>(); + if e.is_ok() { + return node::Error::MalformedKey; + } + + //let e = e.err().unwrap().downcast::<...>(); + node::Error::SystemError + } +} + impl From<tpk::Error> for node::Error { fn from(_: tpk::Error) -> Self { node::Error::MalformedKey diff --git a/store/src/lib.rs b/store/src/lib.rs index d43fe98a..8097e0f6 100644 --- a/store/src/lib.rs +++ b/store/src/lib.rs @@ -51,6 +51,8 @@ extern crate capnp; #[macro_use] extern crate capnp_rpc; +#[macro_use] +extern crate failure; extern crate futures; extern crate rand; extern crate rusqlite; @@ -60,7 +62,6 @@ extern crate tokio_io; use std::cell::RefCell; use std::fmt; -use std::io; use std::rc::Rc; use capnp::capability::Promise; @@ -76,7 +77,7 @@ extern crate sequoia_core; extern crate sequoia_net; use openpgp::Fingerprint; -use openpgp::tpk::{self, TPK}; +use openpgp::tpk::TPK; use sequoia_core as core; use sequoia_core::Context; use sequoia_net::ipc; @@ -338,7 +339,7 @@ impl Store { /// // ... /// let store = Store::open(&ctx, "default")?; /// let binding = store.lookup("Mister B."); - /// assert_match!(Err(Error::NotFound) = binding); + /// assert!(binding.is_err()); // not found /// # Ok(()) /// # } /// ``` @@ -479,7 +480,7 @@ impl Binding { /// // later... /// let binding = store.lookup("Testy McTestface")?; /// let r = binding.import(&new); - /// assert_match!(Err(Error::Conflict) = r); // no signature from old on new + /// assert!(r.is_err()); // no signature from old on new /// let r = binding.import(&new_sig)?; /// assert_eq!(new.fingerprint(), r.fingerprint()); /// # Ok(()) @@ -535,7 +536,7 @@ impl Binding { /// // later... /// let binding = store.lookup("Testy McTestface")?; /// let r = binding.import(&new); - /// assert_match!(Err(Error::Conflict) = r); // no signature from old on new + /// assert!(r.is_err()); // no signature from old on new /// let r = binding.rotate(&new)?; /// assert_eq!(new.fingerprint(), r.fingerprint()); /// # Ok(()) @@ -575,7 +576,7 @@ impl Binding { /// let binding = store.add("Mister B.", &fp)?; /// binding.delete()?; /// let binding = store.lookup("Mister B."); - /// assert_match!(Err(Error::NotFound) = binding); + /// assert!(binding.is_err()); // not found /// # Ok(()) /// # } /// ``` @@ -676,7 +677,7 @@ impl Key { /// let r = key.import(&old)?; /// assert_eq!(r.fingerprint(), old.fingerprint()); /// let r = key.import(&new); - /// assert_match!(Err(Error::Conflict) = r); + /// assert!(r.is_err()); // conflict /// # Ok(()) /// # } /// ``` @@ -914,7 +915,7 @@ impl Iterator for LogIter { r.get_error().ok() } else { None - }).ok_or(Error::StoreError)) + }).ok_or(Error::StoreError.into())) }; doit().ok() } @@ -923,18 +924,18 @@ impl Iterator for LogIter { /* Error handling. */ /// Results for sequoia-store. -pub type Result<T> = ::std::result::Result<T, Error>; +pub type Result<T> = ::std::result::Result<T, failure::Error>; // Converts from backend errors. -impl From<node::Error> for Error { +impl From<node::Error> for failure::Error { fn from(error: node::Error) -> Self { match error { - node::Error::Unspecified => Error::StoreError, - node::Error::NotFound => Error::NotFound, - node::Error::Conflict => Error::Conflict, - node::Error::SystemError => Error::StoreError, - node::Error::MalformedKey => Error::MalformedKey, + node::Error::Unspecified => Error::StoreError.into(), + node::Error::NotFound => Error::NotFound.into(), + node::Error::Conflict => Error::Conflict.into(), + node::Error::SystemError => Error::StoreError.into(), + node::Error::MalformedKey => Error::MalformedKey.into(), node::Error::NetworkPolicyViolationOffline => core::Error::NetworkPolicyViolation(core::NetworkPolicy::Offline).into(), node::Error::NetworkPolicyViolationAnonymized => @@ -947,48 +948,30 @@ impl From<node::Error> for Error { } } - +#[derive(Fail, Debug)] /// Errors returned from the store. -#[derive(Debug)] pub enum Error { /// A requested key was not found. + #[fail(display = "Key not found")] NotFound, /// The new key is in conflict with the current key. + #[fail(display = "New key conflicts with the current key")] Conflict, - /// A `sequoia_core::Error` occurred. - CoreError(sequoia_core::Error), - /// An `io::Error` occurred. - IoError(io::Error), /// This is a catch-all for unspecified backend errors, and should /// go away soon. + #[fail(display = "Unspecified store error")] StoreError, /// A protocol error occurred. + #[fail(display = "Unspecified protocol error")] ProtocolError, /// A TPK is malformed. + #[fail(display = "Malformed key")] MalformedKey, - /// A `openpgp::tpk::Error` occurred. - TpkError(tpk::Error), /// A `capnp::Error` occurred. + #[fail(display = "Internal RPC error")] RpcError(capnp::Error), } -impl From<sequoia_core::Error> for Error { - fn from(error: sequoia_core::Error) -> Self { - Error::CoreError(error) - } -} - -impl From<io::Error> for Error { - fn from(error: io::Error) -> Self { - Error::IoError(error) - } -} - -impl From<tpk::Error> for Error { - fn from(error: tpk::Error) -> Self { - Error::TpkError(error) - } -} impl From<capnp::Error> for Error { fn from(error: capnp::Error) -> Self { Error::RpcError(error) @@ -1025,7 +1008,8 @@ mod store_test { .ipc_policy(core::IPCPolicy::Internal) .build().unwrap(); let store = Store::open(&ctx2, "default"); - assert_match!(Err(Error::CoreError(core::Error::NetworkPolicyViolation(_))) = store); + assert_match!(core::Error::NetworkPolicyViolation(_) + = store.err().unwrap().downcast::<core::Error>().unwrap()); } #[test] @@ -1052,7 +1036,8 @@ mod store_test { .build().unwrap(); let store = Store::open(&ctx, "default").unwrap(); let r = store.lookup("I do not exist"); - assert_match!(Err(Error::NotFound) = r); + assert_match!(Error::NotFound + = r.err().unwrap().downcast::<Error>().unwrap()); } #[test] @@ -1067,7 +1052,8 @@ mod store_test { let fp = Fingerprint::from_bytes(b"bbbbbbbbbbbbbbbbbbbb"); let binding = store.add("Mister B.", &fp).unwrap(); let r = binding.import(&tpk); - assert_match!(Err(Error::Conflict) = r); + assert_match!(Error::Conflict + = r.err().unwrap().downcast::<Error>().unwrap()); } #[test] @@ -1081,8 +1067,9 @@ mod store_test { let b = Fingerprint::from_bytes(b"bbbbbbbbbbbbbbbbbbbb"); store.add("Mister B.", &b).unwrap(); let c = Fingerprint::from_bytes(b"cccccccccccccccccccc"); - assert_match!(Err(Error::Conflict) - = store.add("Mister B.", &c)); + assert_match!(Error::Conflict + = store.add("Mister B.", &c) + .err().unwrap().downcast::<Error>().unwrap()); } #[test] @@ -1109,10 +1096,12 @@ mod store_test { let s1 = Store::open(&ctx, "default").unwrap(); s0.delete().unwrap(); let binding = s1.lookup("Foobarbaz"); - assert_match!(Err(Error::NotFound) = binding); + assert_match!(Error::NotFound + = binding.err().unwrap().downcast::<Error>().unwrap()); let fp = Fingerprint::from_bytes(b"bbbbbbbbbbbbbbbbbbbb"); let binding = s1.add("Mister B.", &fp); - assert_match!(Err(Error::NotFound) = binding); + assert_match!(Error::NotFound + = binding.err().unwrap().downcast::<Error>().unwrap()); } #[test] @@ -1142,8 +1131,10 @@ mod store_test { let b0 = store.add("Mister B.", &fp).unwrap(); let b1 = store.lookup("Mister B.").unwrap(); b0.delete().unwrap(); - assert_match!(Err(Error::NotFound) = b1.stats()); - assert_match!(Err(Error::NotFound) = b1.key()); + assert_match!(Error::NotFound + = b1.stats().err().unwrap().downcast::<Error>().unwrap()); + assert_match!(Error::NotFound + = b1.key().err().unwrap().downcast::<Error>().unwrap()); } fn make_some_stores() -> core::Context { diff --git a/store/src/macros.rs b/store/src/macros.rs index 11e5f085..c8b61334 100644 --- a/store/src/macros.rs +++ b/store/src/macros.rs @@ -16,15 +16,15 @@ macro_rules! make_request { let r: std::result::Result<Result<_>, capnp::Error> = $core.run( $request.send().promise - .and_then(|response| { + .and_then(|response| -> Promise<Result<_>, capnp::Error> |