Unverified Commit b4ea0218 authored by Nugine's avatar Nugine
Browse files

codegen: error: unknown

parent e2f003cf
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -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() {
@@ -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();

@@ -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("}");
@@ -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("}");
@@ -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() {
@@ -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("}");
+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
@@ -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",
@@ -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),
@@ -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),
@@ -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,
        }
    }
}
+60 −43
Original line number Diff line number Diff line
@@ -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]
@@ -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(())
@@ -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()
@@ -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())
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -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)
}