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::*;