#![allow(missing_docs)]
use uor_foundation::enforcement::{GroundedShape, ShapeViolation};
use uor_foundation::pipeline::{
AxisExtension, ConstrainedTypeShape, ConstraintRef, IntoBindingValue,
};
use uor_foundation_sdk::axis;
use crate::{check_output, split_pair};
axis! {
pub trait RingAxis: AxisExtension {
const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/RingAxis";
const MAX_OUTPUT_BYTES: usize = 32;
fn add(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation>;
fn mul(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation>;
}
}
pub const MAX_GF2_BYTES: usize = 128;
fn width_violation() -> ShapeViolation {
ShapeViolation {
shape_iri: "https://uor.foundation/axis/RingAxis",
constraint_iri: "https://uor.foundation/axis/RingAxis/widthInRange",
property_iri: "https://uor.foundation/axis/operandByteWidth",
expected_range: "https://uor.foundation/axis/RingAxis/MaxGf2Bytes",
min_count: 1,
#[allow(clippy::cast_possible_truncation)]
max_count: MAX_GF2_BYTES as u32,
kind: uor_foundation::ViolationKind::ValueCheck,
}
}
#[derive(Debug, Clone, Copy)]
pub struct Gf2NumericAxisN<const BYTES: usize>;
impl<const BYTES: usize> Default for Gf2NumericAxisN<BYTES> {
fn default() -> Self {
Self
}
}
impl<const BYTES: usize> RingAxis for Gf2NumericAxisN<BYTES> {
const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/RingAxis/Gf2";
const MAX_OUTPUT_BYTES: usize = BYTES;
fn add(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
if BYTES == 0 || BYTES > MAX_GF2_BYTES {
return Err(width_violation());
}
let (a, b) = split_pair(input, BYTES)?;
check_output(out, BYTES)?;
for i in 0..BYTES {
out[i] = a[i] ^ b[i];
}
Ok(BYTES)
}
fn mul(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
if BYTES == 0 || BYTES > MAX_GF2_BYTES {
return Err(width_violation());
}
let (a, b) = split_pair(input, BYTES)?;
check_output(out, BYTES)?;
for i in 0..BYTES {
out[i] = a[i] & b[i];
}
Ok(BYTES)
}
}
axis_extension_impl_for_ring_axis!(@generic Gf2NumericAxisN<BYTES>, [const BYTES: usize]);
pub type Gf2NumericAxis = Gf2NumericAxisN<32>;
pub type Gf2NumericAxis128 = Gf2NumericAxisN<16>;
pub type Gf2NumericAxis512 = Gf2NumericAxisN<64>;
#[derive(Debug, Clone, Copy)]
pub struct Gf2RingShape<const BYTES: usize>;
impl<const BYTES: usize> Default for Gf2RingShape<BYTES> {
fn default() -> Self {
Self
}
}
impl<const BYTES: usize> ConstrainedTypeShape for Gf2RingShape<BYTES> {
const IRI: &'static str = "https://uor.foundation/type/ConstrainedType";
const SITE_COUNT: usize = BYTES;
const CONSTRAINTS: &'static [ConstraintRef] = &[];
#[allow(clippy::cast_possible_truncation)]
const CYCLE_SIZE: u64 = 256u64.saturating_pow(BYTES as u32);
}
impl<const BYTES: usize> uor_foundation::pipeline::__sdk_seal::Sealed for Gf2RingShape<BYTES> {}
impl<const BYTES: usize> GroundedShape for Gf2RingShape<BYTES> {}
impl<const BYTES: usize> IntoBindingValue for Gf2RingShape<BYTES> {
const MAX_BYTES: usize = BYTES;
fn into_binding_bytes(&self, _out: &mut [u8]) -> Result<usize, ShapeViolation> {
Ok(0)
}
}