github.com/icyphox/x@v0.0.355-0.20220311094250-029bd783e8b8/watcherx/event.go (about) 1 package watcherx 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 9 "github.com/pkg/errors" 10 ) 11 12 type ( 13 Event interface { 14 // MarshalJSON is required to work multiple times 15 json.Marshaler 16 17 Reader() io.Reader 18 Source() string 19 String() string 20 setSource(string) 21 } 22 source string 23 ErrorEvent struct { 24 error 25 source 26 } 27 ChangeEvent struct { 28 data []byte 29 source 30 } 31 RemoveEvent struct { 32 source 33 } 34 serialEventType string 35 serialEvent struct { 36 Type serialEventType `json:"type"` 37 Data []byte `json:"data"` 38 Source source `json:"source"` 39 } 40 ) 41 42 const ( 43 serialTypeChange serialEventType = "change" 44 serialTypeRemove serialEventType = "remove" 45 serialTypeError serialEventType = "error" 46 ) 47 48 var errUnknownEvent = errors.New("unknown event type") 49 50 func (e *ErrorEvent) Reader() io.Reader { 51 return bytes.NewBufferString(e.Error()) 52 } 53 54 func (e *ErrorEvent) MarshalJSON() ([]byte, error) { 55 return json.Marshal(serialEvent{ 56 Type: serialTypeError, 57 Data: []byte(e.Error()), 58 Source: e.source, 59 }) 60 } 61 62 func (e *ErrorEvent) String() string { 63 return fmt.Sprintf("error: %+v; source: %s", e.error, e.source) 64 } 65 66 func (e source) Source() string { 67 return string(e) 68 } 69 70 func (e *source) setSource(nsrc string) { 71 *e = source(nsrc) 72 } 73 74 func (e *ChangeEvent) Reader() io.Reader { 75 return bytes.NewBuffer(e.data) 76 } 77 78 func (e *ChangeEvent) MarshalJSON() ([]byte, error) { 79 return json.Marshal(serialEvent{ 80 Type: serialTypeChange, 81 Data: e.data, 82 Source: e.source, 83 }) 84 } 85 86 func (e *ChangeEvent) String() string { 87 return fmt.Sprintf("data: %s; source: %s", e.data, e.source) 88 } 89 90 func (e *RemoveEvent) Reader() io.Reader { 91 return nil 92 } 93 94 func (e *RemoveEvent) MarshalJSON() ([]byte, error) { 95 return json.Marshal(serialEvent{ 96 Type: serialTypeRemove, 97 Source: e.source, 98 }) 99 } 100 101 func (e *RemoveEvent) String() string { 102 return fmt.Sprintf("removed source: %s", e.source) 103 } 104 105 func unmarshalEvent(data []byte) (Event, error) { 106 var serialEvent serialEvent 107 if err := json.Unmarshal(data, &serialEvent); err != nil { 108 return nil, errors.WithStack(err) 109 } 110 switch serialEvent.Type { 111 case serialTypeRemove: 112 return &RemoveEvent{ 113 source: serialEvent.Source, 114 }, nil 115 case serialTypeChange: 116 return &ChangeEvent{ 117 data: serialEvent.Data, 118 source: serialEvent.Source, 119 }, nil 120 case serialTypeError: 121 return &ErrorEvent{ 122 error: errors.New(string(serialEvent.Data)), 123 source: serialEvent.Source, 124 }, nil 125 } 126 return nil, errUnknownEvent 127 }