lib.rs (13493B)
1 // Copyright 2019 The Servo Project Developers. See the COPYRIGHT 2 // file at the top-level directory of this distribution and at 3 // http://rust-lang.org/COPYRIGHT. 4 // 5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 8 // option. This file may not be copied, modified, or distributed 9 // except according to those terms. 10 11 //! Fast binary serialization and deserialization for types with a known maximum size. 12 //! 13 //! ## Binary Encoding Scheme 14 //! 15 //! ## Usage 16 //! 17 //! ## Comparison to bincode 18 19 #[cfg(feature = "derive")] 20 pub use peek_poke_derive::*; 21 22 use core::{marker::PhantomData, mem::size_of, slice}; 23 use crate::{slice_ext::*, vec_ext::*}; 24 25 mod slice_ext; 26 mod vec_ext; 27 28 union MaybeUninitShim<T: Copy> { 29 uninit: (), 30 init: T, 31 } 32 33 /// Peek helper for constructing a `T` by `Copy`ing into an uninitialized stack 34 /// allocation. 35 /// 36 /// # Safety 37 /// 38 /// * `bytes` must denote a valid pointer to a block of memory. 39 /// 40 /// * `bytes` must point to at least the number of bytes returned by 41 /// `Poke::max_size()`. 42 pub unsafe fn peek_from_uninit<T: Copy + Peek>(bytes: *const u8) -> (T, *const u8) { 43 let mut val = MaybeUninitShim { uninit: () }; 44 let bytes = <T>::peek_from(bytes, &mut val.init); 45 (val.init, bytes) 46 } 47 48 /// Peek helper for constructing a `T` by `Default` initialized stack 49 /// allocation. 50 /// 51 /// # Safety 52 /// 53 /// * `bytes` must denote a valid pointer to a block of memory. 54 /// 55 /// * `bytes` must point to at least the number of bytes returned by 56 /// `Poke::max_size()`. 57 pub unsafe fn peek_from_default<T: Default + Peek>(bytes: *const u8) -> (T, *const u8) { 58 let mut val = T::default(); 59 let bytes = <T>::peek_from(bytes, &mut val); 60 (val, bytes) 61 } 62 63 /// Peek inplace a `T` from a slice of bytes, returning a slice of the remaining 64 /// bytes. `src` must contain at least `T::max_size()` bytes. 65 /// 66 /// [`ensure_red_zone`] can be used to add required padding. 67 pub fn peek_from_slice<'a, T: Peek>(src: &'a [u8], dst: &mut T) -> &'a [u8] { 68 unsafe { 69 // If src.len() == T::max_size() then src is at the start of the red-zone. 70 assert!(T::max_size() < src.len(), "WRDL: unexpected end of display list"); 71 let end_ptr = T::peek_from(src.as_ptr(), dst); 72 let len = end_ptr as usize - src.as_ptr() as usize; 73 // Did someone break the T::peek_from() can't read more than T::max_size() 74 // bytes contract? 75 assert!(len <= src.len(), "WRDL: Peek::max_size was wrong"); 76 slice::from_raw_parts(end_ptr, src.len() - len) 77 } 78 } 79 80 /// Poke helper to insert a serialized version of `src` at the beginning for `dst`. 81 pub fn poke_inplace_slice<T: Poke>(src: &T, dst: &mut [u8]) { 82 assert!(T::max_size() <= dst.len(), "WRDL: buffer too small to write into"); 83 unsafe { 84 src.poke_into(dst.as_mut_ptr()); 85 } 86 } 87 88 /// Poke helper to append a serialized version of `src` to the end of `dst`. 89 pub fn poke_into_vec<T: Poke>(src: &T, dst: &mut Vec<u8>) { 90 dst.reserve(T::max_size()); 91 unsafe { 92 let ptr = dst.as_end_mut_ptr(); 93 let end_ptr = src.poke_into(ptr); 94 dst.set_end_ptr(end_ptr); 95 } 96 } 97 98 // TODO: Is returning the len of the iterator of any practical use? 99 pub fn poke_extend_vec<I>(src: I, dst: &mut Vec<u8>) -> usize 100 where 101 I: ExactSizeIterator, 102 I::Item: Poke, 103 { 104 let len = src.len(); 105 let max_size = len * I::Item::max_size(); 106 dst.reserve(max_size); 107 unsafe { 108 let ptr = dst.as_end_mut_ptr(); 109 // Guard against the possibility of a misbehaved implementation of 110 // ExactSizeIterator by writing at most `len` items. 111 let end_ptr = src.take(len).fold(ptr, |ptr, item| item.poke_into(ptr)); 112 dst.set_end_ptr(end_ptr); 113 } 114 115 len 116 } 117 118 /// Add `T::max_size()` "red zone" (padding of zeroes) to the end of the vec of 119 /// `bytes`. This allows deserialization to assert that at least `T::max_size()` 120 /// bytes exist at all times. 121 pub fn ensure_red_zone<T: Poke>(bytes: &mut Vec<u8>) { 122 bytes.reserve(T::max_size()); 123 unsafe { 124 let end_ptr = bytes.as_end_mut_ptr(); 125 end_ptr.write_bytes(0, T::max_size()); 126 bytes.set_end_ptr(end_ptr.add(T::max_size())); 127 } 128 } 129 130 /// Remove the "red zone" (padding of zeroes) from the end of the vec of `bytes`. 131 /// This is effectively the inverse of `ensure_red_zone`, with the caveat that 132 /// space reserved for the red zone is not un-reserved. Callers are repsonsible 133 /// for making sure the vec actually has a red zone, otherwise data bytes can 134 /// get stripped instead. 135 pub fn strip_red_zone<T: Poke>(bytes: &mut Vec<u8>) { 136 assert!(bytes.len() >= T::max_size()); 137 unsafe { 138 let end_ptr = bytes.as_end_mut_ptr(); 139 bytes.set_end_ptr(end_ptr.sub(T::max_size())); 140 } 141 } 142 143 #[inline] 144 unsafe fn read_verbatim<T>(src: *const u8, dst: *mut T) -> *const u8 { 145 *dst = (src as *const T).read_unaligned(); 146 src.add(size_of::<T>()) 147 } 148 149 #[inline] 150 unsafe fn write_verbatim<T>(src: T, dst: *mut u8) -> *mut u8 { 151 (dst as *mut T).write_unaligned(src); 152 dst.add(size_of::<T>()) 153 } 154 155 #[cfg(feature = "extras")] 156 mod euclid; 157 158 /// A trait for values that provide serialization into buffers of bytes. 159 /// 160 /// # Example 161 /// 162 /// ```no_run 163 /// use peek_poke::Poke; 164 /// 165 /// struct Bar { 166 /// a: u32, 167 /// b: u8, 168 /// c: i16, 169 /// } 170 /// 171 /// unsafe impl Poke for Bar { 172 /// fn max_size() -> usize { 173 /// <u32>::max_size() + <u8>::max_size() + <i16>::max_size() 174 /// } 175 /// unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 176 /// let bytes = self.a.poke_into(bytes); 177 /// let bytes = self.b.poke_into(bytes); 178 /// self.c.poke_into(bytes) 179 /// } 180 /// } 181 /// ``` 182 /// 183 /// # Safety 184 /// 185 /// The `Poke` trait is an `unsafe` trait for the reasons, and implementors must 186 /// ensure that they adhere to these contracts: 187 /// 188 /// * `max_size()` query and calculations in general must be correct. Callers 189 /// of this trait are expected to rely on the contract defined on each 190 /// method, and implementors must ensure such contracts remain true. 191 pub unsafe trait Poke { 192 /// Return the maximum number of bytes that the serialized version of `Self` 193 /// will occupy. 194 /// 195 /// # Safety 196 /// 197 /// Implementors of `Poke` guarantee to not write more than the result of 198 /// calling `max_size()` into the buffer pointed to by `bytes` when 199 /// `poke_into()` is called. 200 fn max_size() -> usize; 201 /// Serialize into the buffer pointed to by `bytes`. 202 /// 203 /// Returns a pointer to the next byte after the serialized representation of `Self`. 204 /// 205 /// # Safety 206 /// 207 /// This function is unsafe because undefined behavior can result if the 208 /// caller does not ensure all of the following: 209 /// 210 /// * `bytes` must denote a valid pointer to a block of memory. 211 /// 212 /// * `bytes` must pointer to at least the number of bytes returned by 213 /// `max_size()`. 214 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8; 215 } 216 217 /// A trait for values that provide deserialization from buffers of bytes. 218 /// 219 /// # Example 220 /// 221 /// ```ignore 222 /// use peek_poke::Peek; 223 /// 224 /// struct Bar { 225 /// a: u32, 226 /// b: u8, 227 /// c: i16, 228 /// } 229 /// 230 /// ... 231 /// 232 /// impl Peek for Bar { 233 /// unsafe fn peek_from(&mut self, bytes: *const u8) -> *const u8 { 234 /// let bytes = self.a.peek_from(bytes); 235 /// let bytes = self.b.peek_from(bytes); 236 /// self.c.peek_from(bytes) 237 /// } 238 /// } 239 /// ``` 240 /// 241 /// # Safety 242 /// 243 /// The `Peek` trait contains unsafe methods for the following reasons, and 244 /// implementors must ensure that they adhere to these contracts: 245 /// 246 /// * Callers of this trait are expected to rely on the contract defined on each 247 /// method, and implementors must ensure that `peek_from()` doesn't read more 248 /// bytes from `bytes` than is returned by `Peek::max_size()`. 249 pub trait Peek: Poke { 250 /// Deserialize from the buffer pointed to by `bytes`. 251 /// 252 /// Returns a pointer to the next byte after the unconsumed bytes not used 253 /// to deserialize the representation of `Self`. 254 /// 255 /// # Safety 256 /// 257 /// This function is unsafe because undefined behavior can result if the 258 /// caller does not ensure all of the following: 259 /// 260 /// * `bytes` must denote a valid pointer to a block of memory. 261 /// 262 /// * `bytes` must pointer to at least the number of bytes returned by 263 /// `Poke::max_size()`. 264 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8; 265 } 266 267 macro_rules! impl_poke_for_deref { 268 (<$($desc:tt)+) => { 269 unsafe impl <$($desc)+ { 270 #[inline(always)] 271 fn max_size() -> usize { 272 <T>::max_size() 273 } 274 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 275 (**self).poke_into(bytes) 276 } 277 } 278 } 279 } 280 281 impl_poke_for_deref!(<'a, T: Poke> Poke for &'a T); 282 impl_poke_for_deref!(<'a, T: Poke> Poke for &'a mut T); 283 284 macro_rules! impl_for_primitive { 285 ($($ty:ty)+) => { 286 $(unsafe impl Poke for $ty { 287 #[inline(always)] 288 fn max_size() -> usize { 289 size_of::<Self>() 290 } 291 #[inline(always)] 292 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 293 write_verbatim(*self, bytes) 294 } 295 } 296 impl Peek for $ty { 297 #[inline(always)] 298 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 { 299 read_verbatim(bytes, output) 300 } 301 })+ 302 }; 303 } 304 305 impl_for_primitive! { 306 i8 i16 i32 i64 isize 307 u8 u16 u32 u64 usize 308 f32 f64 309 } 310 311 unsafe impl Poke for bool { 312 #[inline(always)] 313 fn max_size() -> usize { 314 u8::max_size() 315 } 316 #[inline] 317 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 318 (*self as u8).poke_into(bytes) 319 } 320 } 321 322 impl Peek for bool { 323 #[inline] 324 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 { 325 let mut int_bool = 0u8; 326 let ptr = <u8>::peek_from(bytes, &mut int_bool); 327 *output = int_bool != 0; 328 ptr 329 } 330 } 331 332 unsafe impl<T> Poke for PhantomData<T> { 333 #[inline(always)] 334 fn max_size() -> usize { 335 0 336 } 337 #[inline(always)] 338 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 339 bytes 340 } 341 } 342 343 impl<T> Peek for PhantomData<T> { 344 #[inline(always)] 345 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 { 346 *output = PhantomData; 347 bytes 348 } 349 } 350 351 unsafe impl<T: Poke> Poke for Option<T> { 352 #[inline(always)] 353 fn max_size() -> usize { 354 u8::max_size() + T::max_size() 355 } 356 357 #[inline] 358 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 359 match self { 360 None => 0u8.poke_into(bytes), 361 Some(ref v) => { 362 let bytes = 1u8.poke_into(bytes); 363 v.poke_into(bytes) 364 } 365 } 366 } 367 } 368 369 impl<T: Default + Peek> Peek for Option<T> { 370 #[inline] 371 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 { 372 let (variant, bytes) = peek_from_default::<u8>(bytes); 373 match variant { 374 0 => { 375 *output = None; 376 bytes 377 } 378 1 => { 379 let (val, bytes) = peek_from_default(bytes); 380 *output = Some(val); 381 bytes 382 } 383 _ => unreachable!(), 384 } 385 } 386 } 387 388 macro_rules! impl_for_arrays { 389 ($($len:tt)+) => { 390 $(unsafe impl<T: Poke> Poke for [T; $len] { 391 fn max_size() -> usize { 392 $len * T::max_size() 393 } 394 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 395 self.iter().fold(bytes, |bytes, e| e.poke_into(bytes)) 396 } 397 } 398 impl<T: Peek> Peek for [T; $len] { 399 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 { 400 (&mut *output).iter_mut().fold(bytes, |bytes, e| <T>::peek_from(bytes, e)) 401 } 402 })+ 403 } 404 } 405 406 impl_for_arrays! { 407 1 2 3 4 5 6 7 8 9 10 408 11 12 13 14 15 16 17 18 19 20 409 21 22 23 24 25 26 27 28 29 30 410 31 32 411 } 412 413 unsafe impl Poke for () { 414 fn max_size() -> usize { 415 0 416 } 417 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 418 bytes 419 } 420 } 421 impl Peek for () { 422 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 { 423 *output = (); 424 bytes 425 } 426 } 427 428 macro_rules! impl_for_tuple { 429 ($($n:tt: $ty:ident),+) => { 430 unsafe impl<$($ty: Poke),+> Poke for ($($ty,)+) { 431 #[inline(always)] 432 fn max_size() -> usize { 433 0 $(+ <$ty>::max_size())+ 434 } 435 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 { 436 $(let bytes = self.$n.poke_into(bytes);)+ 437 bytes 438 } 439 } 440 impl<$($ty: Peek),+> Peek for ($($ty,)+) { 441 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 { 442 $(let bytes = $ty::peek_from(bytes, &mut (*output).$n);)+ 443 bytes 444 } 445 } 446 } 447 } 448 449 impl_for_tuple!(0: A); 450 impl_for_tuple!(0: A, 1: B); 451 impl_for_tuple!(0: A, 1: B, 2: C); 452 impl_for_tuple!(0: A, 1: B, 2: C, 3: D); 453 impl_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E);