github.com/anacrolix/torrent@v1.61.0/tracker/shared/shared.go (about)

     1  package shared
     2  
     3  import (
     4  	"encoding"
     5  	"encoding/json"
     6  	"fmt"
     7  	"log/slog"
     8  	"slices"
     9  )
    10  
    11  const (
    12  	None      AnnounceEvent = iota
    13  	Completed               // The local peer just completed the torrent.
    14  	Started                 // The local peer has just resumed this torrent.
    15  	Stopped                 // The local peer is leaving the swarm.
    16  )
    17  
    18  type AnnounceEvent int32
    19  
    20  func (me *AnnounceEvent) UnmarshalText(text []byte) error {
    21  	i := slices.Index(announceEventStrings, string(text))
    22  	if i == -1 {
    23  		return fmt.Errorf("unknown announce event string: %q", text)
    24  	}
    25  	*me = AnnounceEvent(i)
    26  	return nil
    27  }
    28  
    29  func (me AnnounceEvent) MarshalText() ([]byte, error) {
    30  	return []byte(announceEventStrings[me]), nil
    31  }
    32  
    33  var announceEventStrings = []string{"", "completed", "started", "stopped"}
    34  
    35  func (e AnnounceEvent) String() string {
    36  	// See BEP 3, "event", and
    37  	// https://github.com/anacrolix/torrent/issues/416#issuecomment-751427001. Return a safe default
    38  	// in case event values are not sanitized.
    39  	if e < 0 || int(e) >= len(announceEventStrings) {
    40  		return fmt.Sprintf("<unknown announce event %d>", e)
    41  	}
    42  	s := announceEventStrings[e]
    43  	if e == None && s == "" {
    44  		s = "<regular>"
    45  	}
    46  	return s
    47  }
    48  
    49  // I think this is necessary for when we convert a type to JSON for logging.
    50  var _ interface {
    51  	slog.LogValuer
    52  	encoding.TextMarshaler
    53  } = None
    54  
    55  func (me AnnounceEvent) LogValue() slog.Value {
    56  	return slog.StringValue(me.String())
    57  }
    58  
    59  // MarshalJSON implements json.Marshaler to ensure AnnounceEvent is serialized as a string in JSON
    60  func (me AnnounceEvent) MarshalJSON() ([]byte, error) {
    61  	return json.Marshal(me.String())
    62  }
    63  
    64  // UnmarshalJSON implements json.Unmarshaler to deserialize AnnounceEvent from a string in JSON
    65  func (me *AnnounceEvent) UnmarshalJSON(data []byte) error {
    66  	var str string
    67  	if err := json.Unmarshal(data, &str); err != nil {
    68  		return err
    69  	}
    70  	return me.UnmarshalText([]byte(str))
    71  }