repost_storage.gno
2.31 Kb · 98 lines
1package boards
2
3import (
4 "errors"
5
6 "gno.land/p/nt/avl/v0"
7 "gno.land/p/nt/seqid/v0"
8)
9
10type (
11 // RepostIterFn defines a function type to iterate reposts.
12 RepostIterFn func(board, repost ID) bool
13
14 // RepostStorage defines an interface for storing reposts.
15 RepostStorage interface {
16 // Get returns the repost ID for a board.
17 Get(board ID) (repost ID, found bool)
18
19 // Add adds a new repost to the storage.
20 Add(repost *Post) error
21
22 // Remove removes repost for a board.
23 Remove(board ID) (removed bool)
24
25 // Size returns the number of reposts in the storage.
26 Size() int
27
28 // Iterate iterates reposts.
29 // To reverse iterate reposts use a negative count.
30 // If the callback returns true, the iteration is stopped.
31 Iterate(start, count int, fn RepostIterFn) bool
32 }
33)
34
35// NewRepostStorage creates a new storage for reposts.
36// The new storage uses an AVL tree to store reposts.
37func NewRepostStorage() RepostStorage {
38 return &repostStorage{avl.NewTree()}
39}
40
41type repostStorage struct {
42 reposts *avl.Tree // string(Board.ID) -> Post.ID
43}
44
45// Get returns the repost ID for a board.
46func (s repostStorage) Get(boardID ID) (ID, bool) {
47 v, found := s.reposts.Get(boardID.Key())
48 if !found {
49 return 0, false
50 }
51 return v.(ID), true
52}
53
54// Add adds a new repost to the storage.
55func (s *repostStorage) Add(repost *Post) error {
56 if repost == nil {
57 return errors.New("saving nil reposts is not allowed")
58 }
59
60 s.reposts.Set(repost.Board.ID.Key(), repost.ID)
61 return nil
62}
63
64// Remove removes repost for a board.
65func (s *repostStorage) Remove(boardID ID) bool {
66 _, removed := s.reposts.Remove(boardID.Key())
67 return removed
68}
69
70// Size returns the number of reposts in the storage.
71func (s repostStorage) Size() int {
72 return s.reposts.Size()
73}
74
75// Iterate iterates reposts.
76// To reverse iterate reposts use a negative count.
77// If the callback returns true, the iteration is stopped.
78func (s repostStorage) Iterate(start, count int, fn RepostIterFn) bool {
79 if count < 0 {
80 return s.reposts.ReverseIterateByOffset(start, -count, func(k string, v any) bool {
81 id, err := seqid.FromString(k)
82 if err != nil {
83 panic(err)
84 }
85
86 return fn(ID(id), v.(ID))
87 })
88 }
89
90 return s.reposts.IterateByOffset(start, count, func(k string, v any) bool {
91 id, err := seqid.FromString(k)
92 if err != nil {
93 panic(err)
94 }
95
96 return fn(ID(id), v.(ID))
97 })
98}