pkce_std/
length.rs

1//! PKCE code verifier lengths.
2//!
3//! As per the [standard](https://datatracker.ietf.org/doc/html/rfc7636#section-4.1), the length
4//! of the code verifier must be at least `43` and at most `128`.
5//!
6//! This module provides the [`Length`] type, representing the actual length of the code verifier.
7//!
8//! The [`Length`] type internally stores [`usize`] values, which are guaranteed to be in the range
9//! from [`MIN`] to [`MAX`] inclusively, defaulting to [`DEFAULT`].
10//!
11//! ```
12//! use pkce_std::length::Length;
13//!
14//! let length = Length::new(128);
15//! ```
16
17use std::{fmt, num::ParseIntError, str::FromStr};
18
19use const_macros::{const_early, const_ok, const_try};
20
21#[cfg(feature = "diagnostics")]
22use miette::Diagnostic;
23
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
26
27use thiserror::Error;
28
29use crate::{count, encoding};
30
31/// The minimum length.
32pub const MIN: usize = encoding::length(count::MIN);
33
34/// The default length.
35pub const DEFAULT: usize = encoding::length(count::DEFAULT);
36
37/// The maximum length.
38pub const MAX: usize = encoding::length(count::MAX);
39
40/// Represents errors that can occur when constructing [`Length`] values.
41///
42/// This error is returned when the given value is less than [`MIN`] or greater than [`MAX`].
43#[derive(Debug, Error)]
44#[error("expected length in `[{MIN}, {MAX}]` range, got `{value}`")]
45#[cfg_attr(
46    feature = "diagnostics",
47    derive(Diagnostic),
48    diagnostic(
49        code(pkce_std::length),
50        help("make sure the length is at least `{MIN}` and at most `{MAX}`")
51    )
52)]
53pub struct Error {
54    /// The invalid value.
55    pub value: usize,
56}
57
58impl Error {
59    /// Constructs [`Self`].
60    pub const fn new(value: usize) -> Self {
61        Self { value }
62    }
63}
64
65/// Represents sources of errors that can occur when parsing [`Length`] values.
66#[derive(Debug, Error)]
67#[cfg_attr(feature = "diagnostics", derive(Diagnostic))]
68pub enum ParseError {
69    /// Invalid length error.
70    #[error("invalid length")]
71    #[cfg_attr(
72        feature = "diagnostics",
73        diagnostic(
74            code(pkce_std::length::parse),
75            help("make sure the length is in the valid range")
76        )
77    )]
78    Length(#[from] Error),
79    /// Integer parse error.
80    #[error("parse integer error")]
81    #[cfg_attr(
82        feature = "diagnostics",
83        diagnostic(code(pkce_std::length::parse::int), help("check the string"))
84    )]
85    Int(#[from] ParseIntError),
86}
87
88/// Represents lengths.
89///
90/// Refer to the [module] documentation for more information.
91///
92/// # Examples
93///
94/// ```
95/// use pkce_std::length::Length;
96///
97/// let length = Length::new(69).unwrap();
98///
99/// assert_eq!(length.get(), 69);
100/// ```
101///
102/// [module]: self
103#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
104pub struct Length {
105    value: usize,
106}
107
108impl TryFrom<usize> for Length {
109    type Error = Error;
110
111    fn try_from(value: usize) -> Result<Self, Self::Error> {
112        Self::new(value)
113    }
114}
115
116impl From<Length> for usize {
117    fn from(length: Length) -> Self {
118        length.get()
119    }
120}
121
122impl fmt::Display for Length {
123    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
124        self.get().fmt(formatter)
125    }
126}
127
128#[cfg(feature = "serde")]
129impl Serialize for Length {
130    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
131        self.get().serialize(serializer)
132    }
133}
134
135#[cfg(feature = "serde")]
136impl<'de> Deserialize<'de> for Length {
137    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
138        let value = usize::deserialize(deserializer)?;
139
140        Self::new(value).map_err(de::Error::custom)
141    }
142}
143
144impl Default for Length {
145    fn default() -> Self {
146        Self::DEFAULT
147    }
148}
149
150impl FromStr for Length {
151    type Err = ParseError;
152
153    fn from_str(string: &str) -> Result<Self, Self::Err> {
154        let value = string.parse()?;
155
156        let length = Self::new(value)?;
157
158        Ok(length)
159    }
160}
161
162impl Length {
163    /// Constructs [`Self`] if the provided value is in the valid range.
164    ///
165    /// # Errors
166    ///
167    /// See [`check`] for more information.
168    ///
169    /// [`check`]: Self::check
170    pub const fn new(value: usize) -> Result<Self, Error> {
171        const_try!(Self::check(value));
172
173        // SAFETY: `value` is in the valid range for `Self`
174        Ok(unsafe { Self::new_unchecked(value) })
175    }
176
177    /// Similar to [`new`], but the error is discarded.
178    ///
179    /// [`new`]: Self::new
180    pub const fn new_ok(value: usize) -> Option<Self> {
181        const_ok!(Self::new(value))
182    }
183
184    /// Checks whether the given value is in the valid range for [`Self`].
185    ///
186    /// # Errors
187    ///
188    /// [`struct@Error`] is returned if the value is less than [`MIN`] or greater than [`MAX`].
189    pub const fn check(value: usize) -> Result<(), Error> {
190        const_early!(value < MIN || value > MAX => Error::new(value));
191
192        Ok(())
193    }
194
195    /// Constructs [`Self`] without checking the value.
196    ///
197    /// # Safety
198    ///
199    /// The caller must ensure that the value is in the valid range for [`Self`].
200    pub const unsafe fn new_unchecked(value: usize) -> Self {
201        Self { value }
202    }
203
204    /// Consumes [`Self`] and returns the contained value.
205    pub const fn get(self) -> usize {
206        self.value
207    }
208
209    /// The minimum value of [`Self`].
210    pub const MIN: Self = Self::new_ok(MIN).unwrap();
211
212    /// The default value of [`Self`].
213    pub const DEFAULT: Self = Self::new_ok(DEFAULT).unwrap();
214
215    /// The maximum value of [`Self`].
216    pub const MAX: Self = Self::new_ok(MAX).unwrap();
217}