From 8df29c4b2b1da2d58ec07fca31529bf5b40a72ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= <4142+huitseeker@users.noreply.github.com> Date: Sat, 17 Apr 2021 14:44:18 -0400 Subject: [PATCH] Tiny-const-generics (#255) * updates bytes to use const generics * Add a check for a minimum rustc version in ff * Specify min version for the compiler in README --- README.md | 2 +- ff/build.rs | 8 +- ff/src/bytes.rs | 218 ++++++++++++++++++++---------------------------- 3 files changed, 98 insertions(+), 130 deletions(-) diff --git a/README.md b/README.md index 71df845a6..0a3f42ef3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ In addition, the [`curves`](https://github.com/arkworks-rs/curves) repository co ## Build guide -The library compiles on the `stable` toolchain of the Rust compiler. To install the latest version of Rust, first install `rustup` by following the instructions [here](https://rustup.rs/), or via your platform's package manager. Once `rustup` is installed, install the Rust toolchain by invoking: +The library compiles on the `stable` toolchain of the Rust compiler (v 1.51+). To install the latest version of Rust, first install `rustup` by following the instructions [here](https://rustup.rs/), or via your platform's package manager. Once `rustup` is installed, install the Rust toolchain by invoking: ```bash rustup install stable ``` diff --git a/ff/build.rs b/ff/build.rs index c6a7dad16..bc3a3772d 100644 --- a/ff/build.rs +++ b/ff/build.rs @@ -1,5 +1,5 @@ extern crate rustc_version; -use rustc_version::{version_meta, Channel}; +use rustc_version::{version, version_meta, Channel, Version}; fn main() { println!("cargo:rerun-if-changed=build.rs"); @@ -15,4 +15,10 @@ fn main() { if should_use_asm { println!("cargo:rustc-cfg=use_asm"); } + + // TODO: remove this once RFC 2495 ships + if version().expect("Installed rustc version unparseable!") < Version::parse("1.51.0").unwrap() + { + panic!("This code base uses const generics and requires a Rust compiler version greater or equal to 1.51.0"); + } } diff --git a/ff/src/bytes.rs b/ff/src/bytes.rs index 5ddf42fe9..af2e8ef6a 100644 --- a/ff/src/bytes.rs +++ b/ff/src/bytes.rs @@ -14,151 +14,113 @@ pub trait FromBytes: Sized { fn read(reader: R) -> IoResult; } -macro_rules! array_bytes { - ($N:expr) => { - impl ToBytes for [u8; $N] { - #[inline] - fn write(&self, mut writer: W) -> IoResult<()> { - writer.write_all(self) - } - } +impl ToBytes for [u8; N] { + #[inline] + fn write(&self, mut writer: W) -> IoResult<()> { + writer.write_all(self) + } +} - impl FromBytes for [u8; $N] { - #[inline] - fn read(mut reader: R) -> IoResult { - let mut arr = [0u8; $N]; - reader.read_exact(&mut arr)?; - Ok(arr) - } - } +impl FromBytes for [u8; N] { + #[inline] + fn read(mut reader: R) -> IoResult { + let mut arr = [0u8; N]; + reader.read_exact(&mut arr)?; + Ok(arr) + } +} - impl ToBytes for [u16; $N] { - #[inline] - fn write(&self, mut writer: W) -> IoResult<()> { - for num in self { - writer.write_all(&num.to_le_bytes())?; - } - Ok(()) - } +impl ToBytes for [u16; N] { + #[inline] + fn write(&self, mut writer: W) -> IoResult<()> { + for num in self { + writer.write_all(&num.to_le_bytes())?; } + Ok(()) + } +} - impl FromBytes for [u16; $N] { - #[inline] - fn read(mut reader: R) -> IoResult { - let mut res = [0u16; $N]; - for num in res.iter_mut() { - let mut bytes = [0u8; 2]; - reader.read_exact(&mut bytes)?; - *num = u16::from_le_bytes(bytes); - } - Ok(res) - } +impl FromBytes for [u16; N] { + #[inline] + fn read(mut reader: R) -> IoResult { + let mut res = [0u16; N]; + for num in res.iter_mut() { + let mut bytes = [0u8; 2]; + reader.read_exact(&mut bytes)?; + *num = u16::from_le_bytes(bytes); } + Ok(res) + } +} - impl ToBytes for [u32; $N] { - #[inline] - fn write(&self, mut writer: W) -> IoResult<()> { - for num in self { - writer.write_all(&num.to_le_bytes())?; - } - Ok(()) - } +impl ToBytes for [u32; N] { + #[inline] + fn write(&self, mut writer: W) -> IoResult<()> { + for num in self { + writer.write_all(&num.to_le_bytes())?; } + Ok(()) + } +} - impl FromBytes for [u32; $N] { - #[inline] - fn read(mut reader: R) -> IoResult { - let mut res = [0u32; $N]; - for num in res.iter_mut() { - let mut bytes = [0u8; 4]; - reader.read_exact(&mut bytes)?; - *num = u32::from_le_bytes(bytes); - } - Ok(res) - } +impl FromBytes for [u32; N] { + #[inline] + fn read(mut reader: R) -> IoResult { + let mut res = [0u32; N]; + for num in res.iter_mut() { + let mut bytes = [0u8; 4]; + reader.read_exact(&mut bytes)?; + *num = u32::from_le_bytes(bytes); } + Ok(res) + } +} - impl ToBytes for [u64; $N] { - #[inline] - fn write(&self, mut writer: W) -> IoResult<()> { - for num in self { - writer.write_all(&num.to_le_bytes())?; - } - Ok(()) - } +impl ToBytes for [u64; N] { + #[inline] + fn write(&self, mut writer: W) -> IoResult<()> { + for num in self { + writer.write_all(&num.to_le_bytes())?; } + Ok(()) + } +} - impl FromBytes for [u64; $N] { - #[inline] - fn read(mut reader: R) -> IoResult { - let mut res = [0u64; $N]; - for num in res.iter_mut() { - let mut bytes = [0u8; 8]; - reader.read_exact(&mut bytes)?; - *num = u64::from_le_bytes(bytes); - } - Ok(res) - } +impl FromBytes for [u64; N] { + #[inline] + fn read(mut reader: R) -> IoResult { + let mut res = [0u64; N]; + for num in res.iter_mut() { + let mut bytes = [0u8; 8]; + reader.read_exact(&mut bytes)?; + *num = u64::from_le_bytes(bytes); } + Ok(res) + } +} - impl ToBytes for [u128; $N] { - #[inline] - fn write(&self, mut writer: W) -> IoResult<()> { - for num in self { - writer.write_all(&num.to_le_bytes())?; - } - Ok(()) - } +impl ToBytes for [u128; N] { + #[inline] + fn write(&self, mut writer: W) -> IoResult<()> { + for num in self { + writer.write_all(&num.to_le_bytes())?; } + Ok(()) + } +} - impl FromBytes for [u128; $N] { - #[inline] - fn read(mut reader: R) -> IoResult { - let mut res = [0u128; $N]; - for num in res.iter_mut() { - let mut bytes = [0u8; 16]; - reader.read_exact(&mut bytes)?; - *num = u128::from_le_bytes(bytes); - } - Ok(res) - } +impl FromBytes for [u128; N] { + #[inline] + fn read(mut reader: R) -> IoResult { + let mut res = [0u128; N]; + for num in res.iter_mut() { + let mut bytes = [0u8; 16]; + reader.read_exact(&mut bytes)?; + *num = u128::from_le_bytes(bytes); } - }; -} - -array_bytes!(0); -array_bytes!(1); -array_bytes!(2); -array_bytes!(3); -array_bytes!(4); -array_bytes!(5); -array_bytes!(6); -array_bytes!(7); -array_bytes!(8); -array_bytes!(9); -array_bytes!(10); -array_bytes!(11); -array_bytes!(12); -array_bytes!(13); -array_bytes!(14); -array_bytes!(15); -array_bytes!(16); -array_bytes!(17); -array_bytes!(18); -array_bytes!(19); -array_bytes!(20); -array_bytes!(21); -array_bytes!(22); -array_bytes!(23); -array_bytes!(24); -array_bytes!(25); -array_bytes!(26); -array_bytes!(27); -array_bytes!(28); -array_bytes!(29); -array_bytes!(30); -array_bytes!(31); -array_bytes!(32); + Ok(res) + } +} /// Takes as input a sequence of structs, and converts them to a series of /// bytes. All traits that implement `Bytes` can be automatically converted to