Transaction
D1F4CC7ED6EA2E…29CEFD02A4FF
Block 25,651 · index 1 · indexed
Summary
- Hash
- D1F4CC7ED6EA2ED97D9AA6189A79E2F0263A202C580667EBC1BC29CEFD02A4FF
- Block
- 25,651
- Size
- 8065 bytes
- Gas used
- 14,815,923 / 17,779,167
- Fee
- 1000000ugnot
- Memo
- gnopublish
- Status
- success
Messages
- Package
- gno.land/p/moul/deque/v0
Arguments · 9
- #1deque
- #2README.md
- #3# `gno.land/p/moul/deque/v0` _TODO: describe this package._ <!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) --> --- Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage. > ⚠️ **Disclaimer:** provided as-is, without warranty; not security-audited. Full disclaimer: [DISCLAIMER](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md). <!-- END GNOCONTRACTS FOOTER -->
- #4deque.gno
- #5// Package deque provides a doubly-linked deque with optional size limits, // optimized for minimal storage updates and O(1) operations in Gno environments. // // This implementation uses a doubly-linked list structure that provides: // - O(1) push back operations // - O(1) pop front operations // - O(1) access to first/last elements // - No array resizing or slice shifting // - Minimal allocations (one node per element) // - Minimal storage updates (typically 1-2 pointer updates per operation) // - Optional max-size eviction policy // // Optimized for Gno blockchain storage: each operation updates only specific nodes // rather than entire data structures, making it ideal for storage-efficient lists // that need simple read operations like first/last access, size checks, list // enumeration, and iteration with minimal storage update overhead. // // Example usage: // // // Unbounded deque // d := deque.New() // d.PushBack("a", "b", "c") // // // Bounded deque with automatic eviction // d = deque.NewBounded(3) // d.PushBack("a", "b", "c", "d") // "a" gets evicted // // first := d.PopFront() // Returns "b" // last := d.Last() // Returns "d" // // // Iterate forward // iter := d.All() // iter(func(val any) bool { // println(val) // return true // continue // }) // // // Iterate backward // iter = d.Backward() // iter(func(val any) bool { // println(val) // return true // continue // }) package deque // Node represents a single element in the doubly-linked list type Node struct { value any prev *Node next *Node } // Deque represents a doubly-linked deque with optional size limits type Deque struct { head *Node tail *Node size int max int // 0 = unlimited } // New creates a new unbounded deque. func New() *Deque { return &Deque{ max: 0, // unlimited } } // NewBounded creates a new bounded deque with the specified maximum size. // When the deque exceeds maxSize, elements are removed from the front. func NewBounded(maxSize int) *Deque { if maxSize <= 0 { maxSize = 1 } return &Deque{ max: maxSize, } } // PushBack adds one or more elements to the back of the deque. // If the deque exceeds maxSize, elements are removed from the front. func (d *Deque) PushBack(items ...any) { for _, item := range items { d.pushBackSingle(item) } } // pushBackSingle adds a single element to the back func (d *Deque) pushBackSingle(item any) { node := &Node{value: item} if d.tail == nil { // First element d.head = node d.tail = node } else { // Link to existing tail d.tail.next = node node.prev = d.tail d.tail = node } d.size++ // Handle size limit by removing from front if d.max > 0 && d.size > d.max { d.popFrontNode() } } // PopFront removes and returns the front element. // Returns nil if the deque is empty. func (d *Deque) PopFront() any { if d.head == nil { return nil } value := d.head.value d.popFrontNode() return value } // popFrontNode removes the front node func (d *Deque) popFrontNode() { if d.head == nil { return } if d.head == d.tail { // Only one element d.head = nil d.tail = nil } else { // Move head forward d.head = d.head.next d.head.prev = nil } d.size-- } // PopBack removes and returns the back element. // Returns nil if the deque is empty. func (d *Deque) PopBack() any { if d.tail == nil { return nil } value := d.tail.value d.popBackNode() return value } // popBackNode removes the back node func (d *Deque) popBackNode() { if d.tail == nil { return } if d.head == d.tail { // Only one element d.head = nil d.tail = nil } else { // Move tail backward d.tail = d.tail.prev d.tail.next = nil } d.size-- } // PushFront adds one or more elements to the front of the deque. // If bounded and size limit is exceeded, elements are removed from the back. func (d *Deque) PushFront(items ...any) { for _, item := range items { d.pushFrontSingle(item) } } // pushFrontSingle adds a single element to the front func (d *Deque) pushFrontSingle(item any) { node := &Node{value: item} if d.head == nil { // First element d.head = node d.tail = node } else { // Link to existing head d.head.prev = node node.next = d.head d.head = node } d.size++ // Handle size limit by removing from back if d.max > 0 && d.size > d.max { d.popBackNode() } } // Size returns the current number of elements func (d *Deque) Size() int { return d.size } // MaxSize returns the maximum size limit (0 = unlimited) func (d *Deque) MaxSize() int { return d.max } // IsEmpty returns true if the deque is empty func (d *Deque) IsEmpty() bool { return d.size == 0 } // IsBounded returns true if the deque has a size limit func (d *Deque) IsBounded() bool { return d.max > 0 } // First returns the front element without removing it. // Returns nil if the deque is empty. func (d *Deque) First() any { if d.head == nil { return nil } return d.head.value } // Last returns the back element without removing it. // Returns nil if the deque is empty. func (d *Deque) Last() any { if d.tail == nil { return nil } return d.tail.value } // Get returns the element at the specified index (0 = front). // Returns nil if index is out of bounds. func (d *Deque) Get(index int) any { if index < 0 || index >= d.size { return nil } node := d.head for i := 0; i < index; i++ { node = node.next } return node.value } // List returns all elements as a slice, ordered from front to back func (d *Deque) List() []any { if d.size == 0 { return nil } result := make([]any, d.size) node := d.head for i := 0; i < d.size; i++ { result[i] = node.value node = node.next } return result } // Enumerate calls fn for each element with its index (0-based from front) func (d *Deque) Enumerate(fn func(index int, value any) bool) { node := d.head for i := 0; i < d.size; i++ { if fn(i, node.value) { break } node = node.next } } // Clear removes all elements from the deque func (d *Deque) Clear() { d.head = nil d.tail = nil d.size = 0 } // SetMaxSize changes the maximum size limit. // If the new limit is smaller than current size, elements are removed from front. func (d *Deque) SetMaxSize(maxSize int) { d.max = maxSize if maxSize > 0 { for d.size > maxSize { d.popFrontNode() } } } // All returns an iterator function for forward traversal (Go 1.23+ compatible) // Note: range-over-func syntax is not yet supported in Gno, use iter() directly func (d *Deque) All() func(yield func(any) bool) { return func(yield func(any) bool) { current := d.head for current != nil { if !yield(current.value) { return } current = current.next } } } // Backward returns an iterator function for backward traversal (Go 1.23+ compatible) // Note: range-over-func syntax is not yet supported in Gno, use iter() directly func (d *Deque) Backward() func(yield func(any) bool) { return func(yield func(any) bool) { current := d.tail for current != nil { if !yield(current.value) { return } current = current.prev } } }
- #6gnomod.toml
- #7module = "gno.land/p/moul/deque/v0" gno = "0.9"
- #8/gno.MemPackageType
- #9 MPUserProd
Result log
msg:0,success:true,log:,events:[]