Skip to content

Commit 12b85f9

Browse files
committed
Byte tools update
1 parent 5bb9968 commit 12b85f9

File tree

7 files changed

+175
-354
lines changed

7 files changed

+175
-354
lines changed

byte-tools/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "byte-tools"
3-
version = "0.1.3"
3+
version = "0.2.0"
44
authors = ["The Rust-Crypto Project Developers"]
55
license = "MIT/Apache-2.0"
66
description = "Utility functions for working with bytes"

byte-tools/src/lib.rs

Lines changed: 9 additions & 303 deletions
Original file line numberDiff line numberDiff line change
@@ -1,243 +1,15 @@
11
#![no_std]
2-
use core::{mem, ptr};
2+
use core::ptr;
33

4-
/// Write a u64 into a vector, which must be 8 bytes long. The value is written
5-
/// in big-endian format.
6-
pub fn write_u64_be(dst: &mut [u8], mut input: u64) {
7-
assert!(dst.len() == 8);
8-
input = input.to_be();
9-
unsafe {
10-
let tmp = &input as *const _ as *const u8;
11-
ptr::copy_nonoverlapping(tmp, dst.get_unchecked_mut(0), 8);
12-
}
13-
}
14-
15-
/// Write a u64 into a vector, which must be 8 bytes long. The value is written
16-
/// in little-endian format.
17-
pub fn write_u64_le(dst: &mut [u8], mut input: u64) {
18-
assert!(dst.len() == 8);
19-
input = input.to_le();
20-
unsafe {
21-
let tmp = &input as *const _ as *const u8;
22-
ptr::copy_nonoverlapping(tmp, dst.get_unchecked_mut(0), 8);
23-
}
24-
}
25-
26-
/// Write a vector of u64s into a vector of bytes. The values are written in
27-
/// little-endian format.
28-
pub fn write_u64v_be(dst: &mut [u8], input: &[u64]) {
29-
assert!(dst.len() == 8 * input.len());
30-
unsafe {
31-
let mut x: *mut u8 = dst.get_unchecked_mut(0);
32-
let mut y: *const u64 = input.get_unchecked(0);
33-
for _ in 0..input.len() {
34-
let tmp = (*y).to_be();
35-
ptr::copy_nonoverlapping(&tmp as *const _ as *const u8, x, 8);
36-
x = x.offset(8);
37-
y = y.offset(1);
38-
}
39-
}
40-
}
41-
42-
/// Write a vector of u64s into a vector of bytes. The values are written in
43-
/// little-endian format.
44-
pub fn write_u64v_le(dst: &mut [u8], input: &[u64]) {
45-
assert!(dst.len() == 8 * input.len());
46-
unsafe {
47-
let mut x: *mut u8 = dst.get_unchecked_mut(0);
48-
let mut y: *const u64 = input.get_unchecked(0);
49-
for _ in 0..input.len() {
50-
let tmp = (*y).to_le();
51-
ptr::copy_nonoverlapping(&tmp as *const _ as *const u8, x, 8);
52-
x = x.offset(8);
53-
y = y.offset(1);
54-
}
55-
}
56-
}
4+
mod read_single;
5+
mod write_single;
6+
mod read_slice;
7+
mod write_slice;
578

