1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
//! A small Rust library that allows users to reinterpret data of certain types safely. //! //! This crate provides an unsafe trait [`Plain`](trait.Plain.html), which the user //! of the crate uses to mark types for which operations of this library are safe. //! See [`Plain`](trait.Plain.html) for the contractual obligation. //! //! Other than that, everything else in this crate is perfectly safe to use as long //! as the `Plain` trait is not implemented on inadmissible types (similar to how //! `Send` and `Sync` in the standard library work). //! //! //! //! # Examples //! //! To start using the crate, simply do `extern crate plain;`. //! //! If you want your plain types to have methods from this crate, also include `use plain.Methods;`. //! //! Then it's just a matter of marking the right types and using them. //! //! ``` //! //! extern crate plain; //! use plain::Methods; //! //! //! //! #[repr(C)] //! #[derive(Default)] //! struct ELF64Header { //! pub e_ident: [u8; 16], //! pub e_type: u16, //! pub e_machine: u16, //! pub e_version: u32, //! pub e_entry: u64, //! pub e_phoff: u64, //! pub e_shoff: u64, //! pub e_flags: u32, //! pub e_ehsize: u16, //! pub e_phentsize: u16, //! pub e_phnum: u16, //! pub e_shentsize: u16, //! pub e_shnum: u16, //! pub e_shstrndx: u16, //! } //! //! // SAFE: ELF64Header satisfies all the requirements of `Plain`. //! unsafe impl plain::Plain for ELF64Header {} //! //! fn reinterpret_buffer(buf: &[u8]) -> &ELF64Header { //! match plain::from_bytes(buf) { //! Err(_) => panic!("The buffer is either too short or not aligned!"), //! Ok(elfref) => elfref, //! } //! } //! //! fn copy_from_buffer(buf: &[u8]) -> ELF64Header { //! let mut h = ELF64Header::default(); //! h.as_mut_bytes().copy_from_slice(buf); //! h //! } //! //! #[repr(C)] //! struct ArrayEntry { //! pub name: [u8; 64], //! pub tag: u32, //! pub score: u32, //! } //! //! // SAFE: ArrayEntry satisfies all the requirements of `Plain`. //! unsafe impl plain::Plain for ArrayEntry {} //! //! fn array_from_bytes(buf: &[u8]) -> &[ArrayEntry] { //! // NOTE: length is not a concern here, //! // since from_bytes() can return empty slice. //! //! match plain::from_bytes(buf) { //! Err(_) => panic!("The buffer is not aligned!"), //! Ok(arr) => arr, //! } //! } //! //! # fn main() {} //! //! ``` //! #![no_std] #[cfg(test)] #[macro_use] extern crate std; /// A trait for plain reinterpretable data. /// /// A type can be [`Plain`](trait.Plain.html) if it is `#repr(C)` and only contains /// data with no possible invalid values. Specifically, /// `bool`, `char`, `enum`s, tuples, pointers and references are not /// `Plain`. On the other hand, arrays of a `Plain` type, and /// structures where all members are plain, are usually okay. /// pub unsafe trait Plain {} unsafe impl Plain for u8 {} unsafe impl Plain for u16 {} unsafe impl Plain for u32 {} unsafe impl Plain for u64 {} unsafe impl Plain for usize {} unsafe impl Plain for i8 {} unsafe impl Plain for i16 {} unsafe impl Plain for i32 {} unsafe impl Plain for i64 {} unsafe impl Plain for isize {} // TODO: check if floats are valid for every bit sequence. // unsafe impl Plain for f32 {} // unsafe impl Plain for f64 {} unsafe impl<S> Plain for [S] where S: Plain {} mod methods; pub use self::methods::*;