s2n_quic_core/application/
error.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Defines QUIC Application Error Codes
5
6use crate::{
7    frame::ConnectionClose,
8    varint::{VarInt, VarIntError},
9};
10use core::{fmt, ops};
11
12//= https://www.rfc-editor.org/rfc/rfc9000#section-20.2
13//# The management of application error codes is left to application
14//# protocols.
15
16/// Application Error Codes are 62-bit unsigned integer values which
17/// may be used by applications to exchange errors.
18#[derive(Copy, Clone, Eq, PartialEq)]
19pub struct Error(VarInt);
20
21#[cfg(feature = "std")]
22impl std::error::Error for Error {}
23
24impl fmt::Debug for Error {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        write!(f, "application::Error({})", self.0.as_u64())
27    }
28}
29
30impl fmt::Display for Error {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        write!(f, "QUIC application error code: {}", self.0.as_u64())
33    }
34}
35
36impl Error {
37    /// An error code that can be used when the application cannot provide
38    /// a more meaningful code.
39    pub const UNKNOWN: Self = Self(VarInt::from_u8(0));
40
41    /// Creates an `ApplicationErrorCode` from an unsigned integer.
42    ///
43    /// This will return the error code if the given value is inside the valid
44    /// range for error codes and return `Err` otherwise.
45    pub fn new(value: u64) -> Result<Self, VarIntError> {
46        Ok(Self(VarInt::new(value)?))
47    }
48}
49
50impl ops::Deref for Error {
51    type Target = u64;
52
53    fn deref(&self) -> &Self::Target {
54        self.0.deref()
55    }
56}
57
58impl TryInto for Error {
59    fn application_error(&self) -> Option<Error> {
60        Some(*self)
61    }
62}
63
64impl From<VarInt> for Error {
65    fn from(value: VarInt) -> Self {
66        Self(value)
67    }
68}
69
70impl From<Error> for VarInt {
71    fn from(e: Error) -> Self {
72        e.0
73    }
74}
75
76impl From<Error> for u64 {
77    fn from(e: Error) -> Self {
78        e.0.as_u64()
79    }
80}
81
82impl From<Error> for ConnectionClose<'_> {
83    fn from(error: Error) -> Self {
84        ConnectionClose {
85            error_code: error.0,
86            frame_type: None,
87            reason: None,
88        }
89    }
90}
91
92macro_rules! convert {
93    ($ty:ident) => {
94        impl From<$ty> for Error {
95            fn from(value: $ty) -> Self {
96                Self(VarInt::from(value))
97            }
98        }
99    };
100}
101
102convert!(u8);
103convert!(u16);
104convert!(u32);
105
106impl TryFrom<u64> for Error {
107    type Error = VarIntError;
108
109    fn try_from(value: u64) -> Result<Self, Self::Error> {
110        Ok(VarInt::try_from(value)?.into())
111    }
112}
113
114/// Conversion trait for errors that have an associated [`Error`]
115pub trait TryInto {
116    /// Returns the associated [`Error`], if any
117    fn application_error(&self) -> Option<Error>;
118}