pub mod incrementable_implementations;
use core::{fmt::Debug, mem::replace};
use std::{
collections::{HashMap, HashSet, hash_map},
hash::Hash,
option::Option,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::stg::Setting;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[must_use]
pub struct Account<N, K, V> {
name: N,
active: bool,
#[cfg_attr(feature = "serde", serde(bound = "K: Eq + Hash"))]
settings: HashMap<K, V>,
accounts: Vec<Account<N, K, V>>,
valid: Valid,
}
impl<N, K, V> Account<N, K, V> {
pub const fn new_unchecked(
name: N,
active: bool,
settings: HashMap<K, V>,
accounts: Vec<Self>,
valid: Valid,
) -> Self {
Self {
name,
active,
settings,
accounts,
valid,
}
}
#[must_use]
pub const fn name(&self) -> &N {
&self.name
}
#[must_use]
pub const fn active(&self) -> bool {
self.active
}
pub const fn change_activity(&mut self, new_active: bool) -> bool {
if self.active() == new_active {
false
} else {
self.active = new_active;
true
}
}
#[must_use]
pub const fn hashmap(&self) -> &HashMap<K, V> {
&self.settings
}
#[must_use]
pub fn keys(&self) -> hash_map::Keys<'_, K, V> {
self.settings.keys()
}
#[must_use]
pub fn capacity(&self) -> usize {
self.settings.capacity()
}
#[must_use]
pub const fn accounts(&self) -> &Vec<Self> {
&self.accounts
}
#[must_use]
pub fn accounts_names(&self) -> Vec<&N> {
self.accounts.iter().map(Self::name).collect()
}
#[must_use]
pub const fn len(&self) -> usize {
self.accounts.len()
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.accounts.is_empty()
}
#[must_use]
pub fn get_mut_account(&mut self, index: usize) -> Option<&mut Self> {
self.accounts.get_mut(index)
}
fn update_valid_children(&self) -> bool {
for account in self.accounts() {
if !account.valid.is_valid() {
return false;
}
}
true
}
pub const fn valid(&self) -> &Valid {
&self.valid
}
pub fn change_valid(&mut self, new_valid: Valid) -> bool {
new_valid != replace(&mut self.valid, new_valid)
}
pub const fn rename(&mut self, new_name: N) -> N {
core::mem::replace(&mut self.name, new_name)
}
}
impl<N: Eq + Hash, K, V> Account<N, K, V> {
fn update_valid_names(&self) -> bool {
let accounts = self.accounts_names();
let size = accounts.len();
let mut hash_set = HashSet::with_capacity(size);
for account in accounts {
if !hash_set.insert(account) {
return false;
}
}
true
}
}
impl<N: PartialEq, K, V> Account<N, K, V> {
pub fn deep(&self, account_names: &mut Vec<&N>) -> Result<&Self, DeepError> {
let Some(account_to_find) = account_names.pop() else {
return Err(DeepError::EmptyVec); };
self.account_from_name(account_to_find)
.map_or(
Err(DeepError::NotFound),
|found_account| match found_account.deep(account_names) {
Err(error) => match error {
DeepError::EmptyVec => Ok(found_account), DeepError::NotFound => Err(error), },
Ok(value) => Ok(value),
},
)
}
pub fn deep_mut(&mut self, account_names: &mut Vec<&N>) -> Result<&mut Self, DeepError> {
let Some(account_to_find) = account_names.pop() else {
return Err(DeepError::EmptyVec); };
if let Some(found_account) = self.mut_account_from_name(account_to_find) {
if account_names.is_empty() {
return Ok(found_account);
}
match found_account.deep_mut(account_names) {
Ok(value) => {
Ok(value) }
Err(error) => match error {
DeepError::EmptyVec => {
unreachable!() } DeepError::NotFound => Err(error), },
}
} else {
Err(DeepError::NotFound)
}
}
fn account_from_name(&self, name: &N) -> Option<&Self> {
for account in 0..self.len() {
if self.accounts[account].name() == name {
return Some(&self.accounts[account]);
}
}
None
}
fn mut_account_from_name(&mut self, name: &N) -> Option<&mut Self> {
for account in 0..self.len() {
if self.accounts[account].name() == name {
return Some(&mut self.accounts[account]);
}
}
None
}
}
impl<N, K: Eq + Hash, V> Account<N, K, V> {
#[must_use]
#[allow(clippy::borrowed_box)]
pub fn get(&self, setting_name: &K) -> Option<&V> {
self.settings.get(setting_name)
}
pub fn insert(&mut self, setting_name: K, setting_value: V) -> Option<V> {
self.settings.insert(setting_name, setting_value)
}
pub fn remove(&mut self, setting_to_remove: &K) -> Option<V> {
self.settings.remove(setting_to_remove)
}
#[must_use]
pub fn contains_key(&self, setting_name: &K) -> bool {
self.settings.contains_key(setting_name)
}
fn get_in_sub_accounts(&self, setting: &K) -> Option<&V> {
for account in (0..self.len()).rev() {
if self.accounts[account].active
&& let Some(value) = self.accounts[account].settings.get(setting)
{
return Some(value);
}
}
None
}
}
impl<N, K: Eq + Hash, V: PartialEq> Account<N, K, V> {
fn update_valid_settings(&self) -> bool {
let mut hash_set = HashSet::new();
for account in self.accounts() {
if !account.valid.settings() {
return false;
}
if account.active {
for setting in account.keys() {
hash_set.insert(setting);
}
}
}
for setting in hash_set {
if self.get_in_sub_accounts(setting) != self.get(setting) {
return false;
}
}
true
}
}
impl<N, K: Clone + Eq + Hash, V: Clone> Account<N, K, V> {
pub fn update_setting(&mut self, setting: &K) {
for account in (0..self.len()).rev() {
if self.accounts[account].active
&& let Some(value) = self.accounts[account].settings.get(setting)
{
self.settings.insert(setting.to_owned(), value.clone());
return;
}
}
self.settings.remove(setting);
}
pub fn update_vec(&mut self, settings: &Vec<&K>) {
'setting: for setting in settings {
for account in (0..self.len()).rev() {
if self.accounts[account].active
&& let Some(value) = self.accounts[account].settings.get(*setting)
{
self.settings.insert((*setting).to_owned(), value.clone());
continue 'setting;
}
}
self.settings.remove(*setting);
}
}
pub fn update_all_settings(&mut self) {
let settings = self
.settings
.keys()
.map(std::borrow::ToOwned::to_owned)
.collect::<Vec<_>>();
'setting: for setting in settings {
for account in (0..self.len()).rev() {
if self.accounts[account].active
&& let Some(value) = self.accounts[account].settings.get(&setting.clone())
{
self.settings.insert(setting.clone(), value.clone());
continue 'setting;
}
}
self.settings.remove(&setting);
}
}
fn fix_valid_settings(&mut self) {
for account in &mut self.accounts {
if !account.valid.settings {
account.fix_valid_settings();
}
}
let mut all_settings = HashSet::new();
for account in self.accounts() {
if account.active {
for setting in account.keys() {
all_settings.insert(setting.clone());
}
}
}
'setting: for setting in all_settings {
for account in (0..self.len()).rev() {
if self.accounts[account].active
&& let Some(value) = self.accounts[account].settings.get(&setting)
{
self.settings.insert(setting, value.clone());
continue 'setting;
}
}
}
self.valid.settings = true;
}
}
impl<N: Eq + Hash, K: Eq + Hash, V: PartialEq> Account<N, K, V> {
pub fn update_valid(&mut self, valid: Valid) {
if valid.names {
self.valid.names = self.update_valid_names();
}
if valid.children {
self.valid.children = self.update_valid_children();
}
if valid.settings {
self.valid.settings = self.update_valid_settings();
}
}
}
impl<N: Clone + Eq + Hash + Incrementable, K, V> Account<N, K, V> {
fn fix_valid_names(&mut self) {
let size = self.accounts.len();
let mut hash_set = HashSet::with_capacity(size);
let mut vec_names: Vec<(N, usize)> = vec![];
for account in 0..size {
if !hash_set.insert(self.accounts[account].name.clone()) {
vec_names.push((self.accounts[account].name.clone(), account));
}
}
for name in &mut vec_names {
name.0.increment_mut();
'looping: loop {
if hash_set.insert(name.0.clone()) {
self.accounts[name.1].name = name.0.clone();
break 'looping;
}
name.0.increment_mut();
}
}
self.valid.names = true;
}
}
impl<N: PartialEq, K: Clone + Eq + Hash, V: Clone> Account<N, K, V> {
pub fn deep_change_activity(
&mut self,
new_active: bool,
account_names: &mut Vec<&N>,
) -> Result<bool, DeepError> {
self.deep_change_activity_helper(new_active, account_names)
.0
}
pub fn deep_insert(
&mut self,
setting_name: &K,
setting_value: V,
account_names: &mut Vec<&N>,
) -> Result<Option<V>, DeepError> {
let Some(account_to_find) = account_names.pop() else {
return Err(DeepError::EmptyVec); };
#[allow(clippy::option_if_let_else)]
if let Some(found_account) = self.mut_account_from_name(account_to_find) {
if account_names.is_empty() {
return Ok(found_account.insert(setting_name.to_owned(), setting_value));
}
match found_account.deep_insert(setting_name, setting_value, account_names) {
Ok(insert_option) => {
self.update_setting(setting_name);
Ok(insert_option) }
Err(error) => match error {
DeepError::EmptyVec => {
unreachable!()
} DeepError::NotFound => Err(error), },
}
} else {
Err(DeepError::NotFound)
}
}
pub fn deep_remove(
&mut self,
setting_to_remove: &K,
account_names: &mut Vec<&N>,
) -> Result<Option<V>, DeepError> {
let Some(account_to_find) = account_names.pop() else {
return Err(DeepError::EmptyVec); };
#[allow(clippy::option_if_let_else)]
if let Some(found_account) = self.mut_account_from_name(account_to_find) {
match found_account.deep_remove(setting_to_remove, account_names) {
Ok(insert_option) => {
self.update_setting(setting_to_remove);
Ok(insert_option) }
Err(error) => match error {
DeepError::EmptyVec => Ok(found_account.remove(setting_to_remove)), DeepError::NotFound => Err(error), },
}
} else {
Err(DeepError::NotFound)
}
}
fn deep_change_activity_helper(
&mut self,
new_active: bool,
account_names: &mut Vec<&N>,
) -> (Result<bool, DeepError>, Vec<K>) {
let Some(account_to_find) = account_names.pop() else {
return (Err(DeepError::EmptyVec), vec![]); };
#[allow(clippy::option_if_let_else)]
if let Some(found_account) = self.mut_account_from_name(account_to_find) {
match found_account.deep_change_activity_helper(new_active, account_names) {
(Ok(insert_option), settings) => {
self.update_vec(&settings.iter().collect());
(Ok(insert_option), settings) }
(Err(error), _) => match error {
DeepError::EmptyVec => (
Ok(found_account.change_activity(new_active)),
found_account
.keys()
.map(std::borrow::ToOwned::to_owned)
.collect::<Vec<_>>(),
), DeepError::NotFound => (Err(error), vec![]), },
}
} else {
(Err(DeepError::NotFound), vec![])
}
}
}
impl<N, K: Clone + Eq + Hash, V: Clone + PartialEq> Account<N, K, V> {
#[must_use = "if return value isn't needed use update_setting() instead"]
pub fn update_setting_returns(&mut self, setting: &K) -> Option<bool> {
for account in (0..self.len()).rev() {
if self.accounts[account].active
&& let Some(value) = self.accounts[account].settings.get(setting)
{
return Some(
!self
.settings
.insert(setting.to_owned(), value.clone())
.is_some_and(|x| &x == value),
);
}
}
self.settings.remove(setting).map(|_| true)
}
}
impl<N: Clone + Eq + Hash + Incrementable + PartialEq, K, V> Account<N, K, V> {
pub fn deep_rename(
&mut self,
new_name: &N,
account_names: &mut Vec<&N>,
) -> Result<N, DeepError> {
let Some(account_to_find) = account_names.pop() else {
return Err(DeepError::EmptyVec); };
#[allow(clippy::option_if_let_else)]
if let Some(found_account) = self.mut_account_from_name(account_to_find) {
match found_account.deep_rename(new_name, account_names) {
Ok(insert_option) => {
Ok(insert_option) }
Err(error) => match error {
DeepError::EmptyVec => {
let n = found_account.rename(new_name.clone());
self.fix_valid_names();
Ok(n)
} DeepError::NotFound => Err(error), },
}
} else {
Err(DeepError::NotFound)
}
}
}
impl<N: Eq + Hash, K: Clone + Eq + Hash, V: Clone + PartialEq> Account<N, K, V> {
pub fn pop(&mut self, valid: Valid) -> Option<Self> {
let popped_account = self.accounts.pop()?;
if !self.valid.names && valid.names {
self.valid.names = self.update_valid_names();
}
if !self.valid.children && valid.children {
self.valid.children = self.update_valid_children();
}
if !self.valid.settings && valid.settings && popped_account.active {
self.update_vec(&popped_account.keys().collect());
self.valid.settings = self.update_valid_settings();
}
Some(popped_account)
}
pub fn deep_pop(
&mut self,
valid: Valid,
account_names: &mut Vec<&N>,
) -> Result<Option<Self>, DeepError> {
let Some(account_to_find) = account_names.pop() else {
return Err(DeepError::EmptyVec); };
#[allow(clippy::option_if_let_else)]
if let Some(found_account) = self.mut_account_from_name(account_to_find) {
match found_account.deep_pop(valid, account_names) {
Ok(popped_account) => {
Ok(match popped_account {
None => None,
Some(account) => {
if account.active {
self.update_vec(&account.keys().collect());
}
Some(account)
}
})
}
Err(error) => match error {
DeepError::EmptyVec => Ok(found_account.pop(valid)), DeepError::NotFound => Err(error), },
}
} else {
Err(DeepError::NotFound)
}
}
}
impl<N: Clone + Eq + Hash + Incrementable, K: Clone + Eq + Hash, V: Clone + PartialEq>
Account<N, K, V>
{
pub fn new(name: N, active: bool, settings: HashMap<K, V>, accounts: Vec<Self>) -> Self {
let mut new_account = Self {
name,
active,
settings,
accounts,
valid: Valid::new_false(),
};
new_account.fix_valid(Valid::new_true());
new_account
}
pub fn fix_valid(&mut self, valid: Valid) {
if self.valid.is_valid() && valid.is_valid() {
return;
}
if !self.valid.children && valid.children {
self.fix_valid_children();
}
if !self.valid.names && valid.names {
self.fix_valid_names();
}
if !self.valid.settings && valid.settings {
self.fix_valid_settings();
}
}
fn fix_valid_children(&mut self) {
for account in 0..self.len() {
if !self.accounts[account].valid.is_valid() {
self.accounts[account].fix_valid(Valid::default());
}
}
self.valid.children = true;
}
}
impl<N: Clone + Eq + Hash + Incrementable + PartialEq, K: Clone + Eq + Hash, V: Clone + PartialEq>
Account<N, K, V>
{
pub fn push(&mut self, account: Self, valid: Valid) {
if self.valid.children && valid.children && !account.valid.is_valid() {
self.fix_valid(Valid::new(false, false, true));
}
if self.valid.settings && valid.settings && !account.valid.is_valid() {
self.fix_valid(Valid::new(false, true, false));
}
if account.active {
for setting in account.settings.keys() {
self.insert(setting.to_owned(), account.get(setting).unwrap().clone());
}
}
if self.valid.names && valid.names && self.accounts_names().contains(&&account.name) {
self.accounts.push(account);
self.fix_valid(Valid::new(true, false, false));
} else {
self.accounts.push(account);
}
}
pub fn deep_push(
&mut self,
account: Self,
valid: Valid,
account_names: &mut Vec<&N>,
) -> Option<DeepError> {
self.deep_push_helper(account, valid, account_names).err()
}
fn deep_push_helper(
&mut self,
account: Self,
valid: Valid,
account_names: &mut Vec<&N>,
) -> Result<Vec<K>, DeepError> {
let Some(account_to_find) = account_names.pop() else {
return Err(DeepError::EmptyVec); };
#[allow(clippy::option_if_let_else)]
if let Some(found_account) = self.mut_account_from_name(account_to_find) {
if account_names.is_empty() {
let is_active = account.active;
found_account.push(account, valid);
return Ok(if is_active {
found_account.accounts[found_account.len() - 1]
.keys()
.map(std::borrow::ToOwned::to_owned)
.collect::<Vec<_>>()
} else {
vec![]
});
}
match found_account.deep_push_helper(account, valid, account_names) {
Ok(keys) => {
self.update_vec(&keys.iter().collect());
Ok(keys) }
Err(error) => match error {
DeepError::EmptyVec => {
unreachable!() } DeepError::NotFound => Err(error), },
}
} else {
Err(DeepError::NotFound)
}
}
}
impl<N: Default, K, V> Default for Account<N, K, V> {
fn default() -> Self {
Self {
name: N::default(),
active: true,
settings: HashMap::default(),
accounts: Vec::default(),
valid: Valid::default(),
}
}
}
impl<N: Clone, K: Clone, V: Clone> Clone for Account<N, K, V> {
fn clone(&self) -> Self {
Self {
name: self.name.clone(),
active: self.active,
settings: self.settings.clone(),
accounts: self.accounts.clone(),
valid: self.valid,
}
}
}
impl<N: Debug, K: Debug, V: Debug> Debug for Account<N, K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Account")
.field("name", &self.name)
.field("active", &self.active)
.field("settings", &self.settings)
.field("accounts", &self.accounts)
.field("valid", &self.valid)
.finish()
}
}
impl<N: PartialEq, K: Eq + Hash, V: PartialEq> PartialEq for Account<N, K, V> {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
&& self.active == other.active
&& self.settings == other.settings
&& self.accounts == other.accounts
&& self.valid == other.valid
}
}
#[cfg(feature = "serde")]
#[cfg_attr(feature = "serde", typetag::serialize)]
impl<
N: Setting + Clone + Debug + PartialEq + Serialize + for<'a> Deserialize<'a>,
K: Setting + Clone + Debug + Eq + Hash + Serialize + for<'a> Deserialize<'a>,
V: Setting + Clone + Debug + PartialEq + Serialize + for<'a> Deserialize<'a>,
> Setting for Account<N, K, V>
{
fn typetag_deserialize(&self) {
}
}
#[cfg(not(feature = "serde"))]
impl<
N: Setting + Clone + Debug + PartialEq,
K: Setting + Clone + Debug + Eq + Hash,
V: Setting + Clone + Debug + PartialEq,
> Setting for Account<N, K, V>
{
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[must_use]
pub struct Valid {
names: bool,
settings: bool,
children: bool,
}
impl Valid {
pub const fn new(names: bool, settings: bool, children: bool) -> Self {
Self {
names,
settings,
children,
}
}
pub const fn new_true() -> Self {
Self {
names: true,
settings: true,
children: true,
}
}
pub const fn new_false() -> Self {
Self {
names: false,
settings: false,
children: false,
}
}
#[must_use]
pub const fn is_valid(&self) -> bool {
self.children && self.settings && self.names
}
#[must_use]
pub const fn names(&self) -> bool {
self.names
}
#[must_use]
pub const fn settings(&self) -> bool {
self.settings
}
#[must_use]
pub const fn children(&self) -> bool {
self.children
}
}
impl Default for Valid {
fn default() -> Self {
Self {
names: true,
settings: true,
children: true,
}
}
}
pub trait Incrementable {
#[must_use]
fn increment(&self) -> Self;
fn increment_mut(&mut self);
}
#[derive(Debug, PartialEq, Eq)]
pub enum DeepError {
NotFound,
EmptyVec,
}