ark-ff 0.6.0

A library for finite fields
Documentation
use crate::fields::models::small_fp::small_fp_backend::{SmallFp, SmallFpConfig};
use crate::{PrimeField, Zero};
use ark_serialize::{
    buffer_byte_size, CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize,
    CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, SerializationError, Valid, Validate,
};

impl<P: SmallFpConfig> CanonicalSerializeWithFlags for SmallFp<P> {
    fn serialize_with_flags<W: ark_std::io::Write, F: Flags>(
        &self,
        writer: W,
        flags: F,
    ) -> Result<(), SerializationError> {
        // All reasonable `Flags` should be less than 8 bits in size
        // (256 values are enough for anyone!)
        if F::BIT_SIZE > 8 {
            return Err(SerializationError::NotEnoughSpace);
        }

        // Calculate the number of bytes required to represent a field element
        // serialized with `flags`. If `F::BIT_SIZE < 8`,
        // this is at most `N * 8 + 1`
        let output_byte_size = buffer_byte_size(Self::MODULUS_BIT_SIZE as usize + F::BIT_SIZE);
        let mut w = writer;

        // Serialize the Montgomery representation directly
        let raw: u128 = self.value.into();
        let mut bytes = [0u8; 17];
        bytes[..16].copy_from_slice(&raw.to_le_bytes());
        bytes[output_byte_size - 1] |= flags.u8_bitmask();
        w.write_all(&bytes[..output_byte_size])?;
        Ok(())
    }

    // Let `m = 8 * n` for some `n` be the smallest multiple of 8 greater
    // than `P::MODULUS_BIT_SIZE`.
    // If `(m - P::MODULUS_BIT_SIZE) >= F::BIT_SIZE` , then this method returns `n`;
    // otherwise, it returns `n + 1`.
    fn serialized_size_with_flags<F: Flags>(&self) -> usize {
        buffer_byte_size(Self::MODULUS_BIT_SIZE as usize + F::BIT_SIZE)
    }
}

impl<P: SmallFpConfig> CanonicalSerialize for SmallFp<P> {
    #[inline]
    fn serialize_with_mode<W: ark_std::io::Write>(
        &self,
        writer: W,
        _compress: Compress,
    ) -> Result<(), SerializationError> {
        self.serialize_with_flags(writer, EmptyFlags)
    }

    #[inline]
    fn serialized_size(&self, _compress: Compress) -> usize {
        self.serialized_size_with_flags::<EmptyFlags>()
    }
}

impl<P: SmallFpConfig> CanonicalDeserializeWithFlags for SmallFp<P> {
    fn deserialize_with_flags<R: ark_std::io::Read, F: Flags>(
        reader: R,
    ) -> Result<(Self, F), SerializationError> {
        // All reasonable `Flags` should be less than 8 bits in size
        // (256 values are enough for anyone!)
        if F::BIT_SIZE > 8 {
            return Err(SerializationError::NotEnoughSpace);
        }
        // Calculate the number of bytes required to represent a field element
        // serialized with `flags`.
        let output_byte_size = Self::zero().serialized_size_with_flags::<F>();
        let mut r = reader;

        // Deserialize directly into the Montgomery representation,
        let mut bytes = [0u8; 17];
        r.read_exact(&mut bytes[..output_byte_size])?;
        let flags = F::from_u8_remove_flags(&mut bytes[output_byte_size - 1])
            .ok_or(SerializationError::UnexpectedFlags)?;

        let mut le_bytes = [0u8; 16];
        le_bytes[..output_byte_size.min(16)].copy_from_slice(&bytes[..output_byte_size.min(16)]);
        let raw = u128::from_le_bytes(le_bytes);

        if raw >= P::MODULUS_U128 {
            return Err(SerializationError::InvalidData);
        }

        let value = P::T::try_from(raw)
            .ok()
            .ok_or(SerializationError::InvalidData)?;
        Ok((SmallFp::from_raw(value), flags))
    }
}

impl<P: SmallFpConfig> Valid for SmallFp<P> {
    fn check(&self) -> Result<(), SerializationError> {
        Ok(())
    }
}

impl<P: SmallFpConfig> CanonicalDeserialize for SmallFp<P> {
    fn deserialize_with_mode<R: ark_std::io::Read>(
        reader: R,
        _compress: Compress,
        _validate: Validate,
    ) -> Result<Self, SerializationError> {
        Self::deserialize_with_flags::<R, EmptyFlags>(reader).map(|(r, _)| r)
    }
}