identity_jose/jws/
charset.rs

1// Copyright 2020-2023 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use core::str::from_utf8;
5
6use crate::error::Error;
7use crate::error::Result;
8
9/// The requirements towards the character set when encoding a JWS.
10///
11/// See the individual variants for more details.
12#[derive(Clone, Copy, Debug)]
13pub enum CharSet {
14  /// The ASCII space character and all printable ASCII characters other
15  /// than period ('.') (those characters in the ranges %x20-2D and %x2F-7E)
16  /// MAY be included in a non-detached payload using the JWS Compact
17  /// Serialization, provided that the application can transmit the
18  /// resulting JWS without modification.
19  Default,
20  /// If a JWS using the JWS Compact Serialization and a non-detached
21  /// payload is to be transmitted in a context that requires URL-safe
22  /// characters, then the application MUST ensure that the payload
23  /// contains only the URL-safe characters 'a'-'z', 'A'-'Z', '0'-'9',
24  /// dash ('-'), underscore ('_'), and tilde ('~').
25  UrlSafe,
26}
27
28impl CharSet {
29  /// Validate unencoded content for used with the compact serialization
30  /// format. The payload MUST NOT contain a period (`.`) and MAY be
31  /// required to only contain URL-safe characters.
32  ///
33  /// [More Info](https://tools.ietf.org/html/rfc7797#section-5.2)
34  pub fn validate<'data>(&self, data: &'data [u8]) -> Result<&'data str> {
35    let payload: &'data str = from_utf8(data).map_err(|_| Error::InvalidContent("invalid UTF-8"))?;
36
37    if payload.contains('.') {
38      return Err(Error::InvalidContent("invalid character `.`"));
39    }
40
41    if !self.__validate(payload) {
42      return Err(Error::InvalidContent("invalid character(s)"));
43    }
44
45    Ok(payload)
46  }
47
48  fn __validate(&self, data: &str) -> bool {
49    match self {
50      Self::Default => data.chars().all(|ch| matches!(ch, '\x20'..='\x2D' | '\x2F'..='\x7E')),
51      Self::UrlSafe => data
52        .chars()
53        .all(|ch| matches!(ch, 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' | '~')),
54    }
55  }
56}