captcha-sdk 0.0.1

Unified server-side CAPTCHA verification for Rust
Documentation
use std::fmt;

use serde::{Deserialize, Serialize};
use thiserror::Error;

use crate::ProviderId;

/// Broad category for failures that prevent a verification result.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum VerificationErrorKind {
    /// The adapter was configured incorrectly.
    Configuration,
    /// The provider could not be reached.
    Transport,
    /// The provider did not answer within the configured deadline.
    Timeout,
    /// The provider returned an unreadable or unsupported response.
    InvalidResponse,
    /// The provider adapter has not been implemented yet.
    NotImplemented,
}

impl fmt::Display for VerificationErrorKind {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        let value = match self {
            Self::Configuration => "configuration",
            Self::Transport => "transport",
            Self::Timeout => "timeout",
            Self::InvalidResponse => "invalid_response",
            Self::NotImplemented => "not_implemented",
        };
        formatter.write_str(value)
    }
}

/// Error raised when no normalized verification result can be produced.
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[error("{provider} verification failed ({kind}): {message}")]
pub struct VerificationError {
    /// Provider involved in the failed operation.
    pub provider: ProviderId,
    /// Machine-readable failure category.
    pub kind: VerificationErrorKind,
    /// Human-readable context that must not include secrets or tokens.
    pub message: String,
}

impl VerificationError {
    /// Creates a verification error.
    pub fn new(
        provider: ProviderId,
        kind: VerificationErrorKind,
        message: impl Into<String>,
    ) -> Self {
        Self {
            provider,
            kind,
            message: message.into(),
        }
    }
}