//! Partition Manager use crate::error::{Acc1410Error, Result}; use crate::types::{ExtendedGNACS, Partition, PartitionInfo, PartitionType}; use sha3::{Digest, Sha3_256}; use std::collections::HashMap; #[derive(Debug)] pub struct PartitionManager { partitions: HashMap, account_partitions: HashMap>, } impl PartitionManager { pub fn new() -> Self { Self { partitions: HashMap::new(), account_partitions: HashMap::new(), } } pub fn create_partition( &mut self, name: String, extended_gnacs: ExtendedGNACS, partition_type: PartitionType, ) -> Result<[u8; 32]> { let mut hasher = Sha3_256::new(); hasher.update(name.as_bytes()); hasher.update(&extended_gnacs.encode()); let hash_result = hasher.finalize(); let mut partition_id = [0u8; 32]; partition_id.copy_from_slice(&hash_result); let partition_id_hex = hex::encode(partition_id); if self.partitions.contains_key(&partition_id_hex) { return Err(Acc1410Error::PartitionAlreadyExists(partition_id_hex)); } let partition = Partition::new( partition_id, extended_gnacs, name, partition_type, Self::current_timestamp(), ); self.partitions.insert(partition_id_hex, partition); Ok(partition_id) } pub fn close_partition(&mut self, partition_id: &[u8; 32]) -> Result<()> { let partition_id_hex = hex::encode(partition_id); let partition = self .partitions .get_mut(&partition_id_hex) .ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex.clone()))?; partition.info.is_active = false; Ok(()) } pub fn get_partition_info(&self, partition_id: &[u8; 32]) -> Result { let partition_id_hex = hex::encode(partition_id); let partition = self .partitions .get(&partition_id_hex) .ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex))?; Ok(partition.info.clone()) } pub fn balance_of_by_partition( &self, partition_id: &[u8; 32], account: &str, ) -> Result { let partition_id_hex = hex::encode(partition_id); let partition = self .partitions .get(&partition_id_hex) .ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex))?; Ok(partition.balance_of(account)) } pub fn partitions_of(&self, account: &str) -> Vec<[u8; 32]> { self.account_partitions .get(account) .map(|partition_ids| { partition_ids .iter() .filter_map(|id_hex| { let bytes = hex::decode(id_hex).ok()?; if bytes.len() == 32 { let mut arr = [0u8; 32]; arr.copy_from_slice(&bytes); Some(arr) } else { None } }) .collect() }) .unwrap_or_default() } pub fn add_balance( &mut self, partition_id: &[u8; 32], account: &str, amount: u64, ) -> Result<()> { let partition_id_hex = hex::encode(partition_id); let partition = self .partitions .get_mut(&partition_id_hex) .ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex.clone()))?; if !partition.info.is_active { return Err(Acc1410Error::PartitionClosed(partition_id_hex)); } partition.add_balance(account, amount); self.account_partitions .entry(account.to_string()) .or_insert_with(Vec::new) .push(partition_id_hex); Ok(()) } pub fn sub_balance( &mut self, partition_id: &[u8; 32], account: &str, amount: u64, ) -> Result<()> { let partition_id_hex = hex::encode(partition_id); let partition = self .partitions .get_mut(&partition_id_hex) .ok_or_else(|| Acc1410Error::PartitionNotFound(partition_id_hex.clone()))?; if !partition.info.is_active { return Err(Acc1410Error::PartitionClosed(partition_id_hex)); } let available = partition.balance_of(account); if available < amount { return Err(Acc1410Error::InsufficientBalance { account: account.to_string(), required: amount, available, }); } partition.sub_balance(account, amount); Ok(()) } pub fn get_all_partition_ids(&self) -> Vec<[u8; 32]> { self.partitions .keys() .filter_map(|id_hex| { let bytes = hex::decode(id_hex).ok()?; if bytes.len() == 32 { let mut arr = [0u8; 32]; arr.copy_from_slice(&bytes); Some(arr) } else { None } }) .collect() } fn current_timestamp() -> u64 { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs() } } impl Default for PartitionManager { fn default() -> Self { Self::new() } }