Search Apps Documentation Source Content File Folder Download Copy Actions Download

member_grouping.gno

4.10 Kb · 162 lines
  1package commondao
  2
  3import (
  4	"errors"
  5
  6	"gno.land/p/nt/avl/v0"
  7)
  8
  9type (
 10	// MemberGroupIterFn defines a callback to iterate DAO members groups.
 11	MemberGroupIterFn func(MemberGroup) bool
 12
 13	// MemberGrouping defines an interface for storing multiple member groups.
 14	// Member grouping can be used by implementations that require grouping users
 15	// by roles or by tiers for example.
 16	MemberGrouping interface {
 17		// Size returns the number of groups that grouping contains.
 18		Size() int
 19
 20		// Has checks if a group exists.
 21		Has(name string) bool
 22
 23		// Add adds an new member group if it doesn't exists.
 24		Add(name string) (MemberGroup, error)
 25
 26		// Get returns a member group.
 27		Get(name string) (_ MemberGroup, found bool)
 28
 29		// Delete deletes a member group.
 30		Delete(name string) error
 31
 32		// IterateByOffset iterates all member groups.
 33		// The callback can return true to stop iteration.
 34		IterateByOffset(offset, count int, fn MemberGroupIterFn) (stopped bool)
 35	}
 36)
 37
 38// NewMemberGrouping creates a new members grouping.
 39func NewMemberGrouping(options ...MemberGroupingOption) MemberGrouping {
 40	g := &memberGrouping{
 41		createStorage: func(string) MemberStorage { return NewMemberStorage() },
 42	}
 43
 44	for _, apply := range options {
 45		apply(g)
 46	}
 47	return g
 48}
 49
 50type memberGrouping struct {
 51	groups        avl.Tree // string(name) -> MemberGroup
 52	createStorage func(group string) MemberStorage
 53}
 54
 55// Size returns the number of groups that grouping contains.
 56func (g memberGrouping) Size() int {
 57	return g.groups.Size()
 58}
 59
 60// Has checks if a group exists.
 61func (g memberGrouping) Has(name string) bool {
 62	return g.groups.Has(name)
 63}
 64
 65// Add adds an new member group if it doesn't exists.
 66func (g *memberGrouping) Add(name string) (MemberGroup, error) {
 67	if g.groups.Has(name) {
 68		return nil, errors.New("member group already exists: " + name)
 69	}
 70
 71	mg, err := NewMemberGroup(name, g.createStorage(name))
 72	if err != nil {
 73		return nil, err
 74	}
 75
 76	g.groups.Set(name, mg)
 77	return mg, nil
 78}
 79
 80// Get returns a member group.
 81func (g memberGrouping) Get(name string) (_ MemberGroup, found bool) {
 82	v, found := g.groups.Get(name)
 83	if !found {
 84		return nil, false
 85	}
 86	return v.(MemberGroup), true
 87}
 88
 89// Delete deletes a member group.
 90func (g *memberGrouping) Delete(name string) error {
 91	g.groups.Remove(name)
 92	return nil
 93}
 94
 95// IterateByOffset iterates all member groups.
 96func (g memberGrouping) IterateByOffset(offset, count int, fn MemberGroupIterFn) bool {
 97	return g.groups.IterateByOffset(offset, count, func(_ string, v any) bool {
 98		return fn(v.(MemberGroup))
 99	})
100}
101
102// NewReadonlyMemberGrouping creates a new grouping if member.
103func NewReadonlyMemberGrouping(g MemberGrouping) (*ReadonlyMemberGrouping, error) {
104	if g == nil {
105		return nil, errors.New("member grouping is required")
106	}
107	return &ReadonlyMemberGrouping{g}, nil
108}
109
110// MustNewReadonlyMemberGrouping creates a new grouping if member or panics on error.
111func MustNewReadonlyMemberGrouping(g MemberGrouping) *ReadonlyMemberGrouping {
112	grouping, err := NewReadonlyMemberGrouping(g)
113	if err != nil {
114		panic(err)
115	}
116	return grouping
117}
118
119// ReadonlyMemberGrouping defines a type for storing multiple readonly member groups.
120type ReadonlyMemberGrouping struct {
121	grouping MemberGrouping
122}
123
124// Size returns the number of groups that grouping contains.
125func (g ReadonlyMemberGrouping) Size() int {
126	if g.grouping == nil {
127		return 0
128	}
129	return g.grouping.Size()
130}
131
132// Has checks if a group exists.
133func (g ReadonlyMemberGrouping) Has(name string) bool {
134	if g.grouping == nil {
135		return false
136	}
137	return g.grouping.Has(name)
138}
139
140// Get returns a member group.
141func (g ReadonlyMemberGrouping) Get(name string) (_ *ReadonlyMemberGroup, found bool) {
142	if g.grouping == nil {
143		return nil, false
144	}
145
146	group, found := g.grouping.Get(name)
147	if !found {
148		return nil, false
149	}
150	return MustNewReadonlyMemberGroup(group), true
151}
152
153// IterateByOffset iterates all member groups.
154func (g ReadonlyMemberGrouping) IterateByOffset(offset, count int, fn func(*ReadonlyMemberGroup) bool) bool {
155	if g.grouping == nil {
156		return false
157	}
158
159	return g.grouping.IterateByOffset(offset, count, func(group MemberGroup) bool {
160		return fn(MustNewReadonlyMemberGroup(group))
161	})
162}