From bb39d138d89a50a025ab591712fd6daaef705743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jind=C5=99ich=20Moravec?= Date: Tue, 12 Dec 2023 19:31:27 +0100 Subject: [PATCH] refactor(proto): start replacing anyhow with thiserror --- proto/Cargo.toml | 1 + proto/src/message/backend.rs | 16 +++++++++++++--- proto/src/message/errors.rs | 16 ++++++++++++++++ proto/src/message/frontend.rs | 17 ++++++++++++++--- proto/src/message/mod.rs | 1 + proto/src/message/primitive/data.rs | 13 +++++++------ proto/src/message/proto_message.rs | 6 ++++-- proto/src/reader/oneway.rs | 2 +- 8 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 proto/src/message/errors.rs diff --git a/proto/Cargo.toml b/proto/Cargo.toml index 6e5d2fb..9fb51ce 100644 --- a/proto/Cargo.toml +++ b/proto/Cargo.toml @@ -8,3 +8,4 @@ bincode = "2.0.0-rc.3" anyhow = "1.0.75" tokio = { version = "1.34.0", features = ["io-util", "macros", "test-util"] } async-trait = "0.1.74" +thiserror = "1.0.50" diff --git a/proto/src/message/backend.rs b/proto/src/message/backend.rs index 1d96833..7ba0004 100644 --- a/proto/src/message/backend.rs +++ b/proto/src/message/backend.rs @@ -3,6 +3,7 @@ use crate::message::primitive::pglist::PgList; use crate::message::primitive::pgstring::PgString; use crate::message::proto_message::ProtoMessage; use bincode::{Decode, Encode}; +use crate::message::errors::{ProtoDeserializeError, ProtoSerializeError}; #[derive(Debug)] pub enum BackendMessage { @@ -34,7 +35,7 @@ impl ProtoMessage for BackendMessage { } } - fn serialize(&self) -> anyhow::Result> { + fn serialize(&self) -> Result, ProtoSerializeError> { match self { BackendMessage::AuthenticationOk(data) => data.serialize(), BackendMessage::BackendKeyData(data) => data.serialize(), @@ -49,7 +50,7 @@ impl ProtoMessage for BackendMessage { } } - fn deserialize(variant: u8, data: &[u8]) -> anyhow::Result { + fn deserialize(variant: u8, data: &[u8]) -> Result { match variant { b'R' => Ok(BackendMessage::AuthenticationOk( AuthenticationOkData::deserialize(data)?, @@ -84,7 +85,7 @@ impl ProtoMessage for BackendMessage { let data = RowDescriptionData::deserialize(data)?; Ok(BackendMessage::RowDescription(data)) } - v => Err(anyhow::anyhow!("Unknown backend message variant: {v}")), + v => Err(ProtoDeserializeError::InvalidVariant(v)), } } } @@ -354,4 +355,13 @@ mod tests { _ => false, },) } + + #[test] + fn test_unknown_variant() { + let variant = 0; + let data = vec![1, 2, 3]; + + let message = BackendMessage::deserialize(variant, &data); + assert!(matches!(message, Err(ProtoDeserializeError::InvalidVariant(0)))); + } } diff --git a/proto/src/message/errors.rs b/proto/src/message/errors.rs new file mode 100644 index 0000000..7a3e04e --- /dev/null +++ b/proto/src/message/errors.rs @@ -0,0 +1,16 @@ +use bincode::error::{DecodeError, EncodeError}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ProtoDeserializeError { + #[error("invalid message variant: {0}")] + InvalidVariant(u8), + #[error("decoding of inner data failed")] + DecodeData(#[from] DecodeError), +} + +#[derive(Debug, Error)] +pub enum ProtoSerializeError { + #[error("encoding of inner data failed")] + EncodeData(#[from] EncodeError), +} diff --git a/proto/src/message/frontend.rs b/proto/src/message/frontend.rs index 4914fc2..6d7f993 100644 --- a/proto/src/message/frontend.rs +++ b/proto/src/message/frontend.rs @@ -2,6 +2,7 @@ use crate::message::primitive::data::MessageData; use crate::message::primitive::pgstring::PgString; use crate::message::proto_message::ProtoMessage; use bincode::{Decode, Encode}; +use crate::message::errors::{ProtoDeserializeError, ProtoSerializeError}; #[derive(Debug)] pub enum FrontendMessage { @@ -17,18 +18,18 @@ impl ProtoMessage for FrontendMessage { } } - fn serialize(&self) -> anyhow::Result> { + fn serialize(&self) -> Result, ProtoSerializeError> { match self { FrontendMessage::Query(data) => data.serialize(), FrontendMessage::Terminate => Ok(Vec::with_capacity(0)), } } - fn deserialize(variant: u8, data: &[u8]) -> anyhow::Result { + fn deserialize(variant: u8, data: &[u8]) -> Result { match variant { b'Q' => Ok(FrontendMessage::Query(QueryData::deserialize(data)?)), b'X' => Ok(FrontendMessage::Terminate), - v => Err(anyhow::anyhow!("Unknown frontend message variant: {v}")), + v => Err(ProtoDeserializeError::InvalidVariant(v)), } } } @@ -40,6 +41,7 @@ pub struct QueryData { #[cfg(test)] mod tests { + use crate::message::backend::BackendMessage; use super::*; #[test] @@ -65,4 +67,13 @@ mod tests { let message = FrontendMessage::deserialize(variant, &raw).unwrap(); assert!(matches!(message, FrontendMessage::Terminate)); } + + #[test] + fn test_unknown_variant() { + let variant = 0; + let data = vec![1, 2, 3]; + + let message = BackendMessage::deserialize(variant, &data); + assert!(matches!(message, Err(ProtoDeserializeError::InvalidVariant(0)))); + } } diff --git a/proto/src/message/mod.rs b/proto/src/message/mod.rs index 527e584..2c11140 100644 --- a/proto/src/message/mod.rs +++ b/proto/src/message/mod.rs @@ -3,3 +3,4 @@ pub mod frontend; pub mod primitive; pub mod proto_message; pub mod special; +pub mod errors; diff --git a/proto/src/message/primitive/data.rs b/proto/src/message/primitive/data.rs index 41af0f6..37b491a 100644 --- a/proto/src/message/primitive/data.rs +++ b/proto/src/message/primitive/data.rs @@ -1,9 +1,10 @@ use crate::message::primitive::config::pg_proto_config; use bincode::{Decode, Encode}; +use crate::message::errors::{ProtoDeserializeError, ProtoSerializeError}; pub trait MessageData: Sized { - fn deserialize(data: &[u8]) -> anyhow::Result; - fn serialize(&self) -> anyhow::Result>; + fn serialize(&self) -> Result, ProtoSerializeError>; + fn deserialize(data: &[u8]) -> Result; } impl MessageData for T @@ -11,12 +12,12 @@ where T: Encode + Decode, { #[inline] - fn deserialize(data: &[u8]) -> anyhow::Result { - Ok(bincode::decode_from_slice(data, pg_proto_config())?.0) + fn serialize(&self) -> Result, ProtoSerializeError> { + Ok(bincode::encode_to_vec(self, pg_proto_config())?) } #[inline] - fn serialize(&self) -> anyhow::Result> { - Ok(bincode::encode_to_vec(self, pg_proto_config())?) + fn deserialize(data: &[u8]) -> Result { + Ok(bincode::decode_from_slice(data, pg_proto_config())?.0) } } diff --git a/proto/src/message/proto_message.rs b/proto/src/message/proto_message.rs index f2a1a4d..13986e1 100644 --- a/proto/src/message/proto_message.rs +++ b/proto/src/message/proto_message.rs @@ -1,5 +1,7 @@ +use crate::message::errors::{ProtoDeserializeError, ProtoSerializeError}; + pub trait ProtoMessage: Sized { fn variant(&self) -> u8; - fn serialize(&self) -> anyhow::Result>; - fn deserialize(variant: u8, data: &[u8]) -> anyhow::Result; + fn serialize(&self) -> Result, ProtoSerializeError>; + fn deserialize(variant: u8, data: &[u8]) -> Result; } diff --git a/proto/src/reader/oneway.rs b/proto/src/reader/oneway.rs index 4cca72b..16508cb 100644 --- a/proto/src/reader/oneway.rs +++ b/proto/src/reader/oneway.rs @@ -32,6 +32,6 @@ where let mut data = vec![0u8; (length - 4) as usize]; self.inner.read_exact(&mut data).await?; - T::deserialize(variant, &data) + Ok(T::deserialize(variant, &data)?) } }