58-
/// Write a u32 into a vector, which must be 4 bytes long. The value is written
59-
/// in big-endian format.
60-
pub fn write_u32_be(dst: &mut [u8], mut input: u32) {
61-
assert!(dst.len() == 4);
62-
input = input.to_be();
63-
unsafe {
64-
let tmp = &input as *const _ as *const u8;
65-
ptr::copy_nonoverlapping(tmp, dst.get_unchecked_mut(0), 4);
66-
}
67-
}
68-
69-
/// Write a u32 into a vector, which must be 4 bytes long. The value is written
70-
/// in little-endian format.
71-
pub fn write_u32_le(dst: &mut [u8], mut input: u32) {
72-
assert!(dst.len() == 4);
73-
input = input.to_le();
74-
unsafe {
75-
let tmp = &input as *const _ as *const u8;
76-
ptr::copy_nonoverlapping(tmp, dst.get_unchecked_mut(0), 4);
77-
}
78-
}
79-
80-
/// Write a vector of u32s into a vector of bytes. The values are written in
81-
/// little-endian format.
82-
pub fn write_u32v_le(dst: &mut [u8], input: &[u32]) {
83-
assert!(dst.len() == 4 * input.len());
84-
unsafe {
85-
let mut x: *mut u8 = dst.get_unchecked_mut(0);
86-
let mut y: *const u32 = input.get_unchecked(0);
87-
for _ in 0..input.len() {
88-
let tmp = (*y).to_le();
89-
ptr::copy_nonoverlapping(&tmp as *const _ as *const u8, x, 4);
90-
x = x.offset(4);
91-
y = y.offset(1);
92-
}
93-
}
94-
}
95-
96-
/// Write a vector of u32s into a vector of bytes. The values are written in
97-
/// big-endian format.
98-
pub fn write_u32v_be(dst: &mut [u8], input: &[u32]) {
99-
assert!(dst.len() == 4 * input.len());
100-
unsafe {
101-
let mut x: *mut u8 = dst.get_unchecked_mut(0);
102-
let mut y: *const u32 = input.get_unchecked(0);
103-
for _ in 0..input.len() {
104-
let tmp = (*y).to_be();
105-
ptr::copy_nonoverlapping(&tmp as *const _ as *const u8, x, 4);
106-
x = x.offset(4);
107-
y = y.offset(1);
108-
}
109-
}
110-
}
111-
112-
/// Read a vector of bytes into a vector of u64s. The values are read in
113-
/// big-endian format.
114-
pub fn read_u64v_be(dst: &mut [u64], input: &[u8]) {
115-
assert!(dst.len() * 8 == input.len());
116-
unsafe {
117-
let mut x: *mut u64 = dst.get_unchecked_mut(0);
118-
let mut y: *const u8 = input.get_unchecked(0);
119-
for _ in 0..dst.len() {
120-
let mut tmp: u64 = mem::uninitialized();
121-
ptr::copy_nonoverlapping(y, &mut tmp as *mut _ as *mut u8, 8);
122-
*x = u64::from_be(tmp);
123-
x = x.offset(1);
124-
y = y.offset(8);
125-
}
126-
}
127-
}
128-
129-
/// Read a vector of bytes into a vector of u64s. The values are read in
130-
/// little-endian format.
131-
pub fn read_u64v_le(dst: &mut [u64], input: &[u8]) {
132-
assert!(dst.len() * 8 == input.len());
133-
unsafe {
134-
let mut x: *mut u64 = dst.get_unchecked_mut(0);
135-
let mut y: *const u8 = input.get_unchecked(0);
136-
for _ in 0..dst.len() {
137-
let mut tmp: u64 = mem::uninitialized();
138-
ptr::copy_nonoverlapping(y, &mut tmp as *mut _ as *mut u8, 8);
139-
*x = u64::from_le(tmp);
140-
x = x.offset(1);
141-
y = y.offset(8);
142-
}
143-
}
144-
}
145-
146-
/// Read a vector of bytes into a vector of u32s. The values are read in
147-
/// big-endian format.
148-
pub fn read_u32v_be(dst: &mut [u32], input: &[u8]) {
149-
assert!(dst.len() * 4 == input.len());
150-
unsafe {
151-
let mut x: *mut u32 = dst.get_unchecked_mut(0);
152-
let mut y: *const u8 = input.get_unchecked(0);
153-
for _ in 0..dst.len() {
154-
let mut tmp: u32 = mem::uninitialized();
155-
ptr::copy_nonoverlapping(y, &mut tmp as *mut _ as *mut u8, 4);
156-
*x = u32::from_be(tmp);
157-
x = x.offset(1);
158-
y = y.offset(4);
159-
}
160-
}
161-
}
162-
163-
/// Read a vector of bytes into a vector of u32s. The values are read in
164-
/// little-endian format.
165-
pub fn read_u32v_le(dst: &mut [u32], input: &[u8]) {
166-
assert!(dst.len() * 4 == input.len());
167-
unsafe {
168-
let mut x: *mut u32 = dst.get_unchecked_mut(0);
169-
let mut y: *const u8 = input.get_unchecked(0);
170-
for _ in 0..dst.len() {
171-
let mut tmp: u32 = mem::uninitialized();
172-
ptr::copy_nonoverlapping(y, &mut tmp as *mut _ as *mut u8, 4);
173-
*x = u32::from_le(tmp);
174-
x = x.offset(1);
175-
y = y.offset(4);
176-
}
177-
}
178-
}
179-
180-
/// Read the value of a vector of bytes as a u32 value in little-endian format.
181-
pub fn read_u32_le(input: &[u8]) -> u32 {
182-
assert!(input.len() == 4);
183-
unsafe {
184-
let mut tmp: u32 = mem::uninitialized();
185-
ptr::copy_nonoverlapping(input.get_unchecked(0),
186-
&mut tmp as *mut _ as *mut u8,
187-
4);
188-
u32::from_le(tmp)
189-
}
190-
}
191-
192-
/// Read the value of a vector of bytes as a u64 value in little-endian format.
193-
pub fn read_u64_le(input: &[u8]) -> u64 {
194-
assert!(input.len() == 8);
195-
unsafe {
196-
let mut tmp: u64 = mem::uninitialized();
197-
ptr::copy_nonoverlapping(input.get_unchecked(0),
198-
&mut tmp as *mut _ as *mut u8,
199-
8);
200-
u64::from_le(tmp)
201-
}
202-
}
203-
204-
/// Read the value of a vector of bytes as a u32 value in big-endian format.
205-
pub fn read_u32_be(input: &[u8]) -> u32 {
206-
assert!(input.len() == 4);
207-
unsafe {
208-
let mut tmp: u32 = mem::uninitialized();
209-
ptr::copy_nonoverlapping(input.get_unchecked(0),
210-
&mut tmp as *mut _ as *mut u8,
211-
4);
212-
u32::from_be(tmp)
213-
}
214-
}
215-
216-
/// Read the value of a vector of bytes as a u64 value in big-endian format.
217-
pub fn read_u64_be(input: &[u8]) -> u64 {
218-
assert!(input.len() == 8);
219-
unsafe {
220-
let mut tmp: u64 = mem::uninitialized();
221-
ptr::copy_nonoverlapping(input.get_unchecked(0),
222-
&mut tmp as *mut _ as *mut u8,
223-
8);
224-
u64::from_be(tmp)
225-
}
226-
}
227-
228-
/// XOR plaintext and keystream, storing the result in dst.
229-
pub fn xor_keystream(dst: &mut [u8], plaintext: &[u8], keystream: &[u8]) {
230-
assert!(dst.len() == plaintext.len());
231-
assert!(plaintext.len() <= keystream.len());
232-
233-
// Do one byte at a time, using unsafe to skip bounds checking.
234-
let p = plaintext.as_ptr();
235-
let k = keystream.as_ptr();
236-
let d = dst.as_mut_ptr();
237-
for i in 0isize..plaintext.len() as isize {
238-
unsafe { *d.offset(i) = *p.offset(i) ^ *k.offset(i) };
239-
}
240-
}
9+
pub use read_single::*;
10+
pub use write_single::*;
11+
pub use read_slice::*;
12+
pub use write_slice::*;
24113

