Files
mautrix-telegram/pkg/gotd/telegram/message/peer/list.go
T
2025-06-27 20:03:37 -07:00

119 lines
2.5 KiB
Go

package peer
import (
"time"
"go.mau.fi/mautrix-telegram/pkg/gotd/tg"
)
type nodeData struct {
key string
value tg.InputPeerClass
expiresAt time.Time
}
type linkedNode struct {
next, prev *linkedNode
nodeData
}
// linkedList is a doubly linked list implementation.
// This implementation is highly inspired by container/list, but type safe.
type linkedList struct {
root linkedNode
len int
}
// Front returns the first element of list l or nil if the list is empty.
func (l *linkedList) Front() *linkedNode {
if l.len == 0 {
return nil
}
return l.root.next
}
// Back returns the last element of list l or nil if the list is empty.
func (l *linkedList) Back() *linkedNode {
if l.len == 0 {
return nil
}
return l.root.prev
}
// insert inserts e after at, increments l.len, and returns e.
func (l *linkedList) insert(e, at *linkedNode) *linkedNode {
e.prev = at
e.next = at.next
e.prev.next = e
e.next.prev = e
l.len++
return e
}
func (l *linkedList) insertValue(v nodeData, at *linkedNode) *linkedNode {
e := new(linkedNode)
e.nodeData = v
return l.insert(e, at)
}
// PushFront inserts a new element e with value v at the front of list l and returns e.
func (l *linkedList) PushFront(v nodeData) *linkedNode {
l.lazyInit()
return l.insertValue(v, &l.root)
}
// lazyInit lazily initializes a zero List value.
func (l *linkedList) lazyInit() {
if l.root.next == nil {
l.root.next = &l.root
l.root.prev = &l.root
l.len = 0
}
}
// remove removes e from its list, decrements l.len, and returns e.
func (l *linkedList) remove(e *linkedNode) nodeData {
e.prev.next = e.next
e.next.prev = e.prev
e.next = nil // avoid memory leaks
e.prev = nil // avoid memory leaks
l.len--
value := e.nodeData
return value
}
// move moves e to next to at and returns e.
func (l *linkedList) move(e, at *linkedNode) *linkedNode {
if e == at {
return e
}
e.prev.next = e.next
e.next.prev = e.prev
e.prev = at
e.next = at.next
e.prev.next = e
e.next.prev = e
return e
}
// Remove removes e from l if e is an element of list l.
// It returns the element value e.Value.
// The element must not be nil.
func (l *linkedList) Remove(e *linkedNode) nodeData {
return l.remove(e)
}
// MoveToFront moves element e to the front of list l.
// If e is not an element of l, the list is not modified.
// The element must not be nil.
func (l *linkedList) MoveToFront(e *linkedNode) {
if l.root.next == e {
return
}
// see comment in List.Remove about initialization of l
l.move(e, &l.root)
}