fss_rs/group/
int.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2023 Yulong Ming (myl7)
3
4//! Integers as a group.
5//!
6//! - Associative operation: Integer wrapping addition, `$(a + b) \mod 2^N$`.
7//! - Identity element: 0.
8//! - Inverse element: `-x`.
9//!
10//! # Security
11//!
12//! Such a group whose cardinality is not a prime number cannot provide the attribute that: if `a` and `b` are individually indistinguishable with random elements, `a * b` (integer multiplication) is still that.
13//! If you need this attribute (e.g., for some verification), use [`crate::group::int_prime`] instead.
14
15use std::mem::size_of;
16use std::ops::{Add, AddAssign, Neg};
17
18use super::Group;
19
20macro_rules! decl_int_group {
21    ($t:ty, $t_impl:ident) => {
22        /// See [`self`].
23        #[derive(Debug, Clone, PartialEq, Eq)]
24        pub struct $t_impl(pub $t);
25
26        impl Add for $t_impl {
27            type Output = Self;
28
29            fn add(self, rhs: Self) -> Self::Output {
30                $t_impl(self.0.wrapping_add(rhs.0))
31            }
32        }
33
34        impl AddAssign for $t_impl {
35            fn add_assign(&mut self, rhs: Self) {
36                self.0 = self.0.wrapping_add(rhs.0);
37            }
38        }
39
40        impl Neg for $t_impl {
41            type Output = Self;
42
43            fn neg(self) -> Self::Output {
44                $t_impl(self.0.wrapping_neg())
45            }
46        }
47
48        impl<const BLEN: usize> Group<BLEN> for $t_impl {
49            fn zero() -> Self {
50                $t_impl(0)
51            }
52        }
53
54        impl<const BLEN: usize> From<[u8; BLEN]> for $t_impl {
55            fn from(value: [u8; BLEN]) -> Self {
56                if cfg!(not(feature = "int-be")) {
57                    $t_impl(<$t>::from_le_bytes(
58                        (&value[..size_of::<$t>()]).clone().try_into().unwrap(),
59                    ))
60                } else {
61                    $t_impl(<$t>::from_be_bytes(
62                        (&value[..size_of::<$t>()]).clone().try_into().unwrap(),
63                    ))
64                }
65            }
66        }
67
68        impl From<$t> for $t_impl {
69            fn from(value: $t) -> Self {
70                $t_impl(value)
71            }
72        }
73
74        impl<const BLEN: usize> From<$t_impl> for [u8; BLEN] {
75            fn from(value: $t_impl) -> Self {
76                let mut bs = [0; BLEN];
77                if cfg!(not(feature = "int-be")) {
78                    bs[..size_of::<$t>()].copy_from_slice(&value.0.to_le_bytes());
79                } else {
80                    bs[..size_of::<$t>()].copy_from_slice(&value.0.to_be_bytes());
81                }
82                bs
83            }
84        }
85
86        impl From<$t_impl> for $t {
87            fn from(value: $t_impl) -> Self {
88                value.0
89            }
90        }
91    };
92}
93
94decl_int_group!(u8, U8Group);
95decl_int_group!(u16, U16Group);
96decl_int_group!(u32, U32Group);
97decl_int_group!(u64, U64Group);
98decl_int_group!(u128, U128Group);
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103    use crate::test_group_axioms;
104
105    test_group_axioms!(test_u8_group_axioms, U8Group, 1);
106    test_group_axioms!(test_u16_group_axioms, U16Group, 2);
107    test_group_axioms!(test_u32_group_axioms, U32Group, 4);
108    test_group_axioms!(test_u64_group_axioms, U64Group, 8);
109    test_group_axioms!(test_u128_group_axioms, U128Group, 16);
110}