#![deny(warnings)]
#![cfg_attr(not(feature = "std"), no_std)]
#![feature(proc_macro)]
extern crate bitrange_plugin;
pub use bitrange_plugin::proc_default_mask;
pub use bitrange_plugin::proc_default_value;
pub use bitrange_plugin::proc_mask;
pub use bitrange_plugin::proc_offset;
#[cfg(feature = "panic")]
mod error {
#[cfg(feature = "std")]
use std::marker::PhantomData;
#[cfg(feature = "std")]
use std::fmt::Binary;
#[cfg(not(feature = "std"))]
use core::marker::PhantomData;
#[cfg(not(feature = "std"))]
use core::fmt::Binary;
#[derive(Debug)]
pub struct Error<T> { _phantomdata: PhantomData<T> }
impl<T> Error<T> where T : Binary {
pub fn invalid_bits(expected: T, provided: T) -> Error<T> {
panic!("Invalid bits, expected 0b{:0b}, got 0b{:0b}", expected, provided);
}
}
}
#[cfg(not(feature = "panic"))]
mod error {
#[derive(Debug)]
pub struct Error<T> {
pub expected: T,
pub provided: T,
}
impl<T> Error<T> {
pub fn invalid_bits(expected: T, provided: T) -> Error<T> {
Error {
expected,
provided,
}
}
}
}
pub use error::Error;
#[macro_export]
macro_rules! bitrange {
(
$struct_name:ident:
$struct_size:ty,
$format:tt,
$(
$field_format:ident:
$(
$field_name:ident
)+
),+
) => {
pub struct $struct_name {
#[allow(dead_code)]
bits: $struct_size
}
impl Default for $struct_name {
#[allow(dead_code)]
fn default() -> $struct_name {
const DEFAULT_VALUE: $struct_size = ::bitrange::proc_default_value!($format);
$struct_name {
bits: DEFAULT_VALUE
}
}
}
impl $struct_name {
#[allow(dead_code)]
pub fn from(bits: $struct_size) -> Result<$struct_name, ::bitrange::Error<$struct_size>> {
#[allow(dead_code)]
const DEFAULT_VALUE: $struct_size = ::bitrange::proc_default_value!($format);
#[allow(dead_code)]
const DEFAULT_MASK: $struct_size = ::bitrange::proc_default_mask!($format);
if bits & DEFAULT_MASK == DEFAULT_VALUE {
Ok($struct_name {
bits
})
} else {
Err(::bitrange::Error::invalid_bits(DEFAULT_VALUE, bits & DEFAULT_MASK))
}
}
}
$(
bitrange_impl_field!(
$struct_name,
$struct_size,
$format,
$field_format,
$($field_name),+
);
)+
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! bitrange_impl_field {
($struct_name:ident, $struct_size:ty, $format:tt, $field_format:ident, $field_get:ident) => {
impl $struct_name {
pub fn $field_get(&self) -> $struct_size {
#[allow(dead_code)]
const MASK: $struct_size = ::bitrange::proc_mask!($format, $field_format);
#[allow(dead_code)]
const OFFSET: $struct_size = ::bitrange::proc_offset!($format, $field_format);
(self.bits & MASK) >> OFFSET
}
}
};
(
$struct_name:ident,
$struct_size:ty,
$format:tt,
$field_format:ident,
$field_get:ident,
$field_set:ident
) => {
bitrange_impl_field!(
$struct_name,
$struct_size,
$format,
$field_format,
$field_get
);
impl $struct_name {
pub fn $field_set(&mut self, value: $struct_size) -> &mut Self {
#[allow(dead_code)]
const MASK: $struct_size = ::bitrange::proc_mask!($format, $field_format);
#[allow(dead_code)]
const OFFSET: $struct_size = ::bitrange::proc_offset!($format, $field_format);
self.bits &= !MASK;
self.bits |= (value << OFFSET) & MASK;
self
}
}
};
}