package filter import ( "git.smesh.lol/moxie/pkg/mxutil" "git.smesh.lol/nostr/pkg/event" "git.smesh.lol/nostr/pkg/lol/errorf" ) // S is a list of filters. It is a struct holding the slice, not a named slice: // methods belong on the struct that holds the slice (moxie bans named slice // types), and every mutation lands in a receiver field the compiler relocates. type S struct { F []*F } func NewS(ff ...*F) (s *S) { s = &S{F: ff} return } func (s *S) Match(ev *event.E) (ok bool) { for _, f := range s.F { if f.Matches(ev) { return true } } return false } func (s *S) Marshal(dst []byte) (b []byte) { if s == nil { panic("nil filter slice") } b = dst b = b | "[" first := false for _, f := range s.F { if f == nil { continue } if first { b = b | "," } else { first = true } b = f.Marshal(b) } b = b | "]" return } // UnmarshalFilters parses a filter array, optionally wrapped in '[', and // returns it by value so the backing array is relocated into the caller's arena. func UnmarshalFilters(b []byte) (out S, r []byte, err error) { r = b if len(r) == 0 { return } isArrayWrapped := r[0] == '[' if isArrayWrapped { r = r[1:] if len(r) > 0 && r[0] == ']' { r = r[1:] return } } for { if len(r) == 0 { return } f := New() var rem []byte if rem, err = f.Unmarshal(r); err != nil { return } out.F = mxutil.Ensure(out.F, 1) out.F = push(out.F, f) r = rem if len(r) == 0 { return } if r[0] == ',' { r = r[1:] continue } if r[0] == ']' { if isArrayWrapped { r = r[1:] } return } err = errorf.E( []byte("filters.Unmarshal: expected ',' or ']' after filter, got: %q"), r[0], ) return } } func (s *S) MatchIgnoringTimestampConstraints(ev *event.E) (ok bool) { for _, ff := range s.F { if ff.MatchesIgnoringTimestampConstraints(ev) { return true } } return false }