use crate::res::{Res, Set, Sets};
use bitflags::bitflags;
#[cfg(feature = "derive")]
pub use fav_derive::Status;
pub trait Status {
fn status(&self) -> i32;
fn status_mut(&mut self) -> &mut i32;
fn status_flags(&self) -> StatusFlags {
StatusFlags::from_bits_retain(self.status())
}
fn check_status(&self, status: StatusFlags) -> bool {
self.status_flags().contains(status)
}
fn set_status(&mut self, status: StatusFlags) {
*self.status_mut() = status.bits();
}
fn on_status(&mut self, status: StatusFlags) {
self.set_status(self.status_flags() | status);
}
fn off_status(&mut self, status: StatusFlags) {
self.set_status(self.status_flags() - status);
}
}
bitflags! {
#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub struct StatusFlags: i32 {
#[allow(missing_docs)]
const FETCHED = 0b00001;
#[allow(missing_docs)]
const TRACK = 0b00010;
#[allow(missing_docs)]
const SAVED = 0b00100;
#[allow(missing_docs)]
const FAV = 0b01000;
#[allow(missing_docs)]
const EXPIRED = 0b10000;
}
}
pub trait SetsStatusExt: Sets
where
Self::Set: Status,
{
fn on_set_status(&mut self, status: StatusFlags) {
self.iter_mut().for_each(|s| s.on_status(status));
}
fn off_set_status(&mut self, status: StatusFlags) {
self.iter_mut().for_each(|s| s.off_status(status));
}
fn set_set_status(&mut self, status: StatusFlags) {
self.iter_mut().for_each(|s| s.set_status(status));
}
fn with_set_status_on(mut self, status: StatusFlags) -> Self
where
Self: Sized,
{
self.iter_mut().for_each(|s| s.on_status(status));
self
}
fn with_set_status_set(mut self, status: StatusFlags) -> Self
where
Self: Sized,
{
self.iter_mut().for_each(|s| s.set_status(status));
self
}
}
impl<T> SetsStatusExt for T
where
T: Sets,
T::Set: Status,
{
}
pub trait SetStatusExt: Set {
fn on_res_status(&mut self, status: StatusFlags) {
self.iter_mut().for_each(|r| r.on_status(status));
}
fn off_res_status(&mut self, status: StatusFlags) {
self.iter_mut().for_each(|r| r.off_status(status));
}
fn set_res_status(&mut self, status: StatusFlags) {
self.iter_mut().for_each(|r| r.set_status(status));
}
fn with_res_status_on(mut self, status: StatusFlags) -> Self
where
Self: Sized,
{
self.iter_mut().for_each(|r| r.on_status(status));
self
}
fn with_res_status_set(mut self, status: StatusFlags) -> Self
where
Self: Sized,
{
self.iter_mut().for_each(|r| r.set_status(status));
self
}
}
impl<S> SetStatusExt for S where S: Set {}
pub trait ResStatusExt: Res + Status + Sized {
fn with_status_on(mut self, status: StatusFlags) -> Self {
self.on_status(status);
self
}
fn with_status_set(mut self, status: StatusFlags) -> Self {
self.set_status(status);
self
}
}
impl<R> ResStatusExt for R where R: Res + Status + Sized {}
impl From<i32> for StatusFlags {
fn from(value: i32) -> Self {
StatusFlags::from_bits_retain(value)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate as fav_core;
#[derive(Status, Default)]
struct StatusTest {
status: i32,
}
#[test]
fn status_flags_test() {
let mut status = StatusFlags::empty();
status.insert(StatusFlags::FETCHED);
assert!(status.intersects(StatusFlags::FETCHED));
assert_eq!(status.bits(), 1);
status.insert(StatusFlags::TRACK);
assert_eq!(status.bits(), 3);
}
#[test]
fn status_test() {
let mut status = StatusTest::default();
status.on_status(StatusFlags::FETCHED);
assert!(status.check_status(StatusFlags::FETCHED));
status.off_status(StatusFlags::FETCHED);
assert!(!status.check_status(StatusFlags::FETCHED));
status.on_status(StatusFlags::FETCHED);
status.on_status(StatusFlags::SAVED);
assert!(status.check_status(StatusFlags::FETCHED));
assert!(status.check_status(StatusFlags::SAVED));
}
}