Skip to content

Commit

Permalink
Add bitfield implementations for flag-type enums
Browse files Browse the repository at this point in the history
  • Loading branch information
dcoles committed Jan 26, 2025
1 parent b206567 commit 09cd6f8
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 29 deletions.
12 changes: 6 additions & 6 deletions crates/flipperzero/src/furi/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use alloc::{
sync::Arc,
};

use flipperzero_sys::{self as sys, FuriFlagNoClear, FuriFlagWaitAll, FuriFlagWaitAny};
use flipperzero_sys::{self as sys, FuriFlagNoClear, FuriFlagWaitAll, FuriFlagWaitAny, HasFlag};

use crate::furi::time::Duration;

Expand Down Expand Up @@ -259,7 +259,7 @@ impl ThreadId {
pub fn set_flags(thread_id: ThreadId, flags: u32) -> Result<u32, sys::furi::Status> {
let result = unsafe { sys::furi_thread_flags_set(thread_id.0, flags) };

if result & sys::FuriFlagError.0 != 0 {
if sys::FuriFlag(result).has_flag(sys::FuriFlagError) {
return Err((result as i32).into());
}

Expand All @@ -272,7 +272,7 @@ pub fn set_flags(thread_id: ThreadId, flags: u32) -> Result<u32, sys::furi::Stat
pub fn clear_flags(flags: u32) -> Result<u32, sys::furi::Status> {
let result = unsafe { sys::furi_thread_flags_clear(flags) };

if result & sys::FuriFlagError.0 != 0 {
if sys::FuriFlag(result).has_flag(sys::FuriFlagError) {
return Err((result as i32).into());
}

Expand All @@ -283,7 +283,7 @@ pub fn clear_flags(flags: u32) -> Result<u32, sys::furi::Status> {
pub fn get_flags() -> Result<u32, sys::furi::Status> {
let result = unsafe { sys::furi_thread_flags_get() };

if result & sys::FuriFlagError.0 != 0 {
if sys::FuriFlag(result).has_flag(sys::FuriFlagError) {
return Err((result as i32).into());
}

Expand All @@ -301,7 +301,7 @@ pub fn wait_any_flags(
let options = FuriFlagWaitAny.0 | (if clear { 0 } else { FuriFlagNoClear.0 });
let result = unsafe { sys::furi_thread_flags_wait(flags, options, timeout.0) };

if result & sys::FuriFlagError.0 != 0 {
if sys::FuriFlag(result).has_flag(sys::FuriFlagError) {
return Err((result as i32).into());
}

Expand All @@ -319,7 +319,7 @@ pub fn wait_all_flags(
let options = FuriFlagWaitAll.0 | (if clear { 0 } else { FuriFlagNoClear.0 });
let result = unsafe { sys::furi_thread_flags_wait(flags, options, timeout.0) };

if result & sys::FuriFlagError.0 != 0 {
if sys::FuriFlag(result).has_flag(sys::FuriFlagError) {
return Err((result as i32).into());
}

Expand Down
46 changes: 23 additions & 23 deletions crates/flipperzero/src/storage.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
use core::ffi::{c_char, c_void, CStr};
use core::ptr::NonNull;

use flipperzero_sys as sys;
use flipperzero_sys::furi::UnsafeRecord;
use flipperzero_sys::{self as sys, HasFlag};

use crate::io::*;

#[derive(Debug, Default, Clone, Copy)]
pub struct OpenOptions {
access_mode: u8,
open_mode: u8,
access_mode: sys::FS_AccessMode,
open_mode: sys::FS_OpenMode,
}

impl OpenOptions {
pub fn new() -> Self {
Self::default()
}

fn from_parts(access_mode: u8, open_mode: u8) -> Self {
fn from_parts(access_mode: sys::FS_AccessMode, open_mode: sys::FS_OpenMode) -> Self {
OpenOptions {
access_mode,
open_mode,
Expand All @@ -28,9 +28,9 @@ impl OpenOptions {
pub fn read(self, set: bool) -> Self {
OpenOptions::from_parts(
if set {
self.access_mode | sys::FSAM_READ.0
self.access_mode | sys::FSAM_READ
} else {
self.access_mode & !sys::FSAM_READ.0
self.access_mode & !sys::FSAM_READ
},
self.open_mode,
)
Expand All @@ -40,9 +40,9 @@ impl OpenOptions {
pub fn write(self, set: bool) -> Self {
OpenOptions::from_parts(
if set {
self.access_mode | sys::FSAM_WRITE.0
self.access_mode | sys::FSAM_WRITE
} else {
self.access_mode & !sys::FSAM_WRITE.0
self.access_mode & !sys::FSAM_WRITE
},
self.open_mode,
)
Expand All @@ -53,9 +53,9 @@ impl OpenOptions {
OpenOptions::from_parts(
self.access_mode,
if set {
self.open_mode | sys::FSOM_OPEN_EXISTING.0
self.open_mode | sys::FSOM_OPEN_EXISTING
} else {
self.open_mode & !sys::FSOM_OPEN_EXISTING.0
self.open_mode & !sys::FSOM_OPEN_EXISTING
},
)
}
Expand All @@ -65,9 +65,9 @@ impl OpenOptions {
OpenOptions::from_parts(
self.access_mode,
if set {
self.open_mode | sys::FSOM_OPEN_ALWAYS.0
self.open_mode | sys::FSOM_OPEN_ALWAYS
} else {
self.open_mode & !sys::FSOM_OPEN_ALWAYS.0
self.open_mode & !sys::FSOM_OPEN_ALWAYS
},
)
}
Expand All @@ -77,9 +77,9 @@ impl OpenOptions {
OpenOptions::from_parts(
self.access_mode,
if set {
self.open_mode | sys::FSOM_OPEN_APPEND.0
self.open_mode | sys::FSOM_OPEN_APPEND
} else {
self.open_mode & !sys::FSOM_OPEN_APPEND.0
self.open_mode & !sys::FSOM_OPEN_APPEND
},
)
}
Expand All @@ -89,9 +89,9 @@ impl OpenOptions {
OpenOptions::from_parts(
self.access_mode,
if set {
self.open_mode | sys::FSOM_CREATE_NEW.0
self.open_mode | sys::FSOM_CREATE_NEW
} else {
self.open_mode & !sys::FSOM_CREATE_NEW.0
self.open_mode & !sys::FSOM_CREATE_NEW
},
)
}
Expand All @@ -101,9 +101,9 @@ impl OpenOptions {
OpenOptions::from_parts(
self.access_mode,
if set {
self.open_mode | sys::FSOM_CREATE_ALWAYS.0
self.open_mode | sys::FSOM_CREATE_ALWAYS
} else {
self.open_mode & !sys::FSOM_CREATE_ALWAYS.0
self.open_mode & !sys::FSOM_CREATE_ALWAYS
},
)
}
Expand All @@ -115,13 +115,13 @@ impl OpenOptions {
// example, `create_new` is more specialized than `truncate`) so we
// search for the first "on" bit in this sequence, and use that as the
// open mode.
let canonicalized_open_mode = if self.open_mode & sys::FSOM_CREATE_NEW.0 != 0 {
let canonicalized_open_mode = if self.open_mode.has_flag(sys::FSOM_CREATE_NEW) {
sys::FSOM_CREATE_NEW
} else if self.open_mode & sys::FSOM_CREATE_ALWAYS.0 != 0 {
} else if self.open_mode.has_flag(sys::FSOM_CREATE_ALWAYS) {
sys::FSOM_CREATE_ALWAYS
} else if self.open_mode & sys::FSOM_OPEN_APPEND.0 != 0 {
} else if self.open_mode.has_flag(sys::FSOM_OPEN_APPEND) {
sys::FSOM_OPEN_APPEND
} else if self.open_mode & sys::FSOM_OPEN_ALWAYS.0 != 0 {
} else if self.open_mode.has_flag(sys::FSOM_OPEN_ALWAYS) {
sys::FSOM_OPEN_ALWAYS
} else {
sys::FSOM_OPEN_EXISTING
Expand All @@ -132,7 +132,7 @@ impl OpenOptions {
sys::storage_file_open(
f.0.as_ptr(),
path.as_ptr() as *const c_char,
sys::FS_AccessMode(self.access_mode),
self.access_mode,
canonicalized_open_mode,
)
} {
Expand Down
73 changes: 73 additions & 0 deletions crates/sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,79 @@ macro_rules! __halt_implementation {
};
}

/// Check if flag is set.
///
/// Typically implemented as `(self & flag) == flag`.
pub trait HasFlag {
fn has_flag(self, flag: Self) -> bool;
}

/// Implement bitfield operations for "bitfield" enums.
#[doc(hidden)]
macro_rules! impl_bitfield_enum {
($t:ty) => {
impl ::core::default::Default for $t {
#[inline]
fn default() -> Self {
Self(0)
}
}
impl ::core::ops::BitOr<$t> for $t {
type Output = Self;

#[inline]
fn bitor(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
impl ::core::ops::BitOrAssign for $t {
#[inline]
fn bitor_assign(&mut self, rhs: $t) {
self.0 |= rhs.0;
}
}
impl ::core::ops::BitAnd<$t> for $t {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
Self(self.0 & other.0)
}
}
impl ::core::ops::BitAndAssign for $t {
#[inline]
fn bitand_assign(&mut self, rhs: $t) {
self.0 &= rhs.0;
}
}
impl ::core::ops::Not for $t {
type Output = Self;
#[inline]
fn not(self) -> Self::Output {
Self(!self.0)
}
}
impl HasFlag for $t {
#[inline]
fn has_flag(self, flag: Self) -> bool {
(self.0 & flag.0) == flag.0
}
}
};
}

impl_bitfield_enum!(CliCommandFlag);
impl_bitfield_enum!(FS_AccessMode);
impl_bitfield_enum!(FS_Flags);
impl_bitfield_enum!(FS_OpenMode);
impl_bitfield_enum!(FuriFlag);
impl_bitfield_enum!(FuriHalNfcEvent);
impl_bitfield_enum!(FuriHalRtcFlag);
impl_bitfield_enum!(FuriHalSerialRxEvent);
impl_bitfield_enum!(iButtonProtocolFeature);
impl_bitfield_enum!(Light);
impl_bitfield_enum!(MfUltralightFeatureSupport);
impl_bitfield_enum!(SubGhzProtocolFlag);

// Re-export bindings
pub use bindings::*;

Expand Down

0 comments on commit 09cd6f8

Please sign in to comment.