safe_transmute/
bool.rs

1//! Functions for safe transmutation to `bool`.
2//!
3//! Transmuting to `bool` is not undefined behavior if the transmuted value is
4//! either 0 or 1. These functions will return an error if the integer value
5//! behind the `bool` value is neither one.
6//!
7//! # Note
8//!
9//! Currently, these functions only work on systems in which the size of `bool`
10//! is exactly 1 (which are all platforms supported by Rust at the time of
11//! writing). In the event that you find a platform with an unexpected `bool`
12//! size, please report at the project's
13//! [issue tracker](https://github.com/nabijaczleweli/safe-transmute-rs/issues/new).
14
15
16use self::super::guard::{PermissiveGuard, PedanticGuard, Guard};
17use self::super::base::transmute_many;
18#[cfg(feature = "alloc")]
19use self::super::base::transmute_vec;
20use core::mem::transmute;
21use self::super::Error;
22#[cfg(feature = "alloc")]
23use alloc::vec::Vec;
24
25
26/// Makes sure that the bytes represent a sequence of valid boolean values.
27///
28/// # Examples
29///
30/// ```
31/// # use safe_transmute::bool::bytes_are_bool;
32/// assert!(bytes_are_bool(&[false as u8, true as u8]));
33///
34/// assert!(!bytes_are_bool(&[(false as u8 + true as u8) * 2]));
35/// ```
36#[inline]
37pub fn bytes_are_bool(v: &[u8]) -> bool {
38    let _bool_must_be_1_byte_pls_report = transmute::<bool, u8>;
39
40    v.iter().cloned().all(byte_is_bool)
41}
42
43#[inline]
44fn byte_is_bool(b: u8) -> bool {
45    unsafe { b == transmute::<_, u8>(false) || b == transmute::<_, u8>(true) }
46}
47
48fn transmute_bool<G: Guard>(bytes: &[u8]) -> Result<&[bool], Error<u8, bool>> {
49    check_bool(bytes)?;
50    unsafe { transmute_many::<_, G>(bytes) }
51}
52
53/// Helper function for returning an error if any of the bytes does not make a
54/// valid `bool`.
55fn check_bool<'a, T>(bytes: &[u8]) -> Result<(), Error<'a, u8, T>> {
56    if bytes_are_bool(bytes) {
57        Ok(())
58    } else {
59        Err(Error::InvalidValue)
60    }
61}
62
63
64/// View a byte slice as a slice of boolean values.
65///
66/// The resulting slice will have as many instances of `bool` as will fit, can be empty.
67///
68/// # Examples
69///
70/// ```
71/// # use safe_transmute::{Error, transmute_bool_permissive};
72/// # fn run() -> Result<(), Error<'static, u8, bool>> {
73/// assert_eq!(transmute_bool_permissive(&[0x00, 0x01, 0x00, 0x01])?,
74///            &[false, true, false, true]);
75/// assert_eq!(transmute_bool_permissive(&[])?, &[]);
76/// # Ok(())
77/// # }
78/// # run().unwrap()
79/// ```
80pub fn transmute_bool_permissive(bytes: &[u8]) -> Result<&[bool], Error<u8, bool>> {
81    transmute_bool::<PermissiveGuard>(bytes)
82}
83
84/// View a byte slice as a slice of boolean values.
85///
86/// The byte slice must have at least enough bytes to fill a single `bool`.
87///
88/// # Examples
89///
90/// ```
91/// # use safe_transmute::{Error, transmute_bool_pedantic};
92/// # fn run() -> Result<(), Error<'static, u8, bool>> {
93/// assert_eq!(transmute_bool_pedantic(&[0x01, 0x01, 0x01, 0x01])?,
94///            &[true, true, true, true]);
95/// assert!(transmute_bool_pedantic(&[]).is_err());
96/// # Ok(())
97/// # }
98/// # run().unwrap()
99/// ```
100pub fn transmute_bool_pedantic(bytes: &[u8]) -> Result<&[bool], Error<u8, bool>> {
101    transmute_bool::<PedanticGuard>(bytes)
102}
103
104/// Trasform a byte vector into a vector of bool.
105///
106/// The vector's allocated byte buffer will be reused when possible.
107///
108/// # Examples
109///
110/// ```
111/// # use safe_transmute::{Error, transmute_bool_vec_permissive};
112/// # fn run() -> Result<(), Error<'static, u8, bool>> {
113/// assert_eq!(transmute_bool_vec_permissive(vec![0x00, 0x01, 0x00, 0x01])?,
114///            vec![false, true, false, true]);
115/// assert_eq!(transmute_bool_vec_permissive(vec![0x01, 0x00, 0x00, 0x00, 0x01])?,
116///            vec![true, false, false, false, true]);
117/// assert_eq!(transmute_bool_vec_permissive(vec![]), Ok(vec![]));
118/// # Ok(())
119/// # }
120/// # run().unwrap()
121/// ```
122#[cfg(feature = "alloc")]
123pub fn transmute_bool_vec_permissive(bytes: Vec<u8>) -> Result<Vec<bool>, Error<'static, u8, bool>> {
124    check_bool(&bytes)?;
125    PermissiveGuard::check::<u8>(&bytes)?;
126    // Alignment guarantees are ensured, and all values have been checked,
127    // so the conversion is safe.
128    unsafe { Ok(transmute_vec::<u8, bool>(bytes)) }
129}
130
131/// Transform a byte vector into a vector of bool.
132///
133/// The vector's allocated byte buffer will be reused when possible, and
134/// should not be empty.
135///
136/// # Examples
137///
138/// ```
139/// # use safe_transmute::{Error, transmute_bool_vec_pedantic};
140/// # fn run() -> Result<(), Error<'static, u8, bool>> {
141/// assert_eq!(transmute_bool_vec_pedantic(vec![0x00, 0x01, 0x00, 0x01])?,
142///            vec![false, true, false, true]);
143///
144/// assert!(transmute_bool_vec_pedantic(vec![]).is_err());
145///
146/// assert!(transmute_bool_vec_pedantic(vec![0x04, 0x00, 0xED]).is_err());
147/// # Ok(())
148/// # }
149/// # run().unwrap()
150/// ```
151#[cfg(feature = "alloc")]
152pub fn transmute_bool_vec_pedantic(bytes: Vec<u8>) -> Result<Vec<bool>, Error<'static, u8, bool>> {
153    check_bool(&bytes)?;
154    PedanticGuard::check::<u8>(&bytes)?;
155
156    // alignment guarantees are ensured, and all values have been checked,
157    // so the conversion is safe.
158    unsafe { Ok(transmute_vec::<u8, bool>(bytes)) }
159}