Search Apps Documentation Source Content File Folder Download Copy Actions Download

post_storage.gno

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