use std::{
fmt::Display,
sync::atomic::{AtomicBool, Ordering},
};
#[derive(Debug)]
pub enum SelectableItem<T> {
Existing { value: T, selected: AtomicBool },
Requested { value: String, selected: AtomicBool },
}
impl<T: Display> Display for SelectableItem<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SelectableItem::Existing { value, .. } => write!(f, "{}", value),
SelectableItem::Requested { value, .. } => write!(f, "{}", value),
}
}
}
impl<T> SelectableItem<T> {
pub fn new(value: T) -> Self {
Self::Existing {
value,
selected: false.into(),
}
}
pub fn new_selected(value: T) -> Self {
Self::Existing {
value,
selected: true.into(),
}
}
pub fn new_requested(value: String) -> Self {
Self::Requested {
value,
selected: false.into(),
}
}
pub fn new_requested_selected(value: String) -> Self {
Self::Requested {
value,
selected: true.into(),
}
}
pub fn value(&self) -> Option<&T> {
match self {
SelectableItem::Existing { value, .. } => Some(value),
SelectableItem::Requested { .. } => None,
}
}
pub fn value_mut(&mut self) -> Option<&mut T> {
match self {
SelectableItem::Existing { value, .. } => Some(value),
SelectableItem::Requested { .. } => None,
}
}
pub fn requested_value(&self) -> Option<&String> {
match self {
SelectableItem::Existing { .. } => None,
SelectableItem::Requested { value, .. } => Some(value),
}
}
pub fn is_selected(&self) -> bool {
match self {
SelectableItem::Existing { selected, .. } => selected.load(Ordering::SeqCst),
SelectableItem::Requested { selected, .. } => selected.load(Ordering::SeqCst),
}
}
pub fn set_selected(&self, selected_state: bool) {
match self {
SelectableItem::Existing { selected, .. } => {
selected.store(selected_state, Ordering::SeqCst)
}
SelectableItem::Requested { selected, .. } => {
selected.store(selected_state, Ordering::SeqCst)
}
}
}
pub fn toggle_selected(&self) {
match self {
SelectableItem::Existing { selected, .. } => {
selected.fetch_xor(true, Ordering::SeqCst);
}
SelectableItem::Requested { selected, .. } => {
selected.fetch_xor(true, Ordering::SeqCst);
}
}
}
pub fn into_inner(self) -> Option<T> {
match self {
SelectableItem::Existing { value, .. } => Some(value),
SelectableItem::Requested { .. } => None,
}
}
pub fn is_existing(&self) -> bool {
matches!(self, SelectableItem::Existing { .. })
}
pub fn is_requested(&self) -> bool {
matches!(self, SelectableItem::Requested { .. })
}
}