helpers.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Package easyjson contains marshaler/unmarshaler interfaces and helper functions.
  2. package easyjson
  3. import (
  4. "io"
  5. "io/ioutil"
  6. "net/http"
  7. "strconv"
  8. "unsafe"
  9. "github.com/mailru/easyjson/jlexer"
  10. "github.com/mailru/easyjson/jwriter"
  11. )
  12. // Marshaler is an easyjson-compatible marshaler interface.
  13. type Marshaler interface {
  14. MarshalEasyJSON(w *jwriter.Writer)
  15. }
  16. // Marshaler is an easyjson-compatible unmarshaler interface.
  17. type Unmarshaler interface {
  18. UnmarshalEasyJSON(w *jlexer.Lexer)
  19. }
  20. // MarshalerUnmarshaler is an easyjson-compatible marshaler/unmarshaler interface.
  21. type MarshalerUnmarshaler interface {
  22. Marshaler
  23. Unmarshaler
  24. }
  25. // Optional defines an undefined-test method for a type to integrate with 'omitempty' logic.
  26. type Optional interface {
  27. IsDefined() bool
  28. }
  29. // UnknownsUnmarshaler provides a method to unmarshal unknown struct fileds and save them as you want
  30. type UnknownsUnmarshaler interface {
  31. UnmarshalUnknown(in *jlexer.Lexer, key string)
  32. }
  33. // UnknownsMarshaler provides a method to write additional struct fields
  34. type UnknownsMarshaler interface {
  35. MarshalUnknowns(w *jwriter.Writer, first bool)
  36. }
  37. func isNilInterface(i interface{}) bool {
  38. return (*[2]uintptr)(unsafe.Pointer(&i))[1] == 0
  39. }
  40. // Marshal returns data as a single byte slice. Method is suboptimal as the data is likely to be copied
  41. // from a chain of smaller chunks.
  42. func Marshal(v Marshaler) ([]byte, error) {
  43. if isNilInterface(v) {
  44. return nullBytes, nil
  45. }
  46. w := jwriter.Writer{}
  47. v.MarshalEasyJSON(&w)
  48. return w.BuildBytes()
  49. }
  50. // MarshalToWriter marshals the data to an io.Writer.
  51. func MarshalToWriter(v Marshaler, w io.Writer) (written int, err error) {
  52. if isNilInterface(v) {
  53. return w.Write(nullBytes)
  54. }
  55. jw := jwriter.Writer{}
  56. v.MarshalEasyJSON(&jw)
  57. return jw.DumpTo(w)
  58. }
  59. // MarshalToHTTPResponseWriter sets Content-Length and Content-Type headers for the
  60. // http.ResponseWriter, and send the data to the writer. started will be equal to
  61. // false if an error occurred before any http.ResponseWriter methods were actually
  62. // invoked (in this case a 500 reply is possible).
  63. func MarshalToHTTPResponseWriter(v Marshaler, w http.ResponseWriter) (started bool, written int, err error) {
  64. if isNilInterface(v) {
  65. w.Header().Set("Content-Type", "application/json")
  66. w.Header().Set("Content-Length", strconv.Itoa(len(nullBytes)))
  67. written, err = w.Write(nullBytes)
  68. return true, written, err
  69. }
  70. jw := jwriter.Writer{}
  71. v.MarshalEasyJSON(&jw)
  72. if jw.Error != nil {
  73. return false, 0, jw.Error
  74. }
  75. w.Header().Set("Content-Type", "application/json")
  76. w.Header().Set("Content-Length", strconv.Itoa(jw.Size()))
  77. started = true
  78. written, err = jw.DumpTo(w)
  79. return
  80. }
  81. // Unmarshal decodes the JSON in data into the object.
  82. func Unmarshal(data []byte, v Unmarshaler) error {
  83. l := jlexer.Lexer{Data: data}
  84. v.UnmarshalEasyJSON(&l)
  85. return l.Error()
  86. }
  87. // UnmarshalFromReader reads all the data in the reader and decodes as JSON into the object.
  88. func UnmarshalFromReader(r io.Reader, v Unmarshaler) error {
  89. data, err := ioutil.ReadAll(r)
  90. if err != nil {
  91. return err
  92. }
  93. l := jlexer.Lexer{Data: data}
  94. v.UnmarshalEasyJSON(&l)
  95. return l.Error()
  96. }