eoseenvelope.go raw

   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