byte_io/
lib.rs

1//! byte-io: a simple crate for read/write numbers to/from binary.
2//!
3//! This crate only contains 4 functions:
4//!
5//! * `write_be`: write number to big-endian slice.
6//!
7//! * `read_be`: read number from big-endian slice.
8//!
9//! * `write_le`: write number to little-endian slice.
10//!
11//! * `read_le`: read number from little-endian slice.
12//!
13//! ## Examples:
14//!
15//! Read from a slice is simple:
16//!
17//! ```
18//! use byte_io::*;
19//!
20//! fn main() {
21//!     let data = [0x00, 0x00, 0x01, 0x01, 0xAB, 0xCD, 0xEF, 0x89];
22//!     assert_eq!(read_be::<u32>(&data), 0x0101);
23//!     assert_eq!(read_be::<u16>(&data[4..]), 0xABCD);
24//!     assert_eq!(read_le::<u16>(&data[4..]), 0xCDAB);
25//!     assert_eq!(read_le::<u8>(&data[4..]), 0xAB);
26//! }
27//!
28//! ```
29//!
30//! Write is also easy:
31//!
32//! ```
33//! use byte_io::*;
34//!
35//! fn main() {
36//!     let mut buf = [0u8;8];
37//!     write_be(&0xABCDEFu32, &mut buf);
38//!     assert_eq!(buf, [0x00, 0xAB, 0xCD, 0xEF, 0x00, 0x00, 0x00, 0x00]);
39//!     write_le(&0xABCDEFu32, &mut buf[4..]);
40//!     assert_eq!(buf, [0x00, 0xAB, 0xCD, 0xEF, 0xEF, 0xCD, 0xAB, 0x00]);
41//! }
42//! ```
43//!
44//! Moreover, you can even read/write `Vec<T>`:
45//!
46//! ```
47//! use byte_io::*;
48//!
49//! fn main() {
50//!     let mut buf = [0u8;8];
51//!     let data = vec![0x1234u16,0x5678u16];
52//!     write_le(&data, &mut buf);
53//!     assert_eq!(buf, [0x34, 0x12, 0x78, 0x56, 0x00, 0x00, 0x00, 0x00]);
54//!     assert_eq!(data, read_le::<Vec<u16>>(&buf[0..4]));
55//!     let u32_vec = read_be::<Vec<u32>>(&buf[4..]);
56//!     assert_eq!(u32_vec.len(), 1);
57//!     assert_eq!(u32_vec.first(), Some(&0));
58//! }
59//! ```
60//!
61//! The following code also works:
62//!
63//! ```
64//! use byte_io::*;
65//!
66//! fn main() {
67//!     let buf = [0xAA, 0xBB, 0xCC, 0xDD];
68//!     assert_eq!(u32::from_u8_be(&buf), 0xAABBCCDD);
69//! }
70//! ```
71//!
72//!
73//! ## Implementation Details
74//!
75//! byte-io does __NOT__ focus on efficiency, which means that it may be slow
76//! while handling big streams (e.g. hundreds of Mbytes or more).
77//!
78//! Generally speaking, byte-io implements the two traits for numbers: `Readable` and
79//! `Writeable`. Every type implements these two traits can be deceded/enceded from
80//! binary stream.
81use std::marker;
82use std::mem::{size_of, transmute};
83
84/// write a number to stream as big-endian.
85///
86/// panics if buffer does not contain enough space.
87///
88/// ```
89/// use byte_io::*;
90///
91/// let mut buf = [0u8;8];
92/// write_be(&1u64, &mut buf);
93/// assert_eq!(buf, [0,0,0,0,0,0,0,1]);
94/// ```
95pub fn write_be<T: Writeable>(v: &T, buffer: &mut [u8]) {
96    T::to_u8_be(v, buffer);
97}
98
99/// read a number from stream as big-endian.
100///
101/// panics if buffer does not contain enough bytes.
102///
103/// ```
104/// use byte_io::*;
105/// let data = [0xAB, 0xCD, 0xEF, 0x01, 0x23];
106/// assert_eq!(read_be::<u32>(&data), 0xABCDEF01);
107/// assert_eq!(read_be::<i16>(&data[3..]), 0x0123);
108/// ```
109pub fn read_be<T: Readable>(buffer: &[u8]) -> T {
110    T::from_u8_be(buffer)
111}
112
113/// write a number to stream as little-endian.
114///
115/// panics if buffer does not contain enough space.
116///
117/// ```
118/// use byte_io::*;
119///
120/// let mut buf = [0u8;8];
121/// write_le(&1u64, &mut buf);
122/// assert_eq!(buf, [1,0,0,0,0,0,0,0]);
123/// ```
124pub fn write_le<T: Writeable>(v: &T, buffer: &mut [u8]) {
125    T::to_u8_le(v, buffer);
126}
127
128/// read a number from stream as big-endian.
129///
130/// panics if buffer does not contain enough bytes.
131///
132/// ```
133/// use byte_io::*;
134/// let data = [0xAB, 0xCD, 0xEF, 0x01, 0x23];
135/// assert_eq!(read_le::<u32>(&data), 0x01EFCDAB);
136/// assert_eq!(read_le::<i16>(&data[3..]), 0x2301);
137/// ```
138pub fn read_le<T: Readable>(buffer: &[u8]) -> T {
139    T::from_u8_le(buffer)
140}
141
142/// Any type implementing Readable can be decoded from binary.
143pub trait Readable : marker::Sized {
144    fn from_u8_be(&[u8]) -> Self;
145    fn from_u8_le(&[u8]) -> Self;
146}
147
148/// Any type implementing Writeable can be encoded from binary.
149pub trait Writeable : marker::Sized {
150    fn to_u8_be(&Self, &mut [u8]);
151    fn to_u8_le(&Self, &mut [u8]);
152}
153
154
155impl<T: Readable> Readable for Vec<T> {
156    fn from_u8_be(input: &[u8]) -> Self {
157        let t_size = size_of::<T>();
158        let mut output = Vec::new();
159        for i in 0..input.len() / t_size {
160            output.push(T::from_u8_be(&input[i * t_size..(i + 1) * t_size]));
161        }
162        output
163    }
164
165    fn from_u8_le(input: &[u8]) -> Self {
166        let t_size = size_of::<T>();
167        let mut output = Vec::new();
168        for i in 0..input.len() / t_size {
169            output.push(T::from_u8_le(&input[i * t_size..(i + 1) * t_size]));
170        }
171        output
172    }
173}
174
175impl<T: Writeable> Writeable for Vec<T> {
176    fn to_u8_be(v: &Self, buf: &mut [u8]) {
177        let t_size = size_of::<T>();
178        for (i, v) in v.iter().enumerate() {
179            T::to_u8_be(v, &mut buf[i * t_size..(i + 1) * t_size]);
180        }
181    }
182
183    fn to_u8_le(v: &Self, buf: &mut [u8]) {
184        let t_size = size_of::<T>();
185        for (i, v) in v.iter().enumerate() {
186            T::to_u8_le(v, &mut buf[i * t_size..(i + 1) * t_size]);
187        }
188    }
189}
190
191impl Writeable for i8 {
192    fn to_u8_be(v: &Self, a: &mut [u8]) {
193        a[0] = *v as u8;
194    }
195
196    fn to_u8_le(v: &Self, a: &mut [u8]) {
197        a[0] = *v as u8;
198    }
199}
200
201impl Readable for i8 {
202    fn from_u8_be(i: &[u8]) -> Self {
203        i[0] as i8
204    }
205
206    fn from_u8_le(i: &[u8]) -> Self {
207        i[0] as i8
208    }
209}
210
211impl Readable for u8 {
212    fn from_u8_be(a: &[u8]) -> Self {
213        a[0]
214    }
215
216    fn from_u8_le(a: &[u8]) -> Self {
217        a[0]
218    }
219}
220
221impl Writeable for u8 {
222    fn to_u8_be(v: &Self, a: &mut [u8]) {
223        a[0] = *v;
224    }
225
226    fn to_u8_le(v: &Self, a: &mut [u8]) {
227        a[0] = *v;
228    }
229}
230
231impl Readable for i16 {
232    fn from_u8_be(i: &[u8]) -> Self {
233        (i[0] as i16) << 8 | i[1] as i16
234    }
235
236    fn from_u8_le(i: &[u8]) -> Self {
237        (i[1] as i16) << 8 | i[0] as i16
238    }
239}
240
241impl Writeable for i16 {
242    fn to_u8_be(v: &Self, a: &mut [u8]) {
243        a[0] = (*v >> 8) as u8;
244        a[1] = *v as u8;
245    }
246
247    fn to_u8_le(v: &Self, a: &mut [u8]) {
248        a[1] = (*v >> 8) as u8;
249        a[0] = *v as u8;
250    }
251}
252
253impl Readable for u16 {
254    fn from_u8_be(i: &[u8]) -> Self {
255        (i[0] as u16) << 8 | i[1] as u16
256    }
257
258    fn from_u8_le(i: &[u8]) -> Self {
259        (i[1] as u16) << 8 | i[0] as u16
260    }
261}
262
263impl Writeable for u16 {
264    fn to_u8_be(v: &Self, a: &mut [u8]) {
265        a[0] = (*v >> 8) as u8;
266        a[1] = *v as u8;
267    }
268
269    fn to_u8_le(v: &Self, a: &mut [u8]) {
270        a[1] = (*v >> 8) as u8;
271        a[0] = *v as u8;
272    }
273}
274
275impl Readable for i32 {
276    fn from_u8_be(i: &[u8]) -> Self {
277        (i[0] as i32) << 24 | (i[1] as i32) << 16 | (i[2] as i32) << 8 | i[3] as i32
278    }
279
280    fn from_u8_le(i: &[u8]) -> Self {
281        (i[3] as i32) << 24 | (i[2] as i32) << 16 | (i[1] as i32) << 8 | i[0] as i32
282    }
283}
284
285impl Writeable for i32 {
286    fn to_u8_be(v: &Self, a: &mut [u8]) {
287        a[0] = (*v >> 24) as u8;
288        a[1] = (*v >> 16) as u8;
289        a[2] = (*v >> 8) as u8;
290        a[3] = *v as u8;
291    }
292
293    fn to_u8_le(v: &Self, a: &mut [u8]) {
294        a[3] = (*v >> 24) as u8;
295        a[2] = (*v >> 16) as u8;
296        a[1] = (*v >> 8) as u8;
297        a[0] = *v as u8;
298    }
299}
300
301impl Readable for u32 {
302    fn from_u8_be(i: &[u8]) -> Self {
303        (i[0] as u32) << 24 | (i[1] as u32) << 16 | (i[2] as u32) << 8 | i[3] as u32
304    }
305
306    fn from_u8_le(i: &[u8]) -> Self {
307        (i[3] as u32) << 24 | (i[2] as u32) << 16 | (i[1] as u32) << 8 | i[0] as u32
308    }
309}
310
311impl Writeable for u32 {
312    fn to_u8_be(v: &Self, a: &mut [u8]) {
313        a[0] = (*v >> 24) as u8;
314        a[1] = (*v >> 16) as u8;
315        a[2] = (*v >> 8) as u8;
316        a[3] = *v as u8;
317    }
318
319    fn to_u8_le(v: &Self, a: &mut [u8]) {
320        a[3] = (*v >> 24) as u8;
321        a[2] = (*v >> 16) as u8;
322        a[1] = (*v >> 8) as u8;
323        a[0] = *v as u8;
324    }
325}
326
327impl Readable for i64 {
328    fn from_u8_be(i: &[u8]) -> Self {
329        (i[0] as i64) << 56 | (i[1] as i64) << 48 | (i[2] as i64) << 40 | (i[3] as i64) << 32 |
330        (i[4] as i64) << 24 | (i[5] as i64) << 16 |
331        (i[6] as i64) << 8 | i[7] as i64
332    }
333
334    fn from_u8_le(i: &[u8]) -> Self {
335        (i[7] as i64) << 56 | (i[6] as i64) << 48 | (i[5] as i64) << 40 | (i[4] as i64) << 32 |
336        (i[3] as i64) << 24 | (i[2] as i64) << 16 |
337        (i[1] as i64) << 8 | i[0] as i64
338    }
339}
340
341impl Writeable for i64 {
342    fn to_u8_be(v: &Self, a: &mut [u8]) {
343        a[0] = (*v >> 56) as u8;
344        a[1] = (*v >> 48) as u8;
345        a[2] = (*v >> 40) as u8;
346        a[3] = (*v >> 32) as u8;
347        a[4] = (*v >> 24) as u8;
348        a[5] = (*v >> 16) as u8;
349        a[6] = (*v >> 8) as u8;
350        a[7] = *v as u8;
351    }
352
353    fn to_u8_le(v: &Self, a: &mut [u8]) {
354        a[7] = (*v >> 56) as u8;
355        a[6] = (*v >> 48) as u8;
356        a[5] = (*v >> 40) as u8;
357        a[4] = (*v >> 32) as u8;
358        a[3] = (*v >> 24) as u8;
359        a[2] = (*v >> 16) as u8;
360        a[1] = (*v >> 8) as u8;
361        a[0] = *v as u8;
362    }
363}
364
365impl Readable for u64 {
366    fn from_u8_be(i: &[u8]) -> Self {
367        (i[0] as u64) << 56 | (i[1] as u64) << 48 | (i[2] as u64) << 40 | (i[3] as u64) << 32 |
368        (i[4] as u64) << 24 | (i[5] as u64) << 16 |
369        (i[6] as u64) << 8 | i[7] as u64
370    }
371
372    fn from_u8_le(i: &[u8]) -> Self {
373        (i[7] as u64) << 56 | (i[6] as u64) << 48 | (i[5] as u64) << 40 | (i[4] as u64) << 32 |
374        (i[3] as u64) << 24 | (i[2] as u64) << 16 |
375        (i[1] as u64) << 8 | i[0] as u64
376    }
377}
378
379impl Writeable for u64 {
380    fn to_u8_be(v: &Self, a: &mut [u8]) {
381        a[0] = (*v >> 56) as u8;
382        a[1] = (*v >> 48) as u8;
383        a[2] = (*v >> 40) as u8;
384        a[3] = (*v >> 32) as u8;
385        a[4] = (*v >> 24) as u8;
386        a[5] = (*v >> 16) as u8;
387        a[6] = (*v >> 8) as u8;
388        a[7] = *v as u8;
389    }
390
391    fn to_u8_le(v: &Self, a: &mut [u8]) {
392        a[7] = (*v >> 56) as u8;
393        a[6] = (*v >> 48) as u8;
394        a[5] = (*v >> 40) as u8;
395        a[4] = (*v >> 32) as u8;
396        a[3] = (*v >> 24) as u8;
397        a[2] = (*v >> 16) as u8;
398        a[1] = (*v >> 8) as u8;
399        a[0] = *v as u8;
400    }
401}
402
403impl Readable for bool {
404    fn from_u8_be(i: &[u8]) -> Self {
405        i[0] > 0
406    }
407
408    fn from_u8_le(i: &[u8]) -> Self {
409        i[0] > 0
410    }
411}
412
413impl Writeable for bool {
414    fn to_u8_be(v: &Self, a: &mut [u8]) {
415        a[0] = if *v {
416            1u8
417        } else {
418            0u8
419        };
420    }
421
422    fn to_u8_le(v: &Self, a: &mut [u8]) {
423        a[0] = if *v {
424            1u8
425        } else {
426            0u8
427        };
428    }
429}
430
431impl Readable for f32 {
432    fn from_u8_be(i: &[u8]) -> Self {
433        unsafe { transmute(u32::from_u8_be(i)) }
434    }
435
436    fn from_u8_le(i: &[u8]) -> Self {
437        unsafe { transmute(u32::from_u8_le(i)) }
438    }
439}
440
441impl Writeable for f32 {
442    fn to_u8_be(v: &Self, a: &mut [u8]) {
443        unsafe { u32::to_u8_be(transmute(v), a) }
444    }
445
446    fn to_u8_le(v: &Self, a: &mut [u8]) {
447        unsafe { u32::to_u8_le(transmute(v), a) }
448    }
449}
450
451impl Readable for f64 {
452    fn from_u8_be(i: &[u8]) -> Self {
453        unsafe { transmute(u64::from_u8_be(i)) }
454    }
455
456    fn from_u8_le(i: &[u8]) -> Self {
457        unsafe { transmute(u64::from_u8_le(i)) }
458    }
459}
460
461impl Writeable for f64 {
462    fn to_u8_be(v: &Self, a: &mut [u8]) {
463        unsafe { u64::to_u8_be(transmute(v), a) }
464    }
465
466    fn to_u8_le(v: &Self, a: &mut [u8]) {
467        unsafe { u64::to_u8_le(transmute(v), a) }
468    }
469}