pkce_std/
count.rs

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