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 124 125 126 127 128 129 130 131 132 133 134 135 136 137
//! 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() {} //! //! ``` //! //! # Comparison to [`pod`](https://crates.io/crates/pod) //! //! [`pod`](https://crates.io/crates/pod) is another crate created to help working with plain data. //! The major difference between `pod` and `plain` is scope. //! //! `plain` currently provides only four functions (+method wrappers) and its implementation involves //! mere six lines of unsafe code. It can be used in `no_std` code. Also, it doesn't //! deal with [endianness](https://en.wikipedia.org/wiki/Endianness) in any way, //! so it is only suitable for certain kinds of low-level work. //! //! `pod`, on the other hand, provides a wide arsenal //! of various methods, most of which may be unnecessary for a given use case. //! It has dependencies on `std` as well as other crates, but among other things //! it provides tools to handle endianness properly. //! //! In short, `plain` is much, much _plainer_... #![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::*;