github.com/viant/toolbox@v0.34.5/encoder.go (about) 1 package toolbox 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "gopkg.in/yaml.v2" 7 "io" 8 ) 9 10 //Encoder writes an instance to output stream 11 type Encoder interface { 12 //Encode encodes an instance to output stream 13 Encode(object interface{}) error 14 } 15 16 //Marshaler represents byte to object converter 17 type Marshaler interface { 18 //Marshal converts bytes to attributes of owner struct 19 Marshal() (data []byte, err error) 20 } 21 22 //EncoderFactory create an encoder for an output stream 23 type EncoderFactory interface { 24 //Create creates an encoder for an output stream 25 Create(writer io.Writer) Encoder 26 } 27 28 type jsonEncoderFactory struct{} 29 30 func (e jsonEncoderFactory) Create(writer io.Writer) Encoder { 31 return json.NewEncoder(writer) 32 } 33 34 //NewJSONEncoderFactory creates new NewJSONEncoderFactory 35 func NewJSONEncoderFactory() EncoderFactory { 36 return &jsonEncoderFactory{} 37 } 38 39 type marshalerEncoderFactory struct { 40 } 41 42 func (f *marshalerEncoderFactory) Create(writer io.Writer) Encoder { 43 return &marshalerEncoder{writer: writer} 44 } 45 46 type marshalerEncoder struct { 47 writer io.Writer 48 } 49 50 func (e *marshalerEncoder) Encode(v interface{}) error { 51 result, casted := v.(Marshaler) 52 if !casted { 53 return fmt.Errorf("failed to decode - unable cast %T to %s", v, result) 54 } 55 bytes, err := result.Marshal() 56 if err != nil { 57 return err 58 } 59 var totalByteWritten = 0 60 var bytesLen = len(bytes) 61 for i := 0; i < bytesLen; i++ { 62 bytesWritten, err := e.writer.Write(bytes[totalByteWritten:]) 63 if err != nil { 64 return fmt.Errorf("failed to write data %v", err) 65 } 66 totalByteWritten = totalByteWritten + bytesWritten 67 if totalByteWritten == bytesLen { 68 break 69 } 70 } 71 if totalByteWritten != bytesLen { 72 return fmt.Errorf("failed to write all data, written %v, expected: %v", totalByteWritten, bytesLen) 73 } 74 return nil 75 } 76 77 //NewMarshalerEncoderFactory create a new encoder factory for marsheler struct 78 func NewMarshalerEncoderFactory() EncoderFactory { 79 return &marshalerEncoderFactory{} 80 } 81 82 type yamlEncoderFactory struct{} 83 84 func (e yamlEncoderFactory) Create(writer io.Writer) Encoder { 85 return &yamlEncoder{writer} 86 } 87 88 type yamlEncoder struct { 89 io.Writer 90 } 91 92 //Encode converts source into yaml format to write itto writer 93 func (d *yamlEncoder) Encode(source interface{}) error { 94 data, err := yaml.Marshal(source) 95 if err != nil { 96 return err 97 } 98 var dataSize = len(data) 99 for i := 0; i < dataSize; i++ { 100 written, err := d.Writer.Write(data) 101 if err != nil { 102 return err 103 } 104 if len(data) == written { 105 break 106 } 107 data = data[written:] 108 } 109 return err 110 } 111 112 //NewYamlEncoderFactory create a new yaml encoder factory 113 func NewYamlEncoderFactory() EncoderFactory { 114 return &yamlEncoderFactory{} 115 }