rust_3d/io/
from_bytes.rs

1/*
2Copyright 2020 Martin Buck
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation the
7rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the Software
9is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall
12be included all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
20OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21*/
22
23//! Module containing the FromBytes trait
24
25use std::convert::TryInto;
26
27//------------------------------------------------------------------------------
28
29#[macro_export]
30macro_rules! array_from_bytes_le {
31    ($t:ty , $n:expr , $bytes:expr) => {{
32        let size = std::mem::size_of::<$t>();
33        if $bytes.len() != size * $n {
34            return Err(FromBytesError::SizeMismatch)?;
35        }
36
37        let mut arr: [$t; $n] = [<$t>::default(); $n];
38        for i in 0..$n {
39            arr[i] = <$t>::from_le_slice(&$bytes[i * size..(i + 1) * size])?
40        }
41        let result: FromBytesResult<[$t; $n]> = Ok(arr);
42        result
43    }};
44}
45
46#[macro_export]
47macro_rules! array_from_bytes_be {
48    ($t:ty , $n:expr , $bytes:expr) => {{
49        let size = std::mem::size_of::<$t>();
50        if $bytes.len() != size * $n {
51            return Err(FromBytesError::SizeMismatch)?;
52        }
53
54        let mut arr: [$t; $n] = [<$t>::default(); $n];
55        for i in 0..$n {
56            arr[i] = <$t>::from_be_slice(&$bytes[i * size..(i + 1) * size])?
57        }
58        let result: FromBytesResult<[$t; $n]> = Ok(arr);
59        result
60    }};
61}
62
63//------------------------------------------------------------------------------
64
65#[inline(always)]
66#[allow(unused)]
67pub fn slice_from_bytes_le<FB>(bytes: &[u8], target: &mut [FB]) -> FromBytesResult<()>
68where
69    FB: FromBytes,
70{
71    let size = std::mem::size_of::<FB>();
72
73    if bytes.len() != size * target.len() {
74        return Err(FromBytesError::SizeMismatch);
75    }
76
77    for i in 0..target.len() {
78        target[i] = FB::from_le_slice(&bytes[i * size..(i + 1) * size])?
79    }
80
81    Ok(())
82}
83
84//------------------------------------------------------------------------------
85
86#[inline(always)]
87#[allow(unused)]
88pub fn slice_from_bytes_be<FB>(bytes: &[u8], target: &mut [FB]) -> FromBytesResult<()>
89where
90    FB: FromBytes,
91{
92    let size = std::mem::size_of::<FB>();
93
94    if size * bytes.len() != target.len() {
95        return Err(FromBytesError::SizeMismatch);
96    }
97
98    for i in 0..target.len() {
99        target[i] = FB::from_be_slice(&bytes[i * size..(i + 1) * size])?
100    }
101
102    Ok(())
103}
104
105//------------------------------------------------------------------------------
106
107/// Trait for the conversion from byte slices (size is checked at run time)
108pub trait FromBytes: Sized {
109    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self>;
110    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self>;
111}
112
113//------------------------------------------------------------------------------
114
115impl FromBytes for i8 {
116    #[inline(always)]
117    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
118        Ok(i8::from_le_bytes(bytes.try_into()?))
119    }
120    #[inline(always)]
121    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
122        Ok(i8::from_be_bytes(bytes.try_into()?))
123    }
124}
125
126impl FromBytes for u8 {
127    #[inline(always)]
128    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
129        Ok(u8::from_le_bytes(bytes.try_into()?))
130    }
131    #[inline(always)]
132    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
133        Ok(u8::from_be_bytes(bytes.try_into()?))
134    }
135}
136
137impl FromBytes for i16 {
138    #[inline(always)]
139    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
140        Ok(i16::from_le_bytes(bytes.try_into()?))
141    }
142    #[inline(always)]
143    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
144        Ok(i16::from_be_bytes(bytes.try_into()?))
145    }
146}
147
148impl FromBytes for u16 {
149    #[inline(always)]
150    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
151        Ok(u16::from_le_bytes(bytes.try_into()?))
152    }
153    #[inline(always)]
154    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
155        Ok(u16::from_be_bytes(bytes.try_into()?))
156    }
157}
158
159impl FromBytes for i32 {
160    #[inline(always)]
161    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
162        Ok(i32::from_le_bytes(bytes.try_into()?))
163    }
164    #[inline(always)]
165    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
166        Ok(i32::from_be_bytes(bytes.try_into()?))
167    }
168}
169
170impl FromBytes for u32 {
171    #[inline(always)]
172    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
173        Ok(u32::from_le_bytes(bytes.try_into()?))
174    }
175    #[inline(always)]
176    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
177        Ok(u32::from_be_bytes(bytes.try_into()?))
178    }
179}
180
181impl FromBytes for f32 {
182    #[inline(always)]
183    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
184        Ok(f32::from_le_bytes(bytes.try_into()?))
185    }
186    #[inline(always)]
187    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
188        Ok(f32::from_be_bytes(bytes.try_into()?))
189    }
190}
191
192impl FromBytes for i64 {
193    #[inline(always)]
194    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
195        Ok(i64::from_le_bytes(bytes.try_into()?))
196    }
197    #[inline(always)]
198    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
199        Ok(i64::from_be_bytes(bytes.try_into()?))
200    }
201}
202
203impl FromBytes for u64 {
204    #[inline(always)]
205    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
206        Ok(u64::from_le_bytes(bytes.try_into()?))
207    }
208    #[inline(always)]
209    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
210        Ok(u64::from_be_bytes(bytes.try_into()?))
211    }
212}
213
214impl FromBytes for f64 {
215    #[inline(always)]
216    fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
217        Ok(f64::from_le_bytes(bytes.try_into()?))
218    }
219    #[inline(always)]
220    fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
221        Ok(f64::from_be_bytes(bytes.try_into()?))
222    }
223}
224
225//------------------------------------------------------------------------------
226
227/// Error type for the FromBytes conversion
228pub enum FromBytesError {
229    BinaryData,
230    SizeMismatch,
231}
232
233/// Result type for the FromBytes conversion
234pub type FromBytesResult<T> = std::result::Result<T, FromBytesError>;
235
236impl From<std::array::TryFromSliceError> for FromBytesError {
237    fn from(_error: std::array::TryFromSliceError) -> Self {
238        FromBytesError::BinaryData
239    }
240}
241
242//------------------------------------------------------------------------------