generated from eigerco/beerus
-
Notifications
You must be signed in to change notification settings - Fork 103
/
Copy pathstack.cairo
154 lines (132 loc) · 4.45 KB
/
stack.cairo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! Stack implementation.
//!
//! # Example
//! ```
//! use alexandria::data_structures::stack::StackTrait;
//!
//! // Create a new stack instance.
//! let mut stack = StackTrait::new();
//! // Create an item and push it to the stack.
//! let mut item:u256 = 1.into();
//! stack.push(item);
//! Remove the item from the stack;
//! let item = stack.pop();
//! ```
use core::nullable::NullableImpl;
pub trait StackTrait<S, T> {
/// Creates a new Stack instance.
fn new() -> S;
/// Pushes a new value onto the stack.
fn push(ref self: S, value: T);
/// Removes the last item from the stack and returns it, or None if the stack is empty.
fn pop(ref self: S) -> Option<T>;
/// Returns the last item from the stack without removing it, or None if the stack is empty.
fn peek(ref self: S) -> Option<T>;
/// Returns the number of items in the stack.
fn len(self: @S) -> usize;
/// Returns true if the stack is empty.
fn is_empty(self: @S) -> bool;
}
pub struct Felt252Stack<T> {
elements: Felt252Dict<T>,
len: usize,
}
impl DestructFeltStack<T, +Drop<T>, +Felt252DictValue<T>> of Destruct<Felt252Stack<T>> {
fn destruct(self: Felt252Stack<T>) nopanic {
self.elements.squash();
}
}
impl Felt252StackImpl<
T, +Copy<T>, +Drop<T>, +Felt252DictValue<T>,
> of StackTrait<Felt252Stack<T>, T> {
#[inline(always)]
/// Creates a new Stack instance.
/// Returns
/// * Stack The new stack instance.
fn new() -> Felt252Stack<T> {
let elements: Felt252Dict<T> = Default::default();
Felt252Stack { elements, len: 0 }
}
/// Pushes a new value onto the stack.
/// * `self` - The stack to push the value onto.
/// * `value` - The value to push onto the stack.
fn push(ref self: Felt252Stack<T>, value: T) {
self.elements.insert(self.len.into(), value);
self.len += 1;
}
/// Removes the last item from the stack and returns it, or None if the stack is empty.
/// * `self` - The stack to pop the item off of.
/// Returns
/// * Stack The stack with the item removed.
/// * Option<u256> The item removed or None if the stack is empty.
fn pop(ref self: Felt252Stack<T>) -> Option<T> {
if self.is_empty() {
return Option::None;
}
self.len -= 1;
Option::Some(self.elements.get(self.len.into()))
}
/// Returns the last item from the stack without removing it, or None if the stack is empty.
/// * `self` - The stack to peek the item off of.
/// Returns
/// * Option<u256> The last item of the stack
fn peek(ref self: Felt252Stack<T>) -> Option<T> {
if self.is_empty() {
return Option::None;
}
Option::Some(self.elements.get((self.len - 1).into()))
}
/// Returns the number of items in the stack.
/// * `self` - The stack to get the length of.
/// Returns
/// * usize The number of items in the stack.
fn len(self: @Felt252Stack<T>) -> usize {
*self.len
}
/// Returns true if the stack is empty.
/// * `self` - The stack to check if it is empty.
/// Returns
/// * bool True if the stack is empty, false otherwise.
fn is_empty(self: @Felt252Stack<T>) -> bool {
*self.len == 0
}
}
pub struct NullableStack<T> {
elements: Felt252Dict<Nullable<T>>,
len: usize,
}
impl DestructNullableStack<T, +Drop<T>> of Destruct<NullableStack<T>> {
fn destruct(self: NullableStack<T>) nopanic {
self.elements.squash();
}
}
impl NullableStackImpl<T, +Copy<T>, +Drop<T>> of StackTrait<NullableStack<T>, T> {
#[inline(always)]
fn new() -> NullableStack<T> {
let elements: Felt252Dict<Nullable<T>> = Default::default();
NullableStack { elements, len: 0 }
}
fn push(ref self: NullableStack<T>, value: T) {
self.elements.insert(self.len.into(), NullableImpl::new(value));
self.len += 1;
}
fn pop(ref self: NullableStack<T>) -> Option<T> {
if self.is_empty() {
return Option::None;
}
self.len -= 1;
Option::Some(self.elements.get(self.len.into()).deref())
}
fn peek(ref self: NullableStack<T>) -> Option<T> {
if self.is_empty() {
return Option::None;
}
Option::Some(self.elements.get((self.len - 1).into()).deref())
}
fn len(self: @NullableStack<T>) -> usize {
*self.len
}
fn is_empty(self: @NullableStack<T>) -> bool {
*self.len == 0
}
}