rscrypto 0.1.1

Pure Rust cryptography, hardware-accelerated: BLAKE3, SHA-2/3, AES-GCM, ChaCha20-Poly1305, Ed25519, X25519, HMAC, HKDF, Argon2, CRC. no_std, WASM, ten CPU architectures.
Documentation
//! CRC-24 runtime configuration.
//!
//! This module handles force mode selection for CRC-24. The dispatch module
//! handles optimal kernel selection automatically; this module only provides
//! the ability to force specific backends for testing/debugging.

use crate::platform::Caps;

/// Requested backend override for CRC-24.
///
/// Requests are clamped to detected CPU capabilities before use.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum Crc24Force {
  /// Use the default auto selector.
  #[default]
  Auto,
  /// Force the bitwise reference implementation.
  ///
  /// This is the correctness oracle used to validate optimized kernels.
  Reference,
  /// Force the portable tier (slice-by-8).
  Portable,
  /// Force the carryless-multiply tier (PCLMULQDQ/PMULL) if supported.
  Clmul,
}

impl Crc24Force {
  /// Return the stable selector name used by debug and configuration surfaces.
  #[must_use]
  pub const fn as_str(self) -> &'static str {
    match self {
      Self::Auto => "auto",
      Self::Reference => "reference",
      Self::Portable => "portable",
      Self::Clmul => "clmul",
    }
  }
}

#[cfg(feature = "std")]
fn parse_force_env() -> Crc24Force {
  let Ok(value) = std::env::var("RSCRYPTO_CRC24_FORCE") else {
    return Crc24Force::Auto;
  };
  let value = value.trim();
  if value.is_empty() {
    return Crc24Force::Auto;
  }

  if value.eq_ignore_ascii_case("auto") {
    return Crc24Force::Auto;
  }
  if value.eq_ignore_ascii_case("reference") || value.eq_ignore_ascii_case("bitwise") {
    return Crc24Force::Reference;
  }
  if value.eq_ignore_ascii_case("portable")
    || value.eq_ignore_ascii_case("scalar")
    || value.eq_ignore_ascii_case("table")
  {
    return Crc24Force::Portable;
  }
  if value.eq_ignore_ascii_case("clmul")
    || value.eq_ignore_ascii_case("pclmul")
    || value.eq_ignore_ascii_case("pmull")
    || value.eq_ignore_ascii_case("vpmsum")
    || value.eq_ignore_ascii_case("vgfm")
    || value.eq_ignore_ascii_case("zbc")
    || value.eq_ignore_ascii_case("zvbc")
  {
    return Crc24Force::Clmul;
  }
  if value.eq_ignore_ascii_case("slice8") {
    return Crc24Force::Portable;
  }
  if value.eq_ignore_ascii_case("slice4") {
    return Crc24Force::Portable;
  }

  Crc24Force::Auto
}

#[inline]
#[must_use]
#[allow(unused_variables)]
fn clamp_force_to_caps(requested: Crc24Force, caps: Caps) -> Crc24Force {
  match requested {
    Crc24Force::Auto | Crc24Force::Reference | Crc24Force::Portable => requested,
    Crc24Force::Clmul => {
      #[cfg(target_arch = "x86_64")]
      {
        if caps.has(crate::platform::caps::x86::PCLMUL_READY) {
          return Crc24Force::Clmul;
        }
      }
      #[cfg(target_arch = "aarch64")]
      {
        if caps.has(crate::platform::caps::aarch64::PMULL_READY) {
          return Crc24Force::Clmul;
        }
      }
      #[cfg(target_arch = "powerpc64")]
      {
        if caps.has(crate::platform::caps::power::VPMSUM_READY) {
          return Crc24Force::Clmul;
        }
      }
      #[cfg(target_arch = "s390x")]
      {
        if caps.has(crate::platform::caps::s390x::VECTOR) {
          return Crc24Force::Clmul;
        }
      }
      #[cfg(target_arch = "riscv64")]
      {
        use crate::platform::caps::riscv;
        if caps.has(riscv::ZBC) || caps.has(riscv::ZVBC) {
          return Crc24Force::Clmul;
        }
      }
      Crc24Force::Auto
    }
  }
}

/// Resolved CRC-24 force configuration.
///
/// `requested_force` is the user or environment request. `effective_force` is
/// the same request clamped to the current platform capabilities.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Crc24Config {
  /// Requested force mode (env/programmatic).
  pub requested_force: Crc24Force,
  /// Force mode clamped to detected CPU capabilities.
  pub effective_force: Crc24Force,
}

/// Compute the effective CRC-24 config for the current process.
#[inline]
#[must_use]
fn config(caps: Caps) -> Crc24Config {
  #[cfg(feature = "std")]
  let requested_force = parse_force_env();
  #[cfg(not(feature = "std"))]
  let requested_force = Crc24Force::Auto;

  let effective_force = clamp_force_to_caps(requested_force, caps);

  Crc24Config {
    requested_force,
    effective_force,
  }
}

/// Return the cached process-wide CRC-24 configuration.
///
/// Under `std`, this reflects `RSCRYPTO_CRC24_FORCE` clamped to the detected
/// platform capabilities.
#[inline]
#[must_use]
pub fn get() -> Crc24Config {
  #[cfg(feature = "std")]
  {
    use std::sync::OnceLock;
    static CACHED: OnceLock<Crc24Config> = OnceLock::new();
    *CACHED.get_or_init(|| config(crate::platform::caps()))
  }

  #[cfg(not(feature = "std"))]
  {
    config(crate::platform::caps())
  }
}