1#![allow(missing_docs)]
12
13use uor_foundation::enforcement::{GroundedShape, ShapeViolation};
14use uor_foundation::pipeline::{ConstrainedTypeShape, ConstraintRef, IntoBindingValue, TermValue};
15use uor_foundation_sdk::axis;
16
17use crate::{check_output, split_pair};
18
19axis! {
20 pub trait RingAxis: AxisExtension {
26 const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/RingAxis";
28 const MAX_OUTPUT_BYTES: usize = 32;
30 fn add(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation>;
36 fn mul(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation>;
42 }
43}
44
45fn width_violation() -> ShapeViolation {
51 ShapeViolation {
52 shape_iri: "https://uor.foundation/axis/RingAxis",
53 constraint_iri: "https://uor.foundation/axis/RingAxis/widthPositive",
54 property_iri: "https://uor.foundation/axis/operandByteWidth",
55 expected_range: "https://uor.foundation/axis/RingAxis/PositiveByteWidth",
56 min_count: 1,
57 max_count: u32::MAX,
58 kind: uor_foundation::ViolationKind::ValueCheck,
59 }
60}
61
62#[derive(Debug, Clone, Copy)]
68pub struct Gf2NumericAxisN<const BYTES: usize>;
69
70impl<const BYTES: usize> Default for Gf2NumericAxisN<BYTES> {
71 fn default() -> Self {
72 Self
73 }
74}
75
76impl<const BYTES: usize> RingAxis for Gf2NumericAxisN<BYTES> {
77 const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/RingAxis/Gf2";
78 const MAX_OUTPUT_BYTES: usize = BYTES;
79
80 fn add(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
81 if BYTES == 0 {
82 return Err(width_violation());
83 }
84 let (a, b) = split_pair(input, BYTES)?;
85 check_output(out, BYTES)?;
86 for i in 0..BYTES {
87 out[i] = a[i] ^ b[i];
88 }
89 Ok(BYTES)
90 }
91
92 fn mul(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
93 if BYTES == 0 {
94 return Err(width_violation());
95 }
96 let (a, b) = split_pair(input, BYTES)?;
97 check_output(out, BYTES)?;
98 for i in 0..BYTES {
99 out[i] = a[i] & b[i];
100 }
101 Ok(BYTES)
102 }
103}
104
105axis_extension_impl_for_ring_axis!(@generic Gf2NumericAxisN<BYTES>, [const BYTES: usize]);
107
108pub type Gf2NumericAxis = Gf2NumericAxisN<32>;
110pub type Gf2NumericAxis128 = Gf2NumericAxisN<16>;
112pub type Gf2NumericAxis512 = Gf2NumericAxisN<64>;
114
115#[derive(Debug, Clone, Copy)]
119pub struct Gf2RingShape<const BYTES: usize>;
120
121impl<const BYTES: usize> Default for Gf2RingShape<BYTES> {
122 fn default() -> Self {
123 Self
124 }
125}
126
127impl<const BYTES: usize> ConstrainedTypeShape for Gf2RingShape<BYTES> {
128 const IRI: &'static str = "https://uor.foundation/type/ConstrainedType";
129 const SITE_COUNT: usize = BYTES;
130 const CONSTRAINTS: &'static [ConstraintRef] = &[];
131 #[allow(clippy::cast_possible_truncation)]
132 const CYCLE_SIZE: u64 = 256u64.saturating_pow(BYTES as u32);
133}
134
135impl<const BYTES: usize> uor_foundation::pipeline::__sdk_seal::Sealed for Gf2RingShape<BYTES> {}
136impl<const BYTES: usize> GroundedShape for Gf2RingShape<BYTES> {}
137impl<'a, const BYTES: usize> IntoBindingValue<'a> for Gf2RingShape<BYTES> {
138 fn as_binding_value<const INLINE_BYTES: usize>(&self) -> TermValue<'a, INLINE_BYTES> {
139 TermValue::empty()
140 }
141}