Loading codegen/src/error.rs +8 −5 Original line number Diff line number Diff line Loading @@ -114,7 +114,7 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { g.ln("use hyper::StatusCode;"); g.lf(); g.ln("#[derive(Debug, Clone, Copy, PartialEq, Eq)]"); g.ln("#[derive(Debug, Clone, PartialEq, Eq)]"); g.ln("#[non_exhaustive]"); g.ln("pub enum S3ErrorCode {"); for err in errors.values() { Loading Loading @@ -149,6 +149,7 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { g.ln(f!("{},", err.code)); g.lf(); } g.ln("Unknown(Box<str>),"); g.ln("}"); g.lf(); Loading @@ -156,12 +157,13 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { { g.ln("#[must_use]"); g.ln("pub const fn as_str(&self) -> &'static str {"); g.ln("pub fn as_str(&self) -> &str {"); g.ln("match self {"); for err in errors.values() { g.ln(f!("Self::{} => \"{}\",", err.code, err.code)); } g.ln("Self::Unknown(s) => s,"); g.ln("}"); g.ln("}"); Loading @@ -170,13 +172,13 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { { g.ln("#[must_use]"); g.ln("pub const fn from_bytes(s: &[u8]) -> Option<Self> {"); g.ln("pub fn from_bytes(s: &[u8]) -> Option<Self> {"); g.ln("match s {"); for err in errors.values() { g.ln(f!("b\"{}\" => Some(Self::{}),", err.code, err.code)); } g.ln("_ => None"); g.ln("_ => std::str::from_utf8(s).ok().map(|s| Self::Unknown(s.into()))"); g.ln("}"); g.ln("}"); Loading @@ -185,7 +187,7 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { { g.ln("#[must_use]"); g.ln("pub const fn status_code(self) -> Option<StatusCode> {"); g.ln("pub fn status_code(&self) -> Option<StatusCode> {"); g.ln("match self {"); for err in errors.values() { Loading Loading @@ -218,6 +220,7 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { } g.ln(f!("Self::{} => None,", err.code)); } g.ln("Self::Unknown(_) => None,"); g.ln("}"); g.ln("}"); Loading crates/s3s/src/error/generated.rs +9 −5 Original line number Diff line number Diff line use hyper::StatusCode; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum S3ErrorCode { /// Access Denied Loading Loading @@ -485,11 +485,13 @@ pub enum S3ErrorCode { /// HTTP Status Code: 400 Bad Request /// UserKeyMustBeSpecified, Unknown(Box<str>), } impl S3ErrorCode { #[must_use] pub const fn as_str(&self) -> &'static str { pub fn as_str(&self) -> &str { match self { Self::AccessDenied => "AccessDenied ", Self::AccountProblem => "AccountProblem", Loading Loading @@ -571,11 +573,12 @@ impl S3ErrorCode { Self::UnexpectedContent => "UnexpectedContent", Self::UnresolvableGrantByEmailAddress => "UnresolvableGrantByEmailAddress", Self::UserKeyMustBeSpecified => "UserKeyMustBeSpecified", Self::Unknown(s) => s, } } #[must_use] pub const fn from_bytes(s: &[u8]) -> Option<Self> { pub fn from_bytes(s: &[u8]) -> Option<Self> { match s { b"AccessDenied " => Some(Self::AccessDenied), b"AccountProblem" => Some(Self::AccountProblem), Loading Loading @@ -657,12 +660,12 @@ impl S3ErrorCode { b"UnexpectedContent" => Some(Self::UnexpectedContent), b"UnresolvableGrantByEmailAddress" => Some(Self::UnresolvableGrantByEmailAddress), b"UserKeyMustBeSpecified" => Some(Self::UserKeyMustBeSpecified), _ => None, _ => std::str::from_utf8(s).ok().map(|s| Self::Unknown(s.into())), } } #[must_use] pub const fn status_code(self) -> Option<StatusCode> { pub fn status_code(&self) -> Option<StatusCode> { match self { Self::AccessDenied => Some(StatusCode::FORBIDDEN), Self::AccountProblem => Some(StatusCode::FORBIDDEN), Loading Loading @@ -744,6 +747,7 @@ impl S3ErrorCode { Self::UnexpectedContent => Some(StatusCode::BAD_REQUEST), Self::UnresolvableGrantByEmailAddress => Some(StatusCode::BAD_REQUEST), Self::UserKeyMustBeSpecified => Some(StatusCode::BAD_REQUEST), Self::Unknown(_) => None, } } } crates/s3s/src/error/mod.rs +60 −43 Original line number Diff line number Diff line Loading @@ -4,89 +4,98 @@ pub use self::generated::*; use crate::xml; use std::borrow::Cow; use std::convert::Infallible; use std::fmt; use std::io::Write; use std::str::FromStr; use hyper::StatusCode; pub type S3Result<T = (), E = S3Error> = std::result::Result<T, E>; #[derive(Debug, thiserror::Error)] pub struct S3Error { pub struct S3Error(Box<Inner>); #[derive(Debug)] struct Inner { code: S3ErrorCode, message: Option<Cow<'static, str>>, resource: Option<String>, // resource: Option<String>, request_id: Option<String>, status_code: Option<StatusCode>, source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>, } impl S3Error { #[must_use] pub fn new(code: S3ErrorCode) -> Self { Self { Self(Box::new(Inner { code, message: None, resource: None, // resource: None, request_id: None, status_code: None, source: None, } })) } #[must_use] pub fn with_message(code: S3ErrorCode, msg: impl Into<Cow<'static, str>>) -> Self { Self { code, message: Some(msg.into()), resource: None, request_id: None, source: None, } let mut this = Self::new(code); this.0.message = Some(msg.into()); this } #[must_use] pub fn with_source(code: S3ErrorCode, source: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self { Self { code, message: None, resource: None, request_id: None, source: Some(source), } let mut this = Self::new(code); this.0.source = Some(source); this } pub fn set_code(&mut self, val: S3ErrorCode) { self.code = val; self.0.code = val; } pub fn set_message(&mut self, val: impl Into<Cow<'static, str>>) { self.message = Some(val.into()); self.0.message = Some(val.into()); } pub fn set_request_id(&mut self, val: impl Into<String>) { self.request_id = Some(val.into()); self.0.request_id = Some(val.into()); } pub fn set_source(&mut self, val: Box<dyn std::error::Error + Send + Sync + 'static>) { self.source = Some(val); self.0.source = Some(val); } pub fn set_status_code(&mut self, val: StatusCode) { self.0.status_code = Some(val); } #[must_use] pub fn code(&self) -> S3ErrorCode { self.code pub fn code(&self) -> &S3ErrorCode { &self.0.code } #[must_use] pub fn message(&self) -> Option<&str> { self.message.as_deref() self.0.message.as_deref() } #[must_use] pub fn request_id(&self) -> Option<&str> { self.request_id.as_deref() self.0.request_id.as_deref() } #[must_use] pub fn source(&self) -> Option<&(dyn std::error::Error + Send + Sync + 'static)> { self.source.as_deref() self.0.source.as_deref() } #[must_use] pub fn status_code(&self) -> Option<StatusCode> { self.0.status_code.or_else(|| self.0.code.status_code()) } #[must_use] Loading @@ -106,14 +115,14 @@ impl xml::Serialize for S3Error { impl xml::SerializeContent for S3Error { fn serialize_content<W: Write>(&self, s: &mut xml::Serializer<W>) -> xml::SerResult { s.content("Code", self.code.as_str())?; if let Some(val) = self.message.as_deref() { s.content("Code", self.0.code.as_str())?; if let Some(val) = self.0.message.as_deref() { s.content("Message", val)?; } if let Some(val) = self.resource.as_deref() { s.content("Resource", val)?; } if let Some(val) = self.request_id.as_deref() { // if let Some(val) = self.0.resource.as_deref() { // s.content("Resource", val)?; // } if let Some(val) = self.0.request_id.as_deref() { s.content("RequestId", val)?; } Ok(()) Loading @@ -126,14 +135,26 @@ impl From<S3ErrorCode> for S3Error { } } impl From<Infallible> for S3Error { fn from(value: Infallible) -> Self { match value {} } } impl fmt::Display for S3Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut d = f.debug_struct("S3Error"); d.field("code", &self.code); if let Some(ref message) = self.message { d.field("code", &self.0.code); if let Some(ref message) = self.0.message { d.field("message", &message); } if let Some(ref source) = self.source { if let Some(ref request_id) = self.0.request_id { d.field("request_id", &request_id); } if let Some(ref status_code) = self.0.status_code { d.field("status_code", &status_code); } if let Some(ref source) = self.0.source { d.field("source", &source); } d.finish_non_exhaustive() Loading Loading @@ -163,14 +184,10 @@ macro_rules! s3_error { }; } #[derive(Debug, thiserror::Error)] #[error("Unknown S3 Error Code")] pub struct ParseS3ErrorCodeError(()); impl FromStr for S3ErrorCode { type Err = ParseS3ErrorCodeError; type Err = Infallible; fn from_str(s: &str) -> Result<Self, Self::Err> { Self::from_bytes(s.as_bytes()).ok_or(ParseS3ErrorCodeError(())) Ok(Self::from_bytes(s.as_bytes()).unwrap()) } } crates/s3s/src/ops/mod.rs +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ pub trait Operation: Send + Sync + 'static { fn serialize_error(x: S3Error) -> S3Result<Response> { let mut res = Response::default(); *res.status_mut() = x.code().status_code().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR); *res.status_mut() = x.status_code().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR); http::set_xml_body(&mut res, &x)?; Ok(res) } Loading Loading
codegen/src/error.rs +8 −5 Original line number Diff line number Diff line Loading @@ -114,7 +114,7 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { g.ln("use hyper::StatusCode;"); g.lf(); g.ln("#[derive(Debug, Clone, Copy, PartialEq, Eq)]"); g.ln("#[derive(Debug, Clone, PartialEq, Eq)]"); g.ln("#[non_exhaustive]"); g.ln("pub enum S3ErrorCode {"); for err in errors.values() { Loading Loading @@ -149,6 +149,7 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { g.ln(f!("{},", err.code)); g.lf(); } g.ln("Unknown(Box<str>),"); g.ln("}"); g.lf(); Loading @@ -156,12 +157,13 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { { g.ln("#[must_use]"); g.ln("pub const fn as_str(&self) -> &'static str {"); g.ln("pub fn as_str(&self) -> &str {"); g.ln("match self {"); for err in errors.values() { g.ln(f!("Self::{} => \"{}\",", err.code, err.code)); } g.ln("Self::Unknown(s) => s,"); g.ln("}"); g.ln("}"); Loading @@ -170,13 +172,13 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { { g.ln("#[must_use]"); g.ln("pub const fn from_bytes(s: &[u8]) -> Option<Self> {"); g.ln("pub fn from_bytes(s: &[u8]) -> Option<Self> {"); g.ln("match s {"); for err in errors.values() { g.ln(f!("b\"{}\" => Some(Self::{}),", err.code, err.code)); } g.ln("_ => None"); g.ln("_ => std::str::from_utf8(s).ok().map(|s| Self::Unknown(s.into()))"); g.ln("}"); g.ln("}"); Loading @@ -185,7 +187,7 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { { g.ln("#[must_use]"); g.ln("pub const fn status_code(self) -> Option<StatusCode> {"); g.ln("pub fn status_code(&self) -> Option<StatusCode> {"); g.ln("match self {"); for err in errors.values() { Loading Loading @@ -218,6 +220,7 @@ pub fn codegen(model: &smithy::Model, g: &mut Codegen) { } g.ln(f!("Self::{} => None,", err.code)); } g.ln("Self::Unknown(_) => None,"); g.ln("}"); g.ln("}"); Loading
crates/s3s/src/error/generated.rs +9 −5 Original line number Diff line number Diff line use hyper::StatusCode; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum S3ErrorCode { /// Access Denied Loading Loading @@ -485,11 +485,13 @@ pub enum S3ErrorCode { /// HTTP Status Code: 400 Bad Request /// UserKeyMustBeSpecified, Unknown(Box<str>), } impl S3ErrorCode { #[must_use] pub const fn as_str(&self) -> &'static str { pub fn as_str(&self) -> &str { match self { Self::AccessDenied => "AccessDenied ", Self::AccountProblem => "AccountProblem", Loading Loading @@ -571,11 +573,12 @@ impl S3ErrorCode { Self::UnexpectedContent => "UnexpectedContent", Self::UnresolvableGrantByEmailAddress => "UnresolvableGrantByEmailAddress", Self::UserKeyMustBeSpecified => "UserKeyMustBeSpecified", Self::Unknown(s) => s, } } #[must_use] pub const fn from_bytes(s: &[u8]) -> Option<Self> { pub fn from_bytes(s: &[u8]) -> Option<Self> { match s { b"AccessDenied " => Some(Self::AccessDenied), b"AccountProblem" => Some(Self::AccountProblem), Loading Loading @@ -657,12 +660,12 @@ impl S3ErrorCode { b"UnexpectedContent" => Some(Self::UnexpectedContent), b"UnresolvableGrantByEmailAddress" => Some(Self::UnresolvableGrantByEmailAddress), b"UserKeyMustBeSpecified" => Some(Self::UserKeyMustBeSpecified), _ => None, _ => std::str::from_utf8(s).ok().map(|s| Self::Unknown(s.into())), } } #[must_use] pub const fn status_code(self) -> Option<StatusCode> { pub fn status_code(&self) -> Option<StatusCode> { match self { Self::AccessDenied => Some(StatusCode::FORBIDDEN), Self::AccountProblem => Some(StatusCode::FORBIDDEN), Loading Loading @@ -744,6 +747,7 @@ impl S3ErrorCode { Self::UnexpectedContent => Some(StatusCode::BAD_REQUEST), Self::UnresolvableGrantByEmailAddress => Some(StatusCode::BAD_REQUEST), Self::UserKeyMustBeSpecified => Some(StatusCode::BAD_REQUEST), Self::Unknown(_) => None, } } }
crates/s3s/src/error/mod.rs +60 −43 Original line number Diff line number Diff line Loading @@ -4,89 +4,98 @@ pub use self::generated::*; use crate::xml; use std::borrow::Cow; use std::convert::Infallible; use std::fmt; use std::io::Write; use std::str::FromStr; use hyper::StatusCode; pub type S3Result<T = (), E = S3Error> = std::result::Result<T, E>; #[derive(Debug, thiserror::Error)] pub struct S3Error { pub struct S3Error(Box<Inner>); #[derive(Debug)] struct Inner { code: S3ErrorCode, message: Option<Cow<'static, str>>, resource: Option<String>, // resource: Option<String>, request_id: Option<String>, status_code: Option<StatusCode>, source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>, } impl S3Error { #[must_use] pub fn new(code: S3ErrorCode) -> Self { Self { Self(Box::new(Inner { code, message: None, resource: None, // resource: None, request_id: None, status_code: None, source: None, } })) } #[must_use] pub fn with_message(code: S3ErrorCode, msg: impl Into<Cow<'static, str>>) -> Self { Self { code, message: Some(msg.into()), resource: None, request_id: None, source: None, } let mut this = Self::new(code); this.0.message = Some(msg.into()); this } #[must_use] pub fn with_source(code: S3ErrorCode, source: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self { Self { code, message: None, resource: None, request_id: None, source: Some(source), } let mut this = Self::new(code); this.0.source = Some(source); this } pub fn set_code(&mut self, val: S3ErrorCode) { self.code = val; self.0.code = val; } pub fn set_message(&mut self, val: impl Into<Cow<'static, str>>) { self.message = Some(val.into()); self.0.message = Some(val.into()); } pub fn set_request_id(&mut self, val: impl Into<String>) { self.request_id = Some(val.into()); self.0.request_id = Some(val.into()); } pub fn set_source(&mut self, val: Box<dyn std::error::Error + Send + Sync + 'static>) { self.source = Some(val); self.0.source = Some(val); } pub fn set_status_code(&mut self, val: StatusCode) { self.0.status_code = Some(val); } #[must_use] pub fn code(&self) -> S3ErrorCode { self.code pub fn code(&self) -> &S3ErrorCode { &self.0.code } #[must_use] pub fn message(&self) -> Option<&str> { self.message.as_deref() self.0.message.as_deref() } #[must_use] pub fn request_id(&self) -> Option<&str> { self.request_id.as_deref() self.0.request_id.as_deref() } #[must_use] pub fn source(&self) -> Option<&(dyn std::error::Error + Send + Sync + 'static)> { self.source.as_deref() self.0.source.as_deref() } #[must_use] pub fn status_code(&self) -> Option<StatusCode> { self.0.status_code.or_else(|| self.0.code.status_code()) } #[must_use] Loading @@ -106,14 +115,14 @@ impl xml::Serialize for S3Error { impl xml::SerializeContent for S3Error { fn serialize_content<W: Write>(&self, s: &mut xml::Serializer<W>) -> xml::SerResult { s.content("Code", self.code.as_str())?; if let Some(val) = self.message.as_deref() { s.content("Code", self.0.code.as_str())?; if let Some(val) = self.0.message.as_deref() { s.content("Message", val)?; } if let Some(val) = self.resource.as_deref() { s.content("Resource", val)?; } if let Some(val) = self.request_id.as_deref() { // if let Some(val) = self.0.resource.as_deref() { // s.content("Resource", val)?; // } if let Some(val) = self.0.request_id.as_deref() { s.content("RequestId", val)?; } Ok(()) Loading @@ -126,14 +135,26 @@ impl From<S3ErrorCode> for S3Error { } } impl From<Infallible> for S3Error { fn from(value: Infallible) -> Self { match value {} } } impl fmt::Display for S3Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut d = f.debug_struct("S3Error"); d.field("code", &self.code); if let Some(ref message) = self.message { d.field("code", &self.0.code); if let Some(ref message) = self.0.message { d.field("message", &message); } if let Some(ref source) = self.source { if let Some(ref request_id) = self.0.request_id { d.field("request_id", &request_id); } if let Some(ref status_code) = self.0.status_code { d.field("status_code", &status_code); } if let Some(ref source) = self.0.source { d.field("source", &source); } d.finish_non_exhaustive() Loading Loading @@ -163,14 +184,10 @@ macro_rules! s3_error { }; } #[derive(Debug, thiserror::Error)] #[error("Unknown S3 Error Code")] pub struct ParseS3ErrorCodeError(()); impl FromStr for S3ErrorCode { type Err = ParseS3ErrorCodeError; type Err = Infallible; fn from_str(s: &str) -> Result<Self, Self::Err> { Self::from_bytes(s.as_bytes()).ok_or(ParseS3ErrorCodeError(())) Ok(Self::from_bytes(s.as_bytes()).unwrap()) } }
crates/s3s/src/ops/mod.rs +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ pub trait Operation: Send + Sync + 'static { fn serialize_error(x: S3Error) -> S3Result<Response> { let mut res = Response::default(); *res.status_mut() = x.code().status_code().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR); *res.status_mut() = x.status_code().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR); http::set_xml_body(&mut res, &x)?; Ok(res) } Loading