use super::passkey_label::{PasskeyLabelError, normalize_passkey_label};
pub const MAX_SESSION_USER_AGENT_BYTES: usize = 8192;
pub const MAX_PASSKEY_CREDENTIAL_ID_BYTES: usize = 1024;
pub const HELD_NAME_REQUESTED: &str = "HELD_NAME_REQUESTED";
pub const HELD_NAME_REQUEST_LAPSED: &str = "HELD_NAME_REQUEST_LAPSED";
#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
pub enum AccountMetadataError {
#[error("AAGUID must be absent or exactly 16 bytes")]
Aaguid,
#[error("passkey credential ID must be absent or 1..1024 bytes")]
CredentialId,
#[error("user agent exceeds 8192 UTF-8 bytes")]
UserAgentTooLong,
#[error("user agent contains a control character")]
UserAgentControl,
}
pub fn normalize_display_name(value: &str) -> Result<String, PasskeyLabelError> {
normalize_passkey_label(value)
}
pub fn normalize_advisory_label(value: &str) -> Result<String, PasskeyLabelError> {
normalize_passkey_label(value)
}
pub fn validate_aaguid(value: Option<&[u8]>) -> Result<(), AccountMetadataError> {
if value.is_some_and(|bytes| bytes.len() != 16) {
return Err(AccountMetadataError::Aaguid);
}
Ok(())
}
pub fn validate_passkey_credential_id(value: Option<&[u8]>) -> Result<(), AccountMetadataError> {
if value.is_some_and(|bytes| bytes.is_empty() || bytes.len() > MAX_PASSKEY_CREDENTIAL_ID_BYTES)
{
return Err(AccountMetadataError::CredentialId);
}
Ok(())
}
pub fn validate_session_user_agent(value: &str) -> Result<(), AccountMetadataError> {
if value.len() > MAX_SESSION_USER_AGENT_BYTES {
return Err(AccountMetadataError::UserAgentTooLong);
}
if value.chars().any(char::is_control) {
return Err(AccountMetadataError::UserAgentControl);
}
Ok(())
}