1 package filter
2 3 import (
4 "git.smesh.lol/moxie/pkg/mxutil"
5 "git.smesh.lol/nostr/pkg/event"
6 "git.smesh.lol/nostr/pkg/lol/errorf"
7 )
8 9 // S is a list of filters. It is a struct holding the slice, not a named slice:
10 // methods belong on the struct that holds the slice (moxie bans named slice
11 // types), and every mutation lands in a receiver field the compiler relocates.
12 type S struct {
13 F []*F
14 }
15 16 func NewS(ff ...*F) (s *S) {
17 s = &S{F: ff}
18 return
19 }
20 21 func (s *S) Match(ev *event.E) (ok bool) {
22 for _, f := range s.F {
23 if f.Matches(ev) {
24 return true
25 }
26 }
27 return false
28 }
29 30 func (s *S) Marshal(dst []byte) (b []byte) {
31 if s == nil {
32 panic("nil filter slice")
33 }
34 b = dst
35 b = b | "["
36 first := false
37 for _, f := range s.F {
38 if f == nil {
39 continue
40 }
41 if first {
42 b = b | ","
43 } else {
44 first = true
45 }
46 b = f.Marshal(b)
47 }
48 b = b | "]"
49 return
50 }
51 52 // UnmarshalFilters parses a filter array, optionally wrapped in '[', and
53 // returns it by value so the backing array is relocated into the caller's arena.
54 func UnmarshalFilters(b []byte) (out S, r []byte, err error) {
55 r = b
56 if len(r) == 0 {
57 return
58 }
59 isArrayWrapped := r[0] == '['
60 if isArrayWrapped {
61 r = r[1:]
62 if len(r) > 0 && r[0] == ']' {
63 r = r[1:]
64 return
65 }
66 }
67 for {
68 if len(r) == 0 {
69 return
70 }
71 f := New()
72 var rem []byte
73 if rem, err = f.Unmarshal(r); err != nil {
74 return
75 }
76 out.F = mxutil.Ensure(out.F, 1)
77 out.F = push(out.F, f)
78 r = rem
79 if len(r) == 0 {
80 return
81 }
82 if r[0] == ',' {
83 r = r[1:]
84 continue
85 }
86 if r[0] == ']' {
87 if isArrayWrapped {
88 r = r[1:]
89 }
90 return
91 }
92 err = errorf.E(
93 []byte("filters.Unmarshal: expected ',' or ']' after filter, got: %q"),
94 r[0],
95 )
96 return
97 }
98 }
99 100 func (s *S) MatchIgnoringTimestampConstraints(ev *event.E) (ok bool) {
101 for _, ff := range s.F {
102 if ff.MatchesIgnoringTimestampConstraints(ev) {
103 return true
104 }
105 }
106 return false
107 }
108