feat: container tests
This commit is contained in:
parent
6dc79f7e29
commit
0b1486aeee
3 changed files with 339 additions and 316 deletions
|
@ -25,169 +25,169 @@ use proc_macro2_diagnostics::Diagnostic;
|
||||||
/// you can also call functions from BitFlag trait beacause the new struct implements deref and deref_mut to the underlying type
|
/// you can also call functions from BitFlag trait beacause the new struct implements deref and deref_mut to the underlying type
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn bitflag(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn bitflag(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
|
|
||||||
let structdef: syn::ItemStruct = syn::parse_macro_input!(input as syn::ItemStruct);
|
let structdef: syn::ItemStruct = syn::parse_macro_input!(input as syn::ItemStruct);
|
||||||
// check if the struct has correct shape
|
// check if the struct has correct shape
|
||||||
check_struct(&mut diagnostics, &structdef);
|
check_struct(&mut diagnostics, &structdef);
|
||||||
|
|
||||||
let structname = structdef.ident;
|
let structname = structdef.ident;
|
||||||
let structfields = match &structdef.fields {
|
let structfields = match &structdef.fields {
|
||||||
syn::Fields::Named(f) => f
|
syn::Fields::Named(f) => f
|
||||||
.named
|
.named
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| f.ident.clone().unwrap())
|
.map(|f| f.ident.clone().unwrap())
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
_ => {
|
_ => {
|
||||||
diagnostics.push(
|
diagnostics.push(
|
||||||
syn::Error::new_spanned(
|
syn::Error::new_spanned(
|
||||||
&structdef.fields,
|
&structdef.fields,
|
||||||
"struct has incorrect shape, only works on struct with named fields",
|
"struct has incorrect shape, only works on struct with named fields",
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let vis = structdef.vis.clone();
|
let vis = structdef.vis.clone();
|
||||||
let attrs = structdef.attrs.clone();
|
let attrs = structdef.attrs.clone();
|
||||||
|
|
||||||
// a unsigned int type of a size larger then the number of fields in the struct
|
// a unsigned int type of a size larger then the number of fields in the struct
|
||||||
let u_type = {
|
let u_type = {
|
||||||
let fields_len = structfields.len();
|
let fields_len = structfields.len();
|
||||||
match fields_len {
|
match fields_len {
|
||||||
0..=8 => quote::quote! { u8 },
|
0..=8 => quote::quote! { u8 },
|
||||||
9..=16 => quote::quote! { u16 },
|
9..=16 => quote::quote! { u16 },
|
||||||
17..=32 => quote::quote! { u32 },
|
17..=32 => quote::quote! { u32 },
|
||||||
33..=64 => quote::quote! { u64 },
|
33..=64 => quote::quote! { u64 },
|
||||||
65..=128 => quote::quote! { u128 },
|
65..=128 => quote::quote! { u128 },
|
||||||
_ => {
|
_ => {
|
||||||
diagnostics.push(
|
diagnostics.push(
|
||||||
syn::Error::new_spanned(structdef.fields, "struct has too many fields").into(),
|
syn::Error::new_spanned(structdef.fields, "struct has too many fields").into(),
|
||||||
);
|
);
|
||||||
quote::quote! { u128 }
|
quote::quote! { u128 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let newstruct = quote::quote! {
|
let newstruct = quote::quote! {
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#vis struct #structname {
|
#vis struct #structname {
|
||||||
value: #u_type
|
value: #u_type
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// make functions for each field in the struct
|
// make functions for each field in the struct
|
||||||
let mut functions = Vec::new();
|
let mut functions = Vec::new();
|
||||||
for (i, field) in structfields.iter().enumerate() {
|
for (i, field) in structfields.iter().enumerate() {
|
||||||
let field = field.clone();
|
let field = field.clone();
|
||||||
let i = i as u8;
|
let i = i as u8;
|
||||||
let set_ident = syn::Ident::new(&format!("set_{}", field), field.span());
|
let set_ident = syn::Ident::new(&format!("set_{}", field), field.span());
|
||||||
functions.push(quote::quote! {
|
functions.push(quote::quote! {
|
||||||
pub fn #field(&self) -> bool {
|
pub fn #field(&self) -> bool {
|
||||||
self.value.get_flag(#i)
|
self.value.get_flag(#i)
|
||||||
}
|
}
|
||||||
pub fn #set_ident(&mut self, value: bool) {
|
pub fn #set_ident(&mut self, value: bool) {
|
||||||
self.value.set_flag(#i, value);
|
self.value.set_flag(#i, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let impls = quote::quote! {
|
let impls = quote::quote! {
|
||||||
impl #structname {
|
impl #structname {
|
||||||
#(#functions)*
|
#(#functions)*
|
||||||
|
|
||||||
pub fn new(val: #u_type) -> Self {
|
pub fn new(val: #u_type) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: val
|
value: val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value(&self) -> #u_type {
|
pub fn value(&self) -> #u_type {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let deref_impl = quote::quote! {
|
let deref_impl = quote::quote! {
|
||||||
impl std::ops::Deref for #structname {
|
impl std::ops::Deref for #structname {
|
||||||
type Target = #u_type;
|
type Target = #u_type;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.value
|
&self.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let deref_mut_impl = quote::quote! {
|
let deref_mut_impl = quote::quote! {
|
||||||
impl std::ops::DerefMut for #structname {
|
impl std::ops::DerefMut for #structname {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.value
|
&mut self.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let diagnostics = diagnostics.iter().map(|d| d.clone().emit_as_item_tokens());
|
let diagnostics = diagnostics.iter().map(|d| d.clone().emit_as_item_tokens());
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
#(#diagnostics)*
|
#(#diagnostics)*
|
||||||
#newstruct
|
#newstruct
|
||||||
#impls
|
#impls
|
||||||
#deref_impl
|
#deref_impl
|
||||||
#deref_mut_impl
|
#deref_mut_impl
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns true if the struct has a correct shape
|
/// returns true if the struct has a correct shape
|
||||||
fn check_struct(diagnostics: &mut Vec<Diagnostic>, input: &syn::ItemStruct) {
|
fn check_struct(diagnostics: &mut Vec<Diagnostic>, input: &syn::ItemStruct) {
|
||||||
if input.generics.lt_token.is_some() {
|
if input.generics.lt_token.is_some() {
|
||||||
diagnostics.push(
|
diagnostics.push(
|
||||||
syn::Error::new_spanned(&input.generics, "generics not allowed in bitflag structs")
|
syn::Error::new_spanned(&input.generics, "generics not allowed in bitflag structs")
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if input.generics.gt_token.is_some() {
|
if input.generics.gt_token.is_some() {
|
||||||
diagnostics.push(
|
diagnostics.push(
|
||||||
syn::Error::new_spanned(&input.generics, "generics not allowed in bitflag structs")
|
syn::Error::new_spanned(&input.generics, "generics not allowed in bitflag structs")
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if input.generics.where_clause.is_some() {
|
if input.generics.where_clause.is_some() {
|
||||||
diagnostics.push(
|
diagnostics.push(
|
||||||
syn::Error::new_spanned(&input.generics, "generics not allowed in bitflag structs")
|
syn::Error::new_spanned(&input.generics, "generics not allowed in bitflag structs")
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if !input.generics.params.is_empty() {
|
if !input.generics.params.is_empty() {
|
||||||
diagnostics.push(
|
diagnostics.push(
|
||||||
syn::Error::new_spanned(&input.generics, "generics not allowed in bitflag structs")
|
syn::Error::new_spanned(&input.generics, "generics not allowed in bitflag structs")
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
match &input.fields {
|
match &input.fields {
|
||||||
syn::Fields::Unnamed(f) => diagnostics.push(
|
syn::Fields::Unnamed(f) => diagnostics.push(
|
||||||
syn::Error::new_spanned(f, "struct has incorrect shape, found tuple struct").into(),
|
syn::Error::new_spanned(f, "struct has incorrect shape, found tuple struct").into(),
|
||||||
),
|
),
|
||||||
syn::Fields::Unit => diagnostics.push(
|
syn::Fields::Unit => diagnostics.push(
|
||||||
syn::Error::new_spanned(input, "struct has incorrect shape, found unit struct").into(),
|
syn::Error::new_spanned(input, "struct has incorrect shape, found unit struct").into(),
|
||||||
),
|
),
|
||||||
syn::Fields::Named(f) => {
|
syn::Fields::Named(f) => {
|
||||||
if f.named.len() > 128 {
|
if f.named.len() > 128 {
|
||||||
diagnostics.push(syn::Error::new_spanned(f, "struct has too many fields").into());
|
diagnostics.push(syn::Error::new_spanned(f, "struct has too many fields").into());
|
||||||
}
|
}
|
||||||
for field in f.named.iter() {
|
for field in f.named.iter() {
|
||||||
match &field.ty {
|
match &field.ty {
|
||||||
syn::Type::Path(path_type) if path_type.path.is_ident("bool") => {}
|
syn::Type::Path(path_type) if path_type.path.is_ident("bool") => {}
|
||||||
_ => diagnostics.push(
|
_ => diagnostics.push(
|
||||||
syn::Error::new_spanned(
|
syn::Error::new_spanned(
|
||||||
field,
|
field,
|
||||||
"struct has incorrect shape, found non bool field",
|
"struct has incorrect shape, found non bool field",
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
352
src/lib.rs
352
src/lib.rs
|
@ -3,185 +3,187 @@
|
||||||
This crate aims to make working with binary/bit flags easier. It also provides a macro to add similar functionality to zig's packed structs with boolean fields.
|
This crate aims to make working with binary/bit flags easier. It also provides a macro to add similar functionality to zig's packed structs with boolean fields.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
pub use binf_macros::*;
|
pub use binf_macros::*;
|
||||||
|
|
||||||
/// A trait for types that can be used as bit flags.
|
/// A trait for types that can be used as bit flags.
|
||||||
pub trait BitFlag {
|
pub trait BitFlag {
|
||||||
type T;
|
type T;
|
||||||
/// Sets the flag at the given position to the given value.
|
/// Sets the flag at the given position to the given value.
|
||||||
/// I don't know what happens if the position is larger than the number of bits in the type.
|
/// I don't know what happens if the position is larger than the number of bits in the type.
|
||||||
fn set_flag(&mut self, position: u8, value: bool);
|
fn set_flag(&mut self, position: u8, value: bool);
|
||||||
/// Returns the value of the flag at the given position.
|
/// Returns the value of the flag at the given position.
|
||||||
/// I don't know what happens if the position is larger than the number of bits in the type.
|
/// I don't know what happens if the position is larger than the number of bits in the type.
|
||||||
fn get_flag(&self, position: u8) -> bool;
|
fn get_flag(&self, position: u8) -> bool;
|
||||||
/// Returns an array of bools representing the flags.
|
/// Returns an array of bools representing the flags.
|
||||||
/// The first element in the array is the flag at position 0.
|
/// The first element in the array is the flag at position 0.
|
||||||
fn flags(&self) -> Self::T;
|
fn flags(&self) -> Self::T;
|
||||||
/// Sets the flags to the given values.
|
/// Sets the flags to the given values.
|
||||||
/// flags can be any size, but if it is larger than the number of bits in the type only the first bits will be used.
|
/// flags can be any size, but if it is larger than the number of bits in the type only the first bits will be used.
|
||||||
/// So if this is u8 flags should be 8 or less any more are ignored.
|
/// So if this is u8 flags should be 8 or less any more are ignored.
|
||||||
fn set_flags(&mut self, flags: &[bool]);
|
fn set_flags(&mut self, flags: &[bool]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// implementation for u8. u8 means it can store 8 flags 1 flag per bit.
|
/// implementation for u8. u8 means it can store 8 flags 1 flag per bit.
|
||||||
impl BitFlag for u8 {
|
impl BitFlag for u8 {
|
||||||
type T = [bool; 8];
|
type T = [bool; 8];
|
||||||
fn set_flag(&mut self, position: u8, value: bool) {
|
fn set_flag(&mut self, position: u8, value: bool) {
|
||||||
if value {
|
if value {
|
||||||
*self |= 1 << position;
|
*self |= 1 << position;
|
||||||
} else {
|
} else {
|
||||||
*self &= !(1 << position);
|
*self &= !(1 << position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_flag(&self, position: u8) -> bool {
|
fn get_flag(&self, position: u8) -> bool {
|
||||||
(*self & (1 << position)) != 0
|
(*self & (1 << position)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> Self::T {
|
fn flags(&self) -> Self::T {
|
||||||
let mut flags = [false; 8];
|
let mut flags = [false; 8];
|
||||||
for (i, flag) in flags.iter_mut().enumerate() {
|
for (i, flag) in flags.iter_mut().enumerate() {
|
||||||
*flag = self.get_flag(i as u8);
|
*flag = self.get_flag(i as u8);
|
||||||
}
|
}
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flags(&mut self, flags: &[bool]) {
|
fn set_flags(&mut self, flags: &[bool]) {
|
||||||
for (i, v) in flags.iter().enumerate() {
|
for (i, v) in flags.iter().enumerate() {
|
||||||
if i >= 8 {
|
if i >= 8 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self.set_flag(i as u8, *v);
|
self.set_flag(i as u8, *v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitFlag for u16 {
|
impl BitFlag for u16 {
|
||||||
type T = [bool; 16];
|
type T = [bool; 16];
|
||||||
fn set_flag(&mut self, position: u8, value: bool) {
|
fn set_flag(&mut self, position: u8, value: bool) {
|
||||||
if value {
|
if value {
|
||||||
*self |= 1 << position;
|
*self |= 1 << position;
|
||||||
} else {
|
} else {
|
||||||
*self &= !(1 << position);
|
*self &= !(1 << position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_flag(&self, position: u8) -> bool {
|
fn get_flag(&self, position: u8) -> bool {
|
||||||
(*self & (1 << position)) != 0
|
(*self & (1 << position)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> Self::T {
|
fn flags(&self) -> Self::T {
|
||||||
let mut flags = [false; 16];
|
let mut flags = [false; 16];
|
||||||
for (i, flag) in flags.iter_mut().enumerate() {
|
for (i, flag) in flags.iter_mut().enumerate() {
|
||||||
*flag = self.get_flag(i as u8);
|
*flag = self.get_flag(i as u8);
|
||||||
}
|
}
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flags(&mut self, flags: &[bool]) {
|
fn set_flags(&mut self, flags: &[bool]) {
|
||||||
for (i, v) in flags.iter().enumerate() {
|
for (i, v) in flags.iter().enumerate() {
|
||||||
if i >= 16 {
|
if i >= 16 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self.set_flag(i as u8, *v);
|
self.set_flag(i as u8, *v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitFlag for u32 {
|
impl BitFlag for u32 {
|
||||||
type T = [bool; 32];
|
type T = [bool; 32];
|
||||||
fn set_flag(&mut self, position: u8, value: bool) {
|
fn set_flag(&mut self, position: u8, value: bool) {
|
||||||
if value {
|
if value {
|
||||||
*self |= 1 << position;
|
*self |= 1 << position;
|
||||||
} else {
|
} else {
|
||||||
*self &= !(1 << position);
|
*self &= !(1 << position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_flag(&self, position: u8) -> bool {
|
fn get_flag(&self, position: u8) -> bool {
|
||||||
(*self & (1 << position)) != 0
|
(*self & (1 << position)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> Self::T {
|
fn flags(&self) -> Self::T {
|
||||||
let mut flags = [false; 32];
|
let mut flags = [false; 32];
|
||||||
for (i, flag) in flags.iter_mut().enumerate() {
|
for (i, flag) in flags.iter_mut().enumerate() {
|
||||||
*flag = self.get_flag(i as u8);
|
*flag = self.get_flag(i as u8);
|
||||||
}
|
}
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flags(&mut self, flags: &[bool]) {
|
fn set_flags(&mut self, flags: &[bool]) {
|
||||||
for (i, v) in flags.iter().enumerate() {
|
for (i, v) in flags.iter().enumerate() {
|
||||||
if i >= 32 {
|
if i >= 32 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self.set_flag(i as u8, *v);
|
self.set_flag(i as u8, *v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitFlag for u64 {
|
impl BitFlag for u64 {
|
||||||
type T = [bool; 64];
|
type T = [bool; 64];
|
||||||
fn set_flag(&mut self, position: u8, value: bool) {
|
fn set_flag(&mut self, position: u8, value: bool) {
|
||||||
if value {
|
if value {
|
||||||
*self |= 1 << position;
|
*self |= 1 << position;
|
||||||
} else {
|
} else {
|
||||||
*self &= !(1 << position);
|
*self &= !(1 << position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_flag(&self, position: u8) -> bool {
|
fn get_flag(&self, position: u8) -> bool {
|
||||||
(*self & (1 << position)) != 0
|
(*self & (1 << position)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> Self::T {
|
fn flags(&self) -> Self::T {
|
||||||
let mut flags = [false; 64];
|
let mut flags = [false; 64];
|
||||||
for (i, flag) in flags.iter_mut().enumerate() {
|
for (i, flag) in flags.iter_mut().enumerate() {
|
||||||
*flag = self.get_flag(i as u8);
|
*flag = self.get_flag(i as u8);
|
||||||
}
|
}
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flags(&mut self, flags: &[bool]) {
|
fn set_flags(&mut self, flags: &[bool]) {
|
||||||
for (i, v) in flags.iter().enumerate() {
|
for (i, v) in flags.iter().enumerate() {
|
||||||
if i >= 64 {
|
if i >= 64 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self.set_flag(i as u8, *v);
|
self.set_flag(i as u8, *v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitFlag for u128 {
|
impl BitFlag for u128 {
|
||||||
type T = [bool; 128];
|
type T = [bool; 128];
|
||||||
fn set_flag(&mut self, position: u8, value: bool) {
|
fn set_flag(&mut self, position: u8, value: bool) {
|
||||||
if value {
|
if value {
|
||||||
*self |= 1 << position;
|
*self |= 1 << position;
|
||||||
} else {
|
} else {
|
||||||
*self &= !(1 << position);
|
*self &= !(1 << position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_flag(&self, position: u8) -> bool {
|
fn get_flag(&self, position: u8) -> bool {
|
||||||
(*self & (1 << position)) != 0
|
(*self & (1 << position)) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> Self::T {
|
fn flags(&self) -> Self::T {
|
||||||
let mut flags = [false; 128];
|
let mut flags = [false; 128];
|
||||||
for (i, flag) in flags.iter_mut().enumerate() {
|
for (i, flag) in flags.iter_mut().enumerate() {
|
||||||
*flag = self.get_flag(i as u8);
|
*flag = self.get_flag(i as u8);
|
||||||
}
|
}
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flags(&mut self, flags: &[bool]) {
|
fn set_flags(&mut self, flags: &[bool]) {
|
||||||
for (i, v) in flags.iter().enumerate() {
|
for (i, v) in flags.iter().enumerate() {
|
||||||
if i >= 128 {
|
if i >= 128 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self.set_flag(i as u8, *v);
|
self.set_flag(i as u8, *v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper around a type that implements BitFlag. In case you don't want to import the trait and
|
/// A wrapper around a type that implements BitFlag. In case you don't want to import the trait and
|
||||||
|
@ -189,32 +191,46 @@ impl BitFlag for u128 {
|
||||||
pub struct BitFlags<T>(T);
|
pub struct BitFlags<T>(T);
|
||||||
|
|
||||||
impl<T: BitFlag> BitFlags<T> {
|
impl<T: BitFlag> BitFlags<T> {
|
||||||
pub fn new(value: T) -> Self {
|
pub fn new(value: T) -> Self {
|
||||||
Self(value)
|
Self(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the flag at the given position to the given value.
|
/// Sets the flag at the given position to the given value.
|
||||||
/// I don't know what happens if the position is larger than the number of bits in the type.
|
/// I don't know what happens if the position is larger than the number of bits in the type.
|
||||||
pub fn set_flag(&mut self, position: u8, value: bool) {
|
pub fn set_flag(&mut self, position: u8, value: bool) {
|
||||||
self.0.set_flag(position, value);
|
self.0.set_flag(position, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value of the flag at the given position.
|
/// Returns the value of the flag at the given position.
|
||||||
/// I don't know what happens if the position is larger than the number of bits in the type.
|
/// I don't know what happens if the position is larger than the number of bits in the type.
|
||||||
pub fn get_flag(&self, position: u8) -> bool {
|
pub fn get_flag(&self, position: u8) -> bool {
|
||||||
self.0.get_flag(position)
|
self.0.get_flag(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an array of bools representing the flags.
|
/// Returns an array of bools representing the flags.
|
||||||
/// The first element in the array is the flag at position 0.
|
/// The first element in the array is the flag at position 0.
|
||||||
pub fn flags(&self) -> T::T {
|
pub fn flags(&self) -> T::T {
|
||||||
self.0.flags()
|
self.0.flags()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the flags to the given values.
|
/// Sets the flags to the given values.
|
||||||
/// flags can be any size, but if it is larger than the number of bits in the type only the first bits will be used.
|
/// flags can be any size, but if it is larger than the number of bits in the type only the first bits will be used.
|
||||||
/// So if this is u8 flags should be 8 or less any more are ignored.
|
/// So if this is u8 flags should be 8 or less any more are ignored.
|
||||||
pub fn set_flags(&mut self, flags: &[bool]) {
|
pub fn set_flags(&mut self, flags: &[bool]) {
|
||||||
self.0.set_flags(flags);
|
self.0.set_flags(flags);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: BitFlag> Deref for BitFlags<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: BitFlag> DerefMut for BitFlags<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
7
tests/container.rs
Normal file
7
tests/container.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use binf::BitFlags;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn standalone() {
|
||||||
|
let flags = BitFlags::<u8>::new(0b10101010);
|
||||||
|
assert_eq!(*flags, 0b10101010);
|
||||||
|
}
|
Loading…
Reference in a new issue