@@ -38,11 +38,22 @@ library DoubleEndedQueue {
3838 * Reverts with {Panic-RESOURCE_ERROR} if the queue is full.
3939 */
4040 function pushBack (Bytes32Deque storage deque , bytes32 value ) internal {
41+ bool success = tryPushBack (deque, value);
42+ if (! success) Panic.panic (Panic.RESOURCE_ERROR);
43+ }
44+
45+ /**
46+ * @dev Attempts to insert an item at the end of the queue.
47+ *
48+ * Returns `false` if the queue is full. Never reverts.
49+ */
50+ function tryPushBack (Bytes32Deque storage deque , bytes32 value ) internal returns (bool success ) {
4151 unchecked {
4252 uint128 backIndex = deque._end;
43- if (backIndex + 1 == deque._begin) Panic. panic (Panic.RESOURCE_ERROR) ;
53+ if (backIndex + 1 == deque._begin) return false ;
4454 deque._data[backIndex] = value;
4555 deque._end = backIndex + 1 ;
56+ return true ;
4657 }
4758 }
4859
@@ -51,11 +62,23 @@ library DoubleEndedQueue {
5162 *
5263 * Reverts with {Panic-EMPTY_ARRAY_POP} if the queue is empty.
5364 */
54- function popBack (Bytes32Deque storage deque ) internal returns (bytes32 value ) {
65+ function popBack (Bytes32Deque storage deque ) internal returns (bytes32 ) {
66+ (bool success , bytes32 value ) = tryPopBack (deque);
67+ if (! success) Panic.panic (Panic.EMPTY_ARRAY_POP);
68+ return value;
69+ }
70+
71+ /**
72+ * @dev Attempts to remove the item at the end of the queue and return it.
73+ *
74+ * Returns `(false, 0x00)` if the queue is empty. Never reverts.
75+ */
76+ function tryPopBack (Bytes32Deque storage deque ) internal returns (bool success , bytes32 value ) {
5577 unchecked {
5678 uint128 backIndex = deque._end;
57- if (backIndex == deque._begin) Panic. panic (Panic.EMPTY_ARRAY_POP );
79+ if (backIndex == deque._begin) return ( false , bytes32 ( 0 ) );
5880 -- backIndex;
81+ success = true ;
5982 value = deque._data[backIndex];
6083 delete deque._data[backIndex];
6184 deque._end = backIndex;
@@ -68,11 +91,22 @@ library DoubleEndedQueue {
6891 * Reverts with {Panic-RESOURCE_ERROR} if the queue is full.
6992 */
7093 function pushFront (Bytes32Deque storage deque , bytes32 value ) internal {
94+ bool success = tryPushFront (deque, value);
95+ if (! success) Panic.panic (Panic.RESOURCE_ERROR);
96+ }
97+
98+ /**
99+ * @dev Attempts to insert an item at the beginning of the queue.
100+ *
101+ * Returns `false` if the queue is full. Never reverts.
102+ */
103+ function tryPushFront (Bytes32Deque storage deque , bytes32 value ) internal returns (bool success ) {
71104 unchecked {
72105 uint128 frontIndex = deque._begin - 1 ;
73- if (frontIndex == deque._end) Panic. panic (Panic.RESOURCE_ERROR) ;
106+ if (frontIndex == deque._end) return false ;
74107 deque._data[frontIndex] = value;
75108 deque._begin = frontIndex;
109+ return true ;
76110 }
77111 }
78112
@@ -81,10 +115,23 @@ library DoubleEndedQueue {
81115 *
82116 * Reverts with {Panic-EMPTY_ARRAY_POP} if the queue is empty.
83117 */
84- function popFront (Bytes32Deque storage deque ) internal returns (bytes32 value ) {
118+ function popFront (Bytes32Deque storage deque ) internal returns (bytes32 ) {
119+ (bool success , bytes32 value ) = tryPopFront (deque);
120+ if (! success) Panic.panic (Panic.EMPTY_ARRAY_POP);
121+ return value;
122+ }
123+
124+ /**
125+ * @dev Attempts to remove the item at the beginning of the queue and
126+ * return it.
127+ *
128+ * Returns `(false, 0x00)` if the queue is empty. Never reverts.
129+ */
130+ function tryPopFront (Bytes32Deque storage deque ) internal returns (bool success , bytes32 value ) {
85131 unchecked {
86132 uint128 frontIndex = deque._begin;
87- if (frontIndex == deque._end) Panic.panic (Panic.EMPTY_ARRAY_POP);
133+ if (frontIndex == deque._end) return (false , bytes32 (0 ));
134+ success = true ;
88135 value = deque._data[frontIndex];
89136 delete deque._data[frontIndex];
90137 deque._begin = frontIndex + 1 ;
@@ -96,20 +143,42 @@ library DoubleEndedQueue {
96143 *
97144 * Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the queue is empty.
98145 */
99- function front (Bytes32Deque storage deque ) internal view returns (bytes32 value ) {
100- if (empty (deque)) Panic.panic (Panic.ARRAY_OUT_OF_BOUNDS);
101- return deque._data[deque._begin];
146+ function front (Bytes32Deque storage deque ) internal view returns (bytes32 ) {
147+ (bool success , bytes32 value ) = tryFront (deque);
148+ if (! success) Panic.panic (Panic.ARRAY_OUT_OF_BOUNDS);
149+ return value;
150+ }
151+
152+ /**
153+ * @dev Attempts to return the item at the beginning of the queue.
154+ *
155+ * Returns `(false, 0x00)` if the queue is empty. Never reverts.
156+ */
157+ function tryFront (Bytes32Deque storage deque ) internal view returns (bool success , bytes32 value ) {
158+ if (empty (deque)) return (false , bytes32 (0 ));
159+ return (true , deque._data[deque._begin]);
102160 }
103161
104162 /**
105163 * @dev Returns the item at the end of the queue.
106164 *
107165 * Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the queue is empty.
108166 */
109- function back (Bytes32Deque storage deque ) internal view returns (bytes32 value ) {
110- if (empty (deque)) Panic.panic (Panic.ARRAY_OUT_OF_BOUNDS);
167+ function back (Bytes32Deque storage deque ) internal view returns (bytes32 ) {
168+ (bool success , bytes32 value ) = tryBack (deque);
169+ if (! success) Panic.panic (Panic.ARRAY_OUT_OF_BOUNDS);
170+ return value;
171+ }
172+
173+ /**
174+ * @dev Attempts to return the item at the end of the queue.
175+ *
176+ * Returns `(false, 0x00)` if the queue is empty. Never reverts.
177+ */
178+ function tryBack (Bytes32Deque storage deque ) internal view returns (bool success , bytes32 value ) {
179+ if (empty (deque)) return (false , bytes32 (0 ));
111180 unchecked {
112- return deque._data[deque._end - 1 ];
181+ return ( true , deque._data[deque._end - 1 ]) ;
113182 }
114183 }
115184
@@ -119,11 +188,23 @@ library DoubleEndedQueue {
119188 *
120189 * Reverts with {Panic-ARRAY_OUT_OF_BOUNDS} if the index is out of bounds.
121190 */
122- function at (Bytes32Deque storage deque , uint256 index ) internal view returns (bytes32 value ) {
123- if (index >= length (deque)) Panic.panic (Panic.ARRAY_OUT_OF_BOUNDS);
191+ function at (Bytes32Deque storage deque , uint256 index ) internal view returns (bytes32 ) {
192+ (bool success , bytes32 value ) = tryAt (deque, index);
193+ if (! success) Panic.panic (Panic.ARRAY_OUT_OF_BOUNDS);
194+ return value;
195+ }
196+
197+ /**
198+ * @dev Attempts to return the item at a position in the queue given by `index`, with the first item at
199+ * 0 and the last item at `length(deque) - 1`.
200+ *
201+ * Returns `(false, 0x00)` if the index is out of bounds. Never reverts.
202+ */
203+ function tryAt (Bytes32Deque storage deque , uint256 index ) internal view returns (bool success , bytes32 value ) {
204+ if (index >= length (deque)) return (false , bytes32 (0 ));
124205 // By construction, length is a uint128, so the check above ensures that index can be safely downcast to uint128
125206 unchecked {
126- return deque._data[deque._begin + uint128 (index)];
207+ return ( true , deque._data[deque._begin + uint128 (index)]) ;
127208 }
128209 }
129210
0 commit comments