24214
/// Copy bytes from src to dest
24315
#[inline]
@@ -257,69 +29,3 @@ pub fn zero(dst: &mut [u8]) {
25729
ptr::write_bytes(dst.as_mut_ptr(), 0, dst.len());
25830
}
25931
}
260-
261-
/// Convert the value in bytes to the number of bits, a tuple where the 1st
262-
/// item is the high-order value and the 2nd item is the low order value.
263-
fn to_bits(x: u64) -> (u64, u64) { (x >> 61, x << 3) }
264-
265-
/// Adds the specified number of bytes to the bit count. panic!() if this
266-
/// would cause numeric overflow.
267-
pub fn add_bytes_to_bits(bits: u64, bytes: u64) -> u64 {
268-
let (new_high_bits, new_low_bits) = to_bits(bytes);
269-
270-
if new_high_bits > 0 {
271-
panic!("Numeric overflow occured.")
272-
}
273-
274-
bits.checked_add(new_low_bits).expect("Numeric overflow occured.")
275-
}
276-
277-
/// Adds the specified number of bytes to the bit count, which is a tuple where
278-
/// the first element is the high order value. panic!() if this would cause
279-
/// numeric overflow.
280-
pub fn add_bytes_to_bits_tuple(bits: (u64, u64), bytes: u64) -> (u64, u64) {
281-
let (new_high_bits, new_low_bits) = to_bits(bytes);
282-
let (hi, low) = bits;
283-
284-
// Add the low order value - if there is no overflow, then add the high
285-
// order values. If the addition of the low order values causes overflow,
286-
// add one to the high order values before adding them.
287-
match low.checked_add(new_low_bits) {
288-
Some(x) => {
289-
if new_high_bits == 0 {
290-
// This is the fast path - every other alternative will rarely
291-
// occur in practice considering how large an input would need
292-
// to be for those paths to be used.
293-
(hi, x)
294-
} else {
295-
match hi.checked_add(new_high_bits) {
296-
Some(y) => (y, x),
297-
None => panic!("Numeric overflow occured."),
298-
}
299-
}
300-
},
301-
None => {
302-
let z = match new_high_bits.checked_add(1) {
303-
Some(w) => w,
304-
None => panic!("Numeric overflow occured."),
305-
};
306-
match hi.checked_add(z) {
307-
// This re-executes the addition that was already performed
308-
// earlier when overflow occured, this time allowing the
309-
// overflow to happen. Technically, this could be avoided by
310-
// using the checked add intrinsic directly, but that involves
311-
// using unsafe code and is not really worthwhile considering
312-
// how infrequently code will run in practice. This is the
313-
// reason that this function requires that the type T be
314-
// UnsignedInt - overflow is not defined for Signed types.
315-
// This function could be implemented for signed types as well
316-
// if that were needed.
317-
Some(y) => (y, low.wrapping_add(new_low_bits)),
318-
None => panic!("Numeric overflow occured."),
319-
}
320-
},
321-
}
322-
}
323-
324-
#[cfg(test)]
325-
pub mod tests;

