aws_sdk_cloudfront_url_signer/
error.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6use std::borrow::Cow;
7use std::error::Error as StdError;
8use std::fmt;
9
10#[derive(Debug)]
11pub(crate) enum ErrorKind {
12    InvalidKey,
13    InvalidPolicy,
14    InvalidInput,
15    SigningFailure,
16}
17
18/// Error type for CloudFront signing operations
19#[derive(Debug)]
20pub struct SigningError {
21    kind: ErrorKind,
22    source: Option<Box<dyn StdError + Send + Sync>>,
23    message: Option<Cow<'static, str>>,
24}
25
26impl SigningError {
27    pub(crate) fn new(
28        kind: ErrorKind,
29        source: Option<Box<dyn StdError + Send + Sync>>,
30        message: Option<Cow<'static, str>>,
31    ) -> Self {
32        Self {
33            kind,
34            source,
35            message,
36        }
37    }
38
39    pub(crate) fn invalid_key(source: impl Into<Box<dyn StdError + Send + Sync>>) -> Self {
40        Self::new(ErrorKind::InvalidKey, Some(source.into()), None)
41    }
42
43    pub(crate) fn invalid_policy(message: impl Into<Cow<'static, str>>) -> Self {
44        Self::new(ErrorKind::InvalidPolicy, None, Some(message.into()))
45    }
46
47    pub(crate) fn invalid_input(message: impl Into<Cow<'static, str>>) -> Self {
48        Self::new(ErrorKind::InvalidInput, None, Some(message.into()))
49    }
50
51    pub(crate) fn signing_failure(source: impl Into<Box<dyn StdError + Send + Sync>>) -> Self {
52        Self::new(ErrorKind::SigningFailure, Some(source.into()), None)
53    }
54}
55
56impl fmt::Display for SigningError {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        match self.kind {
59            ErrorKind::InvalidKey => write!(f, "invalid private key"),
60            ErrorKind::InvalidPolicy => {
61                write!(f, "invalid policy")?;
62                if let Some(ref msg) = self.message {
63                    write!(f, ": {msg}")?;
64                }
65                Ok(())
66            }
67            ErrorKind::InvalidInput => {
68                write!(f, "invalid input")?;
69                if let Some(ref msg) = self.message {
70                    write!(f, ": {msg}")?;
71                }
72                Ok(())
73            }
74            ErrorKind::SigningFailure => write!(f, "signing operation failed"),
75        }
76    }
77}
78
79impl StdError for SigningError {
80    fn source(&self) -> Option<&(dyn StdError + 'static)> {
81        self.source.as_ref().map(|e| e.as_ref() as _)
82    }
83}
84
85impl From<ErrorKind> for SigningError {
86    fn from(kind: ErrorKind) -> Self {
87        Self::new(kind, None, None)
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_invalid_key_display() {
97        let err = SigningError::invalid_key("test error");
98        assert_eq!(err.to_string(), "invalid private key");
99        assert!(err.source().is_some());
100    }
101
102    #[test]
103    fn test_invalid_policy_display() {
104        let err = SigningError::invalid_policy("missing expires_at");
105        assert_eq!(err.to_string(), "invalid policy: missing expires_at");
106        assert!(err.source().is_none());
107    }
108
109    #[test]
110    fn test_invalid_input_display() {
111        let err = SigningError::invalid_input("empty URL");
112        assert_eq!(err.to_string(), "invalid input: empty URL");
113        assert!(err.source().is_none());
114    }
115
116    #[test]
117    fn test_signing_failure_display() {
118        let err = SigningError::signing_failure("RSA error");
119        assert_eq!(err.to_string(), "signing operation failed");
120        assert!(err.source().is_some());
121    }
122}