1 // Package eoseenvelope provides an encoder for the EOSE (End Of Stored
2 // Events) event that signifies that a REQ has found all stored events and
3 // from here on the request morphs into a subscription, until the limit, if
4 // requested, or until CLOSE or CLOSED.
5 package eoseenvelope
6 7 import (
8 "io"
9 10 "next.orly.dev/pkg/nostr/encoders/envelopes"
11 "next.orly.dev/pkg/nostr/encoders/text"
12 "next.orly.dev/pkg/nostr/interfaces/codec"
13 "next.orly.dev/pkg/lol/chk"
14 )
15 16 // L is the label associated with this type of codec.Envelope.
17 const L = "EOSE"
18 19 // T is an EOSE envelope (End of Stored Events), that signals the end of events
20 // that are stored and the beginning of a subscription. This is necessitated by
21 // the confusing multiplexing of websockets for multiple requests, and an ugly
22 // merging of two distinct API calls, filter and subscribe.
23 type T struct {
24 Subscription []byte
25 }
26 27 var _ codec.Envelope = (*T)(nil)
28 29 // New creates a new eoseenvelope.T with a standard form subscription.Id.
30 func New() *T {
31 return new(T)
32 }
33 34 // NewFrom creates a new eoseenvelope.T using a provided subscription.Id.
35 func NewFrom[V []byte | string](id V) *T { return &T{Subscription: []byte(id)} }
36 37 // Label returns the label of a EOSE envelope.
38 func (en *T) Label() string { return L }
39 40 // Write the eoseenvelope.T to a provided io.Writer.
41 func (en *T) Write(w io.Writer) (err error) {
42 _, err = w.Write(en.Marshal(nil))
43 return
44 }
45 46 // Marshal a eoseenvelope.T envelope in minified JSON, appending to a provided
47 // destination slice.
48 func (en *T) Marshal(dst []byte) (b []byte) {
49 var err error
50 b = dst
51 b = envelopes.Marshal(
52 b, L,
53 func(bst []byte) (o []byte) {
54 o = bst
55 o = append(o, '"')
56 o = append(o, en.Subscription...)
57 o = append(o, '"')
58 return
59 },
60 )
61 _ = err
62 return
63 }
64 65 // Unmarshal a eoseenvelope.T from minified JSON, returning the remainder after
66 // the end of the envelope.
67 func (en *T) Unmarshal(b []byte) (r []byte, err error) {
68 r = b
69 if en.Subscription, r, err = text.UnmarshalQuoted(r); chk.E(err) {
70 return
71 }
72 if r, err = envelopes.SkipToTheEnd(r); chk.E(err) {
73 return
74 }
75 return
76 }
77 78 // Parse reads a EOSE envelope in minified JSON into a newly allocated
79 // eoseenvelope.T.
80 func Parse(b []byte) (t *T, rem []byte, err error) {
81 t = New()
82 if rem, err = t.Unmarshal(b); chk.E(err) {
83 return
84 }
85 return
86 }
87