Skip to content

Commit 2b7e460

Browse files
authored
Improve EncodedUint array conversions (#1068)
- Uses the same trick as `Array` to write bespoke `From` impls for `EncodedUint`, for all the sizes we do currently special-case - Updates the `Array` impls to be defined in the same macro we already use for writing size-specific impls anyway
1 parent 1cae801 commit 2b7e460

File tree

4 files changed

+73
-63
lines changed

4 files changed

+73
-63
lines changed

src/array.rs

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Interop support for `hybrid-array`
22
3-
use crate::{EncodedUint, Encoding, Integer, Limb};
3+
use crate::{Encoding, Integer};
44
use core::ops::Add;
5-
use hybrid_array::{Array, ArrayN, ArraySize, typenum::Unsigned};
5+
use hybrid_array::{Array, ArraySize, typenum::Unsigned};
66

77
/// Alias for a byte array whose size is defined by [`ArrayEncoding::ByteSize`].
88
pub type ByteArray<T> = Array<u8, <T as ArrayEncoding>::ByteSize>;
@@ -36,58 +36,3 @@ pub trait ArrayDecoding {
3636
/// Deserialize from a little-endian `Array`.
3737
fn into_uint_le(self) -> Self::Output;
3838
}
39-
40-
macro_rules! from_impls_for_encoded_uint {
41-
( $($nlimbs:expr),+ ) => {
42-
$(
43-
impl From<EncodedUint<$nlimbs>> for ArrayN<u8, { $nlimbs * Limb::BYTES }> {
44-
#[inline]
45-
fn from(input: EncodedUint<$nlimbs>) -> Self {
46-
let mut output = Self::default();
47-
output.as_mut_slice().copy_from_slice(input.as_ref());
48-
output
49-
}
50-
}
51-
52-
impl From<ArrayN<u8, { $nlimbs * Limb::BYTES }>> for EncodedUint<$nlimbs> {
53-
#[inline]
54-
fn from(input: ArrayN<u8, { $nlimbs * Limb::BYTES }>) -> Self {
55-
let mut output = Self::default();
56-
output.as_mut().copy_from_slice(input.as_ref());
57-
output
58-
}
59-
}
60-
)+
61-
};
62-
}
63-
64-
// Support up to 16 limbs for now (chosen somewhat arbitrarily)
65-
from_impls_for_encoded_uint!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
66-
67-
#[cfg(test)]
68-
mod tests {
69-
const LIMBS: usize = 4;
70-
const BYTES: usize = super::Limb::BYTES * LIMBS;
71-
72-
type Array = super::ArrayN<u8, { BYTES }>;
73-
type EncodedUint = super::EncodedUint<LIMBS>;
74-
75-
const ARRAY: Array = {
76-
let mut i = 0;
77-
let mut ret = [0u8; BYTES];
78-
while i < BYTES {
79-
ret[i] = i as u8;
80-
i += 1;
81-
}
82-
hybrid_array::Array(ret)
83-
};
84-
85-
#[test]
86-
fn from_impls_for_encoded_uint() {
87-
let encoded_uint = EncodedUint::from(ARRAY);
88-
assert_eq!(encoded_uint.as_ref(), ARRAY.as_slice());
89-
90-
let array = Array::from(encoded_uint);
91-
assert_eq!(array, ARRAY);
92-
}
93-
}

src/uint.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ pub use extra_sizes::*;
88
pub(crate) use ref_type::UintRef;
99

1010
use crate::{
11-
Bounded, Choice, ConstOne, ConstZero, Constants, CtEq, CtOption, FixedInteger, Int, Integer,
12-
Limb, NonZero, Odd, One, Unsigned, Word, Zero, modular::MontyForm,
11+
Bounded, Choice, ConstOne, ConstZero, Constants, CtEq, CtOption, EncodedUint, FixedInteger,
12+
Int, Integer, Limb, NonZero, Odd, One, Unsigned, Word, Zero, modular::MontyForm,
1313
};
1414
use core::fmt;
1515

src/uint/array.rs

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
//! `hybrid-array` integration with `Uint`.
22
// TODO(tarcieri): completely phase out `hybrid-array` when const generics are powerful enough
33

4-
use crate::{ArrayDecoding, ArrayEncoding, ByteArray};
5-
use hybrid_array::{Array, typenum};
4+
use crate::{ArrayDecoding, ArrayEncoding, ByteArray, EncodedUint, Limb};
5+
use hybrid_array::{Array, ArrayN, typenum};
66

77
macro_rules! impl_uint_array_encoding {
88
($(($uint:ident, $bytes:path)),+) => {
99
$(
10-
impl ArrayEncoding for super::$uint {
10+
use crate::$uint;
11+
12+
impl ArrayEncoding for $uint {
1113
type ByteSize = $bytes;
1214

1315
#[inline]
@@ -36,7 +38,7 @@ macro_rules! impl_uint_array_encoding {
3638
}
3739

3840
impl ArrayDecoding for Array<u8, $bytes> {
39-
type Output = super::$uint;
41+
type Output = $uint;
4042

4143
fn into_uint_be(self) -> Self::Output {
4244
Self::Output::from_be_byte_array(self)
@@ -46,6 +48,24 @@ macro_rules! impl_uint_array_encoding {
4648
Self::Output::from_le_byte_array(self)
4749
}
4850
}
51+
52+
impl From<EncodedUint<{ $uint::LIMBS }>> for ArrayN<u8, { $uint::LIMBS * Limb::BYTES }> {
53+
#[inline]
54+
fn from(input: EncodedUint<{ $uint::LIMBS }>) -> Self {
55+
let mut output = Self::default();
56+
output.as_mut_slice().copy_from_slice(input.as_ref());
57+
output
58+
}
59+
}
60+
61+
impl From<ArrayN<u8, { $uint::LIMBS * Limb::BYTES }>> for EncodedUint< { $uint::LIMBS }> {
62+
#[inline]
63+
fn from(input: ArrayN<u8, { $uint::LIMBS * Limb::BYTES }>) -> Self {
64+
let mut output = Self::default();
65+
output.as_mut().copy_from_slice(input.as_ref());
66+
output
67+
}
68+
}
4969
)+
5070
};
5171
}
@@ -191,4 +211,31 @@ mod tests {
191211
let actual_bytes = expected_bytes.into_uint_le().to_le_byte_array();
192212
assert_eq!(expected_bytes, actual_bytes);
193213
}
214+
215+
mod encoded_uint {
216+
const LIMBS: usize = 4;
217+
const BYTES: usize = crate::Limb::BYTES * LIMBS;
218+
219+
type Array = hybrid_array::ArrayN<u8, { BYTES }>;
220+
type EncodedUint = crate::EncodedUint<LIMBS>;
221+
222+
const ARRAY: Array = {
223+
let mut i = 0;
224+
let mut ret = [0u8; BYTES];
225+
while i < BYTES {
226+
ret[i] = i as u8;
227+
i += 1;
228+
}
229+
hybrid_array::Array(ret)
230+
};
231+
232+
#[test]
233+
fn from_impls_for_encoded_uint() {
234+
let encoded_uint = EncodedUint::from(ARRAY);
235+
assert_eq!(encoded_uint.as_ref(), ARRAY.as_slice());
236+
237+
let array = Array::from(encoded_uint);
238+
assert_eq!(array, ARRAY);
239+
}
240+
}
194241
}

src/uint/macros.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@ macro_rules! impl_uint_aliases {
77
#[doc = $doc]
88
#[doc="unsigned big integer."]
99
pub type $name = Uint<{ nlimbs!($bits) }>;
10+
11+
impl From<EncodedUint<{ nlimbs!($bits) }>> for [u8; { nlimbs!($bits) * Limb::BYTES }] {
12+
#[inline]
13+
fn from(input: EncodedUint<{ nlimbs!($bits) }>) -> Self {
14+
let mut output = [0u8; nlimbs!($bits) * Limb::BYTES];
15+
output.as_mut_slice().copy_from_slice(input.as_ref());
16+
output
17+
}
18+
}
19+
20+
impl From<[u8; { nlimbs!($bits) * Limb::BYTES }]> for EncodedUint< { nlimbs!($bits) }> {
21+
#[inline]
22+
fn from(input: [u8; { nlimbs!($bits) * Limb::BYTES }]) -> Self {
23+
let mut output = Self::default();
24+
output.as_mut().copy_from_slice(input.as_ref());
25+
output
26+
}
27+
}
1028
)+
1129
};
1230
}

0 commit comments

Comments
 (0)