Skip to main content

ps_ecc/polynomial/implementations/
add.rs

1use std::{
2    borrow::Borrow,
3    ops::{Add, BitXor},
4};
5
6use crate::{error::PolynomialXorError, Polynomial};
7
8impl<B: Borrow<u8>, I: IntoIterator<Item = B>> Add<I> for Polynomial {
9    type Output = Result<Self, PolynomialXorError>;
10
11    /// Adds coefficients from an iterator to this polynomial.
12    ///
13    /// In GF(256), addition is XOR. This delegates to `BitXor`.
14    ///
15    /// # Errors
16    ///
17    /// Returns `TooManyCoefficients` if the iterator yields more than 255 elements.
18    fn add(self, rhs: I) -> Self::Output {
19        BitXor::bitxor(self, rhs)
20    }
21}
22
23impl<B: Borrow<u8>, I: IntoIterator<Item = B>> Add<I> for &Polynomial {
24    type Output = Result<Polynomial, PolynomialXorError>;
25
26    fn add(self, rhs: I) -> Self::Output {
27        BitXor::bitxor(*self, rhs)
28    }
29}
30
31#[cfg(test)]
32#[allow(clippy::expect_used)]
33mod tests {
34    use std::ops::Add;
35
36    use crate::{error::PolynomialXorError, Polynomial};
37
38    #[test]
39    fn add_two_polynomials() {
40        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
41        let b = Polynomial::try_from(&[4u8, 5, 6][..]).expect("valid polynomial");
42
43        let result = a.add(b).expect("polynomials are bounded");
44
45        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6]);
46    }
47
48    #[test]
49    fn add_different_degrees() {
50        let a = Polynomial::try_from(&[1u8, 2][..]).expect("valid polynomial");
51        let b = Polynomial::try_from(&[3u8, 4, 5, 6][..]).expect("valid polynomial");
52
53        let result = a.add(b).expect("polynomials are bounded");
54
55        assert_eq!(result.coefficients(), &[1 ^ 3, 2 ^ 4, 5, 6]);
56    }
57
58    #[test]
59    fn add_cancels_to_zero() {
60        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
61        let b = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
62
63        let result = a.add(b).expect("polynomials are bounded");
64
65        assert_eq!(result.degree(), 0);
66        assert_eq!(result.coefficients(), &[0]);
67    }
68
69    #[test]
70    fn add_with_references() {
71        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
72        let b = Polynomial::try_from(&[4u8, 5, 6][..]).expect("valid polynomial");
73
74        let result = (&a).add(&b).expect("polynomials are bounded");
75
76        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6]);
77    }
78
79    #[test]
80    fn add_slice_via_iter() {
81        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
82        let slice: &[u8] = &[4, 5, 6];
83
84        let result = a.add(slice.iter()).expect("valid slice");
85
86        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6]);
87    }
88
89    #[test]
90    fn add_slice_different_lengths() {
91        let a = Polynomial::try_from(&[1u8, 2][..]).expect("valid polynomial");
92        let slice: &[u8] = &[3, 4, 5, 6];
93
94        let result = a.add(slice.iter()).expect("valid slice");
95
96        assert_eq!(result.coefficients(), &[1 ^ 3, 2 ^ 4, 5, 6]);
97    }
98
99    #[test]
100    fn add_iterator() {
101        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
102        let iter = [4u8, 5, 6].into_iter();
103
104        let result = a.add(iter).expect("valid iterator");
105
106        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6]);
107    }
108
109    #[test]
110    fn add_vec() {
111        let a = Polynomial::try_from(&[1u8, 2, 3][..]).expect("valid polynomial");
112        let vec = vec![4u8, 5, 6, 7];
113
114        let result = a.add(vec).expect("valid vec");
115
116        assert_eq!(result.coefficients(), &[1 ^ 4, 2 ^ 5, 3 ^ 6, 7]);
117    }
118
119    #[test]
120    fn add_iterator_too_long_returns_error() {
121        let a = Polynomial::default();
122        let iter = std::iter::repeat_n(1u8, 256);
123
124        let result = a.add(iter);
125
126        assert_eq!(result, Err(PolynomialXorError::TooManyCoefficients));
127    }
128}