Skip to main content

ps_ecc/polynomial/methods/
from_slice.rs

1use crate::{Polynomial, PolynomialFromSliceError};
2
3impl Polynomial {
4    /// Creates a polynomial from a slice of coefficients.
5    ///
6    /// Coefficients are ordered from degree 0 (constant term) to the leading term.
7    ///
8    /// # Errors
9    ///
10    /// Returns [`PolynomialFromSliceError::TooLong`] if the slice exceeds 255 elements.
11    pub fn from_slice(coeffs: &[u8]) -> Result<Self, PolynomialFromSliceError> {
12        let size = coeffs.len();
13        let size_u8 = u8::try_from(size).map_err(|_| PolynomialFromSliceError::TooLong { size })?;
14        let degree = size_u8.saturating_sub(1);
15
16        let mut poly = Self::default();
17
18        poly.coefficients[..size].copy_from_slice(coeffs);
19        poly.degree = degree;
20        poly.trim_degree();
21
22        Ok(poly)
23    }
24}
25
26#[cfg(test)]
27#[allow(clippy::expect_used)]
28mod tests {
29    use crate::{Polynomial, PolynomialFromSliceError};
30
31    #[test]
32    fn empty_slice() {
33        let poly = Polynomial::from_slice(&[]).expect("empty slice should succeed");
34
35        assert_eq!(poly.degree(), 0);
36        assert_eq!(poly.coefficients(), &[0]);
37    }
38
39    #[test]
40    fn single_coefficient() {
41        let poly = Polynomial::from_slice(&[42]).expect("single coefficient should succeed");
42
43        assert_eq!(poly.degree(), 0);
44        assert_eq!(poly.coefficients(), &[42]);
45    }
46
47    #[test]
48    fn multiple_coefficients() {
49        let poly =
50            Polynomial::from_slice(&[1, 2, 3]).expect("multiple coefficients should succeed");
51
52        assert_eq!(poly.degree(), 2);
53        assert_eq!(poly.coefficients(), &[1, 2, 3]);
54    }
55
56    #[test]
57    fn trims_leading_zeros() {
58        let poly =
59            Polynomial::from_slice(&[1, 2, 0, 0]).expect("slice with leading zeros should succeed");
60
61        assert_eq!(poly.degree(), 1);
62        assert_eq!(poly.coefficients(), &[1, 2]);
63    }
64
65    #[test]
66    fn all_zeros() {
67        let poly = Polynomial::from_slice(&[0, 0, 0]).expect("all zeros should succeed");
68
69        assert_eq!(poly.degree(), 0);
70        assert_eq!(poly.coefficients(), &[0]);
71    }
72
73    #[test]
74    fn sparse_polynomial() {
75        let poly = Polynomial::from_slice(&[1, 0, 0, 5]).expect("sparse polynomial should succeed");
76
77        assert_eq!(poly.degree(), 3);
78        assert_eq!(poly.coefficients(), &[1, 0, 0, 5]);
79    }
80
81    #[test]
82    fn max_size() {
83        let coeffs = [1u8; 255];
84        let poly = Polynomial::from_slice(&coeffs).expect("max size should succeed");
85
86        assert_eq!(poly.degree(), 254);
87        assert_eq!(poly.coefficients().len(), 255);
88    }
89
90    #[test]
91    fn too_long() {
92        let coeffs = [1u8; 256];
93        let err = Polynomial::from_slice(&coeffs).expect_err("256 coefficients should fail");
94
95        assert!(matches!(
96            err,
97            PolynomialFromSliceError::TooLong { size: 256 }
98        ));
99    }
100
101    #[test]
102    fn roundtrip_with_coefficients() {
103        let original = &[5, 0, 3, 7];
104        let poly = Polynomial::from_slice(original).expect("roundtrip should succeed");
105
106        assert_eq!(poly.coefficients(), original);
107    }
108}