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  }