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
21impl core::error::Error for Error {}
22
23impl fmt::Debug for Error {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        write!(f, "application::Error({})", self.0.as_u64())
26    }
27}
28
29impl fmt::Display for Error {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        write!(f, "QUIC application error code: {}", self.0.as_u64())
32    }
33}
34
35impl Error {
36    /// An error code that can be used when the application cannot provide
37    /// a more meaningful code.
38    pub const UNKNOWN: Self = Self(VarInt::from_u8(0));
39
40    /// Creates an `ApplicationErrorCode` from an unsigned integer.
41    ///
42    /// This will return the error code if the given value is inside the valid
43    /// range for error codes and return `Err` otherwise.
44    pub fn new(value: u64) -> Result<Self, VarIntError> {
45        Ok(Self(VarInt::new(value)?))
46    }
47}
48
49impl ops::Deref for Error {
50    type Target = u64;
51
52    fn deref(&self) -> &Self::Target {
53        self.0.deref()
54    }
55}
56
57impl TryInto for Error {
58    fn application_error(&self) -> Option<Error> {
59        Some(*self)
60    }
61}
62
63impl From<VarInt> for Error {
64    fn from(value: VarInt) -> Self {
65        Self(value)
66    }
67}
68
69impl From<Error> for VarInt {
70    fn from(e: Error) -> Self {
71        e.0
72    }
73}
74
75impl From<Error> for u64 {
76    fn from(e: Error) -> Self {
77        e.0.as_u64()
78    }
79}
80
81impl From<Error> for ConnectionClose<'_> {
82    fn from(error: Error) -> Self {
83        ConnectionClose {
84            error_code: error.0,
85            frame_type: None,
86            reason: None,
87        }
88    }
89}
90
91macro_rules! convert {
92    ($ty:ident) => {
93        impl From<$ty> for Error {
94            fn from(value: $ty) -> Self {
95                Self(VarInt::from(value))
96            }
97        }
98    };
99}
100
101convert!(u8);
102convert!(u16);
103convert!(u32);
104
105impl TryFrom<u64> for Error {
106    type Error = VarIntError;
107
108    fn try_from(value: u64) -> Result<Self, Self::Error> {
109        Ok(VarInt::try_from(value)?.into())
110    }
111}
112
113/// Conversion trait for errors that have an associated [`Error`]
114pub trait TryInto {
115    /// Returns the associated [`Error`], if any
116    fn application_error(&self) -> Option<Error>;
117}