1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
use once_cell::sync::Lazy;
use std::sync::Mutex;
static GLOBAL_CONFIG: Lazy<Mutex<Option<Config>>> = Lazy::new(|| Mutex::new(None));
/// Configuring the cryptid library.
#[derive(Clone)]
pub struct Config<'a> {
pub(crate) hmac_length: u8,
pub(crate) key: &'a [u8],
pub(crate) zero_pad_length: u8,
}
#[derive(Debug)]
pub enum ConfigError {
InvalidMacLength,
InvalidVersion,
InvalidZeroPadLength,
}
impl<'a> Config<'a> {
/// Creates a new configuration with the given master `key` and other settings in
/// default values.
/// - `mac_length` defaults to 4, which is large enough to make guessing impractical
/// but still keeps the strings relatively short. High security applications may want
/// to use a higher value.
/// - `zero_pad_length` defaults to 4, which is large enough for most applications
/// to never see encoded strings increase in size, while still keeping the strings
/// relatively short.
pub fn new(key: &'a [u8]) -> Self {
Config {
hmac_length: 4,
key,
zero_pad_length: 4,
}
}
/// Sets the number of bytes in the HMAC.
/// The value must be between 0 and 8.
pub fn hmac_length(mut self, hmac_length: u8) -> Result<Self, ConfigError> {
if hmac_length > 8 {
Err(ConfigError::InvalidMacLength)
} else {
self.hmac_length = hmac_length;
Ok(self)
}
}
/// Sets the number of bytes to zero-pad numbers before encoding.
/// The value must be between 0 and 8.
pub fn zero_pad_length(mut self, zero_pad_length: u8) -> Result<Self, ConfigError> {
if zero_pad_length > 8 {
Err(ConfigError::InvalidZeroPadLength)
} else {
self.zero_pad_length = zero_pad_length;
Ok(self)
}
}
/// Sets the global configuration. This should be called before the `Field` type methods
/// are called.
pub fn set_global(config: Config<'static>) {
let mut global_config = GLOBAL_CONFIG.lock().unwrap();
*global_config = Some(config);
}
/// Accesses the global configuration, if set.
pub fn global() -> Option<Config<'static>> {
GLOBAL_CONFIG.lock().unwrap().clone()
}
}