use core::marker::PhantomData;
use super::{
set_mapper::{CurrentStorage, StorageAddress},
StorageClearable, StorageMapper, StorageMapperFromAddress,
};
use crate::{
abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName},
api::StorageMapperApi,
codec::{
self,
derive::{TopDecode, TopDecodeOrDefault, TopEncode, TopEncodeOrDefault},
multi_encode_iter_or_handle_err, DecodeDefault, EncodeDefault, EncodeErrorHandler,
TopDecode, TopEncode, TopEncodeMulti, TopEncodeMultiOutput,
},
storage::{storage_set, StorageKey},
types::{ManagedAddress, ManagedType, MultiValueEncoded},
};
use alloc::vec::Vec;
const NULL_ENTRY: u32 = 0;
const INFO_IDENTIFIER: &[u8] = b".info";
const NODE_IDENTIFIER: &[u8] = b".node_links";
const VALUE_IDENTIFIER: &[u8] = b".value";
#[derive(TopEncode, TopDecode, PartialEq, Eq, Clone, Copy)]
pub struct Node {
pub previous: u32,
pub next: u32,
}
#[derive(TopEncodeOrDefault, TopDecodeOrDefault, PartialEq, Eq, Clone, Copy)]
pub struct QueueMapperInfo {
pub len: u32,
pub front: u32,
pub back: u32,
pub new: u32,
}
impl EncodeDefault for QueueMapperInfo {
fn is_default(&self) -> bool {
self.len == 0
}
}
impl DecodeDefault for QueueMapperInfo {
fn default() -> Self {
Self {
len: 0,
front: 0,
back: 0,
new: 0,
}
}
}
impl QueueMapperInfo {
pub fn generate_new_node_id(&mut self) -> u32 {
self.new += 1;
self.new
}
}
pub struct QueueMapper<SA, T, A = CurrentStorage>
where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + 'static,
{
_phantom_api: PhantomData<SA>,
address: A,
base_key: StorageKey<SA>,
_phantom_item: PhantomData<T>,
}
impl<SA, T> StorageMapper<SA> for QueueMapper<SA, T, CurrentStorage>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
fn new(base_key: StorageKey<SA>) -> Self {
QueueMapper {
_phantom_api: PhantomData,
address: CurrentStorage,
base_key,
_phantom_item: PhantomData,
}
}
}
impl<SA, T> StorageClearable for QueueMapper<SA, T, CurrentStorage>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
fn clear(&mut self) {
let info = self.get_info();
let mut node_id = info.front;
while node_id != NULL_ENTRY {
let node = self.get_node(node_id);
self.clear_node(node_id);
self.clear_value(node_id);
node_id = node.next;
}
self.set_info(QueueMapperInfo::default());
}
}
impl<SA, T> QueueMapper<SA, T, CurrentStorage>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
fn set_info(&mut self, value: QueueMapperInfo) {
storage_set(self.build_name_key(INFO_IDENTIFIER).as_ref(), &value);
}
fn set_node(&mut self, node_id: u32, item: Node) {
storage_set(
self.build_node_id_named_key(NODE_IDENTIFIER, node_id)
.as_ref(),
&item,
);
}
fn clear_node(&mut self, node_id: u32) {
storage_set(
self.build_node_id_named_key(NODE_IDENTIFIER, node_id)
.as_ref(),
&codec::Empty,
);
}
fn set_value(&mut self, node_id: u32, value: &T) {
storage_set(
self.build_node_id_named_key(VALUE_IDENTIFIER, node_id)
.as_ref(),
value,
)
}
fn clear_value(&mut self, node_id: u32) {
storage_set(
self.build_node_id_named_key(VALUE_IDENTIFIER, node_id)
.as_ref(),
&codec::Empty,
)
}
pub(crate) fn push_back_node_id(&mut self, elt: &T) -> u32 {
let mut info = self.get_info();
let new_node_id = info.generate_new_node_id();
let mut previous = NULL_ENTRY;
if info.len == 0 {
info.front = new_node_id;
} else {
let back = info.back;
let mut back_node = self.get_node(back);
back_node.next = new_node_id;
previous = back;
self.set_node(back, back_node);
}
self.set_node(
new_node_id,
Node {
previous,
next: NULL_ENTRY,
},
);
info.back = new_node_id;
self.set_value(new_node_id, elt);
info.len += 1;
self.set_info(info);
new_node_id
}
pub fn push_back(&mut self, elt: T) {
let _ = self.push_back_node_id(&elt);
}
pub fn push_front(&mut self, elt: T) {
let mut info = self.get_info();
let new_node_id = info.generate_new_node_id();
let mut next = NULL_ENTRY;
if info.len == 0 {
info.back = new_node_id;
} else {
let front = info.front;
let mut front_node = self.get_node(front);
front_node.previous = new_node_id;
next = front;
self.set_node(front, front_node);
}
self.set_node(
new_node_id,
Node {
previous: NULL_ENTRY,
next,
},
);
info.front = new_node_id;
self.set_value(new_node_id, &elt);
info.len += 1;
self.set_info(info);
}
pub fn pop_back(&mut self) -> Option<T> {
self.remove_by_node_id(self.get_info().back)
}
pub fn pop_front(&mut self) -> Option<T> {
self.remove_by_node_id(self.get_info().front)
}
pub(crate) fn remove_by_node_id(&mut self, node_id: u32) -> Option<T> {
if node_id == NULL_ENTRY {
return None;
}
let node = self.get_node(node_id);
let mut info = self.get_info();
if node.previous == NULL_ENTRY {
info.front = node.next;
} else {
let mut previous = self.get_node(node.previous);
previous.next = node.next;
self.set_node(node.previous, previous);
}
if node.next == NULL_ENTRY {
info.back = node.previous;
} else {
let mut next = self.get_node(node.next);
next.previous = node.previous;
self.set_node(node.next, next);
}
self.clear_node(node_id);
let removed_value = self.get_value(node_id);
self.clear_value(node_id);
info.len -= 1;
self.set_info(info);
Some(removed_value)
}
}
impl<SA, T> StorageMapperFromAddress<SA> for QueueMapper<SA, T, ManagedAddress<SA>>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
QueueMapper {
_phantom_api: PhantomData::<SA>,
address,
base_key,
_phantom_item: PhantomData::<T>,
}
}
}
impl<SA, A, T> QueueMapper<SA, T, A>
where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + 'static,
{
fn build_node_id_named_key(&self, name: &[u8], node_id: u32) -> StorageKey<SA> {
let mut named_key = self.base_key.clone();
named_key.append_bytes(name);
named_key.append_item(&node_id);
named_key
}
fn build_name_key(&self, name: &[u8]) -> StorageKey<SA> {
let mut name_key = self.base_key.clone();
name_key.append_bytes(name);
name_key
}
pub fn iter(&self) -> Iter<SA, A, T> {
Iter::new(self)
}
pub fn iter_from_node_id(&self, node_id: u32) -> Iter<SA, A, T> {
Iter::new_from_node_id(self, node_id)
}
fn get_info(&self) -> QueueMapperInfo {
self.address
.address_storage_get(self.build_name_key(INFO_IDENTIFIER).as_ref())
}
pub fn get_node(&self, node_id: u32) -> Node {
self.address.address_storage_get(
self.build_node_id_named_key(NODE_IDENTIFIER, node_id)
.as_ref(),
)
}
fn get_value(&self, node_id: u32) -> T {
self.address.address_storage_get(
self.build_node_id_named_key(VALUE_IDENTIFIER, node_id)
.as_ref(),
)
}
pub fn get_value_option(&self, node_id: u32) -> Option<T> {
if node_id == NULL_ENTRY {
return None;
}
Some(self.get_value(node_id))
}
pub fn is_empty(&self) -> bool {
self.get_info().len == 0
}
pub fn len(&self) -> usize {
self.get_info().len as usize
}
pub fn front(&self) -> Option<T> {
self.get_value_option(self.get_info().front)
}
pub fn back(&self) -> Option<T> {
self.get_value_option(self.get_info().back)
}
pub fn check_internal_consistency(&self) -> bool {
let info = self.get_info();
let mut front = info.front;
let mut back = info.back;
if info.len == 0 {
if front != NULL_ENTRY {
return false;
}
if back != NULL_ENTRY {
return false;
}
true
} else {
if front == NULL_ENTRY {
return false;
}
if back == NULL_ENTRY {
return false;
}
if self.get_node(front).previous != NULL_ENTRY {
return false;
}
if self.get_node(back).next != NULL_ENTRY {
return false;
}
let mut forwards = Vec::new();
while front != NULL_ENTRY {
forwards.push(front);
front = self.get_node(front).next;
}
if forwards.len() != info.len as usize {
return false;
}
let mut backwards = Vec::new();
while back != NULL_ENTRY {
backwards.push(back);
back = self.get_node(back).previous;
}
if backwards.len() != info.len as usize {
return false;
}
let backwards_reversed: Vec<u32> = backwards.iter().rev().cloned().collect();
if forwards != backwards_reversed {
return false;
}
forwards.sort_unstable();
forwards.dedup();
if forwards.len() != info.len as usize {
return false;
}
true
}
}
}
impl<'a, SA, A, T> IntoIterator for &'a QueueMapper<SA, T, A>
where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + 'static,
{
type Item = T;
type IntoIter = Iter<'a, SA, A, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct Iter<'a, SA, A, T>
where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + 'static,
{
node_id: u32,
queue: &'a QueueMapper<SA, T, A>,
}
impl<'a, SA, A, T> Iter<'a, SA, A, T>
where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + 'static,
{
fn new(queue: &'a QueueMapper<SA, T, A>) -> Iter<'a, SA, A, T> {
Iter {
node_id: queue.get_info().front,
queue,
}
}
pub fn new_from_node_id(queue: &'a QueueMapper<SA, T, A>, node_id: u32) -> Iter<'a, SA, A, T> {
Iter { node_id, queue }
}
}
impl<SA, A, T> Iterator for Iter<'_, SA, A, T>
where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + 'static,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
let current_node_id = self.node_id;
if current_node_id == NULL_ENTRY {
return None;
}
self.node_id = self.queue.get_node(current_node_id).next;
Some(self.queue.get_value(current_node_id))
}
}
impl<SA, T> TopEncodeMulti for QueueMapper<SA, T, CurrentStorage>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
where
O: TopEncodeMultiOutput,
H: EncodeErrorHandler,
{
multi_encode_iter_or_handle_err(self.iter(), output, h)
}
}
impl<SA, T> TypeAbiFrom<QueueMapper<SA, T, CurrentStorage>> for MultiValueEncoded<SA, T>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
}
impl<SA, T> TypeAbiFrom<Self> for QueueMapper<SA, T, CurrentStorage>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode,
{
}
impl<SA, T> TypeAbi for QueueMapper<SA, T, CurrentStorage>
where
SA: StorageMapperApi,
T: TopEncode + TopDecode + TypeAbi,
{
type Unmanaged = Self;
fn type_name() -> TypeName {
crate::abi::type_name_variadic::<T>()
}
fn type_name_rust() -> TypeName {
crate::abi::type_name_multi_value_encoded::<T>()
}
fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
T::provide_type_descriptions(accumulator);
}
fn is_variadic() -> bool {
true
}
}