/rust/registry/src/index.crates.io-6f17d22bba15001f/object-0.36.1/src/pod.rs
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | //! Tools for converting file format structures to and from bytes. | 
| 2 |  | //! | 
| 3 |  | //! This module should be replaced once rust provides safe transmutes. | 
| 4 |  |  | 
| 5 |  | // This module provides functions for both read and write features. | 
| 6 |  | #![cfg_attr( | 
| 7 |  |     not(all(feature = "read_core", feature = "write_core")), | 
| 8 |  |     allow(dead_code) | 
| 9 |  | )] | 
| 10 |  |  | 
| 11 |  | use core::{mem, result, slice}; | 
| 12 |  |  | 
| 13 |  | type Result<T> = result::Result<T, ()>; | 
| 14 |  |  | 
| 15 |  | /// A trait for types that can safely be converted from and to byte slices. | 
| 16 |  | /// | 
| 17 |  | /// # Safety | 
| 18 |  | /// A type that is `Pod` must: | 
| 19 |  | /// - be `#[repr(C)]` or `#[repr(transparent)]` | 
| 20 |  | /// - have no invalid byte values | 
| 21 |  | /// - have no padding | 
| 22 |  | pub unsafe trait Pod: Copy + 'static {} | 
| 23 |  |  | 
| 24 |  | /// Cast the head of a byte slice to a `Pod` type. | 
| 25 |  | /// | 
| 26 |  | /// Returns the type and the tail of the byte slice. | 
| 27 |  | /// | 
| 28 |  | /// Returns an error if the byte slice is too short or the alignment is invalid. | 
| 29 |  | #[inline] | 
| 30 | 0 | pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> { | 
| 31 | 0 |     let size = mem::size_of::<T>(); | 
| 32 | 0 |     let tail = data.get(size..).ok_or(())?; | 
| 33 | 0 |     let ptr = data.as_ptr(); | 
| 34 | 0 |     if (ptr as usize) % mem::align_of::<T>() != 0 { | 
| 35 | 0 |         return Err(()); | 
| 36 | 0 |     } | 
| 37 | 0 |     // Safety: | 
| 38 | 0 |     // The alignment and size are checked by this function. | 
| 39 | 0 |     // The Pod trait ensures the type is valid to cast from bytes. | 
| 40 | 0 |     let val = unsafe { &*ptr.cast() }; | 
| 41 | 0 |     Ok((val, tail)) | 
| 42 | 0 | } Unexecuted instantiation: object::pod::from_bytes::<object::elf::FileHeader64<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::from_bytes::<object::elf::NoteHeader32<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::from_bytes::<object::elf::SectionHeader64<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::from_bytes::<object::elf::CompressionHeader64<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::from_bytes::<object::endian::U32Bytes<object::endian::BigEndian>>Unexecuted instantiation: object::pod::from_bytes::<object::endian::U16Bytes<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageBaseRelocation>Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageExportDirectory>Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageImportDescriptor>Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageResourceDataEntry>Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageResourceDirectory>Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageDelayloadDescriptor>Unexecuted instantiation: object::pod::from_bytes::<u8> | 
| 43 |  |  | 
| 44 |  | /// Cast the head of a mutable byte slice to a `Pod` type. | 
| 45 |  | /// | 
| 46 |  | /// Returns the type and the tail of the byte slice. | 
| 47 |  | /// | 
| 48 |  | /// Returns an error if the byte slice is too short or the alignment is invalid. | 
| 49 |  | #[inline] | 
| 50 | 0 | pub fn from_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> { | 
| 51 | 0 |     let size = mem::size_of::<T>(); | 
| 52 | 0 |     if size > data.len() { | 
| 53 | 0 |         return Err(()); | 
| 54 | 0 |     } | 
| 55 | 0 |     let (data, tail) = data.split_at_mut(size); | 
| 56 | 0 |     let ptr = data.as_mut_ptr(); | 
| 57 | 0 |     if (ptr as usize) % mem::align_of::<T>() != 0 { | 
| 58 | 0 |         return Err(()); | 
| 59 | 0 |     } | 
| 60 | 0 |     // Safety: | 
| 61 | 0 |     // The alignment and size are checked by this function. | 
| 62 | 0 |     // The Pod trait ensures the type is valid to cast from bytes. | 
| 63 | 0 |     let val = unsafe { &mut *ptr.cast() }; | 
| 64 | 0 |     Ok((val, tail)) | 
| 65 | 0 | } | 
| 66 |  |  | 
| 67 |  | /// Cast the head of a byte slice to a slice of a `Pod` type. | 
| 68 |  | /// | 
| 69 |  | /// Returns the type slice and the tail of the byte slice. | 
| 70 |  | /// | 
| 71 |  | /// Returns an error if the byte slice is too short or the alignment is invalid. | 
| 72 |  | #[inline] | 
| 73 | 0 | pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8])> { | 
| 74 | 0 |     let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?; | 
| 75 | 0 |     let tail = data.get(size..).ok_or(())?; | 
| 76 | 0 |     let ptr = data.as_ptr(); | 
| 77 | 0 |     if (ptr as usize) % mem::align_of::<T>() != 0 { | 
| 78 | 0 |         return Err(()); | 
| 79 | 0 |     } | 
| 80 | 0 |     // Safety: | 
| 81 | 0 |     // The alignment and size are checked by this function. | 
| 82 | 0 |     // The Pod trait ensures the type is valid to cast from bytes. | 
| 83 | 0 |     let slice = unsafe { slice::from_raw_parts(ptr.cast(), count) }; | 
| 84 | 0 |     Ok((slice, tail)) | 
| 85 | 0 | } Unexecuted instantiation: object::pod::slice_from_bytes::<object::elf::SectionHeader64<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::slice_from_bytes::<object::elf::Sym64<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::slice_from_bytes::<object::endian::U32Bytes<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::slice_from_bytes::<object::endian::U16Bytes<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::slice_from_bytes::<object::endian::U32Bytes<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::slice_from_bytes::<object::pe::ImageDataDirectory>Unexecuted instantiation: object::pod::slice_from_bytes::<object::pe::ImageResourceDirectoryEntry> | 
| 86 |  |  | 
| 87 |  | /// Cast the head of a mutable byte slice to a slice of a `Pod` type. | 
| 88 |  | /// | 
| 89 |  | /// Returns the type slice and the tail of the byte slice. | 
| 90 |  | /// | 
| 91 |  | /// Returns an error if the byte slice is too short or the alignment is invalid. | 
| 92 |  | #[inline] | 
| 93 | 0 | pub fn slice_from_bytes_mut<T: Pod>( | 
| 94 | 0 |     data: &mut [u8], | 
| 95 | 0 |     count: usize, | 
| 96 | 0 | ) -> Result<(&mut [T], &mut [u8])> { | 
| 97 | 0 |     let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?; | 
| 98 | 0 |     if size > data.len() { | 
| 99 | 0 |         return Err(()); | 
| 100 | 0 |     } | 
| 101 | 0 |     let (data, tail) = data.split_at_mut(size); | 
| 102 | 0 |     let ptr = data.as_mut_ptr(); | 
| 103 | 0 |     if (ptr as usize) % mem::align_of::<T>() != 0 { | 
| 104 | 0 |         return Err(()); | 
| 105 | 0 |     } | 
| 106 | 0 |     // Safety: | 
| 107 | 0 |     // The alignment and size are checked by this function. | 
| 108 | 0 |     // The Pod trait ensures the type is valid to cast from bytes. | 
| 109 | 0 |     let slice = unsafe { slice::from_raw_parts_mut(ptr.cast(), count) }; | 
| 110 | 0 |     Ok((slice, tail)) | 
| 111 | 0 | } | 
| 112 |  |  | 
| 113 |  | /// Cast all of a byte slice to a slice of a `Pod` type. | 
| 114 |  | /// | 
| 115 |  | /// Returns the type slice. | 
| 116 |  | /// | 
| 117 |  | /// Returns an error if the size of the byte slice is not an exact multiple | 
| 118 |  | /// of the type size, or the alignment is invalid. | 
| 119 |  | #[inline] | 
| 120 | 0 | pub fn slice_from_all_bytes<T: Pod>(data: &[u8]) -> Result<&[T]> { | 
| 121 | 0 |     let count = data.len() / mem::size_of::<T>(); | 
| 122 | 0 |     let (slice, tail) = slice_from_bytes(data, count)?; | 
| 123 | 0 |     if !tail.is_empty() { | 
| 124 | 0 |         return Err(()); | 
| 125 | 0 |     } | 
| 126 | 0 |     Ok(slice) | 
| 127 | 0 | } Unexecuted instantiation: object::pod::slice_from_all_bytes::<object::elf::Sym64<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::slice_from_all_bytes::<object::endian::U32Bytes<object::endian::LittleEndian>>Unexecuted instantiation: object::pod::slice_from_all_bytes::<_> | 
| 128 |  |  | 
| 129 |  | /// Cast all of a byte slice to a slice of a `Pod` type. | 
| 130 |  | /// | 
| 131 |  | /// Returns the type slice. | 
| 132 |  | /// | 
| 133 |  | /// Returns an error if the size of the byte slice is not an exact multiple | 
| 134 |  | /// of the type size, or the alignment is invalid. | 
| 135 |  | #[inline] | 
| 136 | 0 | pub fn slice_from_all_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<&mut [T]> { | 
| 137 | 0 |     let count = data.len() / mem::size_of::<T>(); | 
| 138 | 0 |     let (slice, tail) = slice_from_bytes_mut(data, count)?; | 
| 139 | 0 |     if !tail.is_empty() { | 
| 140 | 0 |         return Err(()); | 
| 141 | 0 |     } | 
| 142 | 0 |     Ok(slice) | 
| 143 | 0 | } | 
| 144 |  |  | 
| 145 |  | /// Cast a `Pod` type to a byte slice. | 
| 146 |  | #[inline] | 
| 147 | 0 | pub fn bytes_of<T: Pod>(val: &T) -> &[u8] { | 
| 148 | 0 |     let size = mem::size_of::<T>(); | 
| 149 | 0 |     // Safety: | 
| 150 | 0 |     // Any alignment is allowed. | 
| 151 | 0 |     // The size is determined in this function. | 
| 152 | 0 |     // The Pod trait ensures the type is valid to cast to bytes. | 
| 153 | 0 |     unsafe { slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size) } | 
| 154 | 0 | } | 
| 155 |  |  | 
| 156 |  | /// Cast a `Pod` type to a mutable byte slice. | 
| 157 |  | #[inline] | 
| 158 | 0 | pub fn bytes_of_mut<T: Pod>(val: &mut T) -> &mut [u8] { | 
| 159 | 0 |     let size = mem::size_of::<T>(); | 
| 160 | 0 |     // Safety: | 
| 161 | 0 |     // Any alignment is allowed. | 
| 162 | 0 |     // The size is determined in this function. | 
| 163 | 0 |     // The Pod trait ensures the type is valid to cast to bytes. | 
| 164 | 0 |     unsafe { slice::from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size) } | 
| 165 | 0 | } | 
| 166 |  |  | 
| 167 |  | /// Cast a slice of a `Pod` type to a byte slice. | 
| 168 |  | #[inline] | 
| 169 | 0 | pub fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] { | 
| 170 | 0 |     let size = val.len().wrapping_mul(mem::size_of::<T>()); | 
| 171 | 0 |     // Safety: | 
| 172 | 0 |     // Any alignment is allowed. | 
| 173 | 0 |     // The size is determined in this function. | 
| 174 | 0 |     // The Pod trait ensures the type is valid to cast to bytes. | 
| 175 | 0 |     unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) } | 
| 176 | 0 | } | 
| 177 |  |  | 
| 178 |  | /// Cast a slice of a `Pod` type to a mutable byte slice. | 
| 179 |  | #[inline] | 
| 180 | 0 | pub fn bytes_of_slice_mut<T: Pod>(val: &mut [T]) -> &mut [u8] { | 
| 181 | 0 |     let size = val.len().wrapping_mul(mem::size_of::<T>()); | 
| 182 | 0 |     // Safety: | 
| 183 | 0 |     // Any alignment is allowed. | 
| 184 | 0 |     // The size is determined in this function. | 
| 185 | 0 |     // The Pod trait ensures the type is valid to cast to bytes. | 
| 186 | 0 |     unsafe { slice::from_raw_parts_mut(val.as_mut_ptr().cast(), size) } | 
| 187 | 0 | } | 
| 188 |  |  | 
| 189 |  | macro_rules! unsafe_impl_pod { | 
| 190 |  |     ($($struct_name:ident),+ $(,)?) => { | 
| 191 |  |         $( | 
| 192 |  |             unsafe impl Pod for $struct_name { } | 
| 193 |  |         )+ | 
| 194 |  |     } | 
| 195 |  | } | 
| 196 |  |  | 
| 197 |  | unsafe_impl_pod!(u8, u16, u32, u64); | 
| 198 |  |  | 
| 199 |  | unsafe impl<const N: usize, T: Pod> Pod for [T; N] {} | 
| 200 |  |  | 
| 201 |  | #[cfg(test)] | 
| 202 |  | mod tests { | 
| 203 |  |     use super::*; | 
| 204 |  |  | 
| 205 |  |     #[test] | 
| 206 |  |     fn single() { | 
| 207 |  |         let x = u32::to_be(0x0123_4567); | 
| 208 |  |         let mut x_mut = x; | 
| 209 |  |         let bytes = bytes_of(&x); | 
| 210 |  |         let bytes_mut = bytes_of_mut(&mut x_mut); | 
| 211 |  |         assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67]); | 
| 212 |  |         assert_eq!(bytes, bytes_mut); | 
| 213 |  |  | 
| 214 |  |         let x16 = [u16::to_be(0x0123), u16::to_be(0x4567)]; | 
| 215 |  |  | 
| 216 |  |         let (y, tail) = from_bytes::<u32>(bytes).unwrap(); | 
| 217 |  |         let (y_mut, tail_mut) = from_bytes_mut::<u32>(bytes_mut).unwrap(); | 
| 218 |  |         assert_eq!(*y, x); | 
| 219 |  |         assert_eq!(y, y_mut); | 
| 220 |  |         assert_eq!(tail, &[]); | 
| 221 |  |         assert_eq!(tail, tail_mut); | 
| 222 |  |  | 
| 223 |  |         let (y, tail) = from_bytes::<u16>(bytes).unwrap(); | 
| 224 |  |         let (y_mut, tail_mut) = from_bytes_mut::<u16>(bytes_mut).unwrap(); | 
| 225 |  |         assert_eq!(*y, x16[0]); | 
| 226 |  |         assert_eq!(y, y_mut); | 
| 227 |  |         assert_eq!(tail, &bytes[2..]); | 
| 228 |  |         assert_eq!(tail, tail_mut); | 
| 229 |  |  | 
| 230 |  |         let (y, tail) = from_bytes::<u16>(&bytes[2..]).unwrap(); | 
| 231 |  |         let (y_mut, tail_mut) = from_bytes_mut::<u16>(&mut bytes_mut[2..]).unwrap(); | 
| 232 |  |         assert_eq!(*y, x16[1]); | 
| 233 |  |         assert_eq!(y, y_mut); | 
| 234 |  |         assert_eq!(tail, &[]); | 
| 235 |  |         assert_eq!(tail, tail_mut); | 
| 236 |  |  | 
| 237 |  |         assert_eq!(from_bytes::<u16>(&bytes[1..]), Err(())); | 
| 238 |  |         assert_eq!(from_bytes::<u16>(&bytes[3..]), Err(())); | 
| 239 |  |         assert_eq!(from_bytes::<u16>(&bytes[4..]), Err(())); | 
| 240 |  |         assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[1..]), Err(())); | 
| 241 |  |         assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[3..]), Err(())); | 
| 242 |  |         assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[4..]), Err(())); | 
| 243 |  |     } | 
| 244 |  |  | 
| 245 |  |     #[test] | 
| 246 |  |     fn slice() { | 
| 247 |  |         let x = [ | 
| 248 |  |             u16::to_be(0x0123), | 
| 249 |  |             u16::to_be(0x4567), | 
| 250 |  |             u16::to_be(0x89ab), | 
| 251 |  |             u16::to_be(0xcdef), | 
| 252 |  |         ]; | 
| 253 |  |         let mut x_mut = x; | 
| 254 |  |  | 
| 255 |  |         let bytes = bytes_of_slice(&x); | 
| 256 |  |         let bytes_mut = bytes_of_slice_mut(&mut x_mut); | 
| 257 |  |         assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]); | 
| 258 |  |         assert_eq!(bytes, bytes_mut); | 
| 259 |  |  | 
| 260 |  |         let (y, tail) = slice_from_bytes::<u16>(bytes, 4).unwrap(); | 
| 261 |  |         let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(bytes_mut, 4).unwrap(); | 
| 262 |  |         assert_eq!(y, x); | 
| 263 |  |         assert_eq!(y, y_mut); | 
| 264 |  |         assert_eq!(tail, &[]); | 
| 265 |  |         assert_eq!(tail, tail_mut); | 
| 266 |  |  | 
| 267 |  |         let (y, tail) = slice_from_bytes::<u16>(&bytes[2..], 2).unwrap(); | 
| 268 |  |         let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 2).unwrap(); | 
| 269 |  |         assert_eq!(y, &x[1..3]); | 
| 270 |  |         assert_eq!(y, y_mut); | 
| 271 |  |         assert_eq!(tail, &bytes[6..]); | 
| 272 |  |         assert_eq!(tail, tail_mut); | 
| 273 |  |  | 
| 274 |  |         assert_eq!(slice_from_bytes::<u16>(bytes, 5), Err(())); | 
| 275 |  |         assert_eq!(slice_from_bytes::<u16>(&bytes[2..], 4), Err(())); | 
| 276 |  |         assert_eq!(slice_from_bytes::<u16>(&bytes[1..], 2), Err(())); | 
| 277 |  |         assert_eq!(slice_from_bytes_mut::<u16>(bytes_mut, 5), Err(())); | 
| 278 |  |         assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 4), Err(())); | 
| 279 |  |         assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[1..], 2), Err(())); | 
| 280 |  |     } | 
| 281 |  | } |