byte-tools/src/read_single.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use core::{mem, ptr};
2+
3+
macro_rules! read_single {
4+
($src:expr, $size:expr, $ty:ty, $which:ident) => ({
5+
assert!($size == mem::size_of::<$ty>());
6+
assert!($size == $src.len());
7+
unsafe {
8+
let mut tmp: $ty = mem::uninitialized();
9+
let p = &mut tmp as *mut _ as *mut u8;
10+
ptr::copy_nonoverlapping($src.as_ptr(), p, $size);
11+
tmp.$which()
12+
}
13+
});
14+
}
15+
16+
/// Read the value of a vector of bytes as a u32 value in little-endian format.
17+
#[inline]
18+
pub fn read_u32_le(src: &[u8]) -> u32 {
19+
read_single!(src, 4, u32, to_le)
20+
}
21+
22+
/// Read the value of a vector of bytes as a u32 value in big-endian format.
23+
#[inline]
24+
pub fn read_u32_be(src: &[u8]) -> u32 {
25+
read_single!(src, 4, u32, to_be)
26+
}
27+
28+
/// Read the value of a vector of bytes as a u64 value in little-endian format.
29+
#[inline]
30+
pub fn read_u64_le(src: &[u8]) -> u64 {
31+
read_single!(src, 8, u64, to_le)
32+
}
33+
34+
/// Read the value of a vector of bytes as a u64 value in big-endian format.
35+
#[inline]
36+
pub fn read_u64_be(src: &[u8]) -> u64 {
37+
read_single!(src, 8, u64, to_be)
38+
}

0 commit comments

Comments
 (0)