transcoding.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package sessions
  2. import (
  3. "bytes"
  4. "encoding/gob"
  5. "encoding/json"
  6. "reflect"
  7. "time"
  8. )
  9. func init() {
  10. gob.Register(time.Time{})
  11. }
  12. type (
  13. // Marshaler is the common marshaler interface, used by transcoder.
  14. Marshaler interface {
  15. Marshal(interface{}) ([]byte, error)
  16. }
  17. // Unmarshaler is the common unmarshaler interface, used by transcoder.
  18. Unmarshaler interface {
  19. Unmarshal([]byte, interface{}) error
  20. }
  21. // Transcoder is the interface that transcoders should implement, it includes just the `Marshaler` and the `Unmarshaler`.
  22. Transcoder interface {
  23. Marshaler
  24. Unmarshaler
  25. }
  26. )
  27. type (
  28. defaultTranscoder struct{}
  29. // GobTranscoder can be set to `DefaultTranscoder` to modify the database(s) transcoder.
  30. GobTranscoder struct{}
  31. )
  32. var (
  33. _ Transcoder = (*defaultTranscoder)(nil)
  34. _ Transcoder = (*GobTranscoder)(nil)
  35. // DefaultTranscoder is the default transcoder across databases (when `UseDatabase` is used).
  36. //
  37. // The default database's values encoder and decoder
  38. // calls the value's `Marshal/Unmarshal` methods (if any)
  39. // otherwise JSON is selected,
  40. // the JSON format can be stored to any database and
  41. // it supports both builtin language types(e.g. string, int) and custom struct values.
  42. // Also, and the most important, the values can be
  43. // retrieved/logged/monitored by a third-party program
  44. // written in any other language as well.
  45. //
  46. // You can change this behavior by registering a custom `Transcoder`.
  47. // Iris provides a `GobTranscoder` which is mostly suitable
  48. // if your session values are going to be custom Go structs.
  49. // Select this if you always retrieving values through Go.
  50. // Don't forget to initialize a call of gob.Register when necessary.
  51. // Read https://golang.org/pkg/encoding/gob/ for more.
  52. //
  53. // You can also implement your own `sessions.Transcoder` and use it,
  54. // i.e: a transcoder which will allow(on Marshal: return its byte representation and nil error)
  55. // or dissalow(on Marshal: return non nil error) certain types.
  56. //
  57. // sessions.DefaultTranscoder = sessions.GobTranscoder{}
  58. DefaultTranscoder Transcoder = defaultTranscoder{}
  59. )
  60. func (defaultTranscoder) Marshal(value interface{}) ([]byte, error) {
  61. if tr, ok := value.(Marshaler); ok {
  62. return tr.Marshal(value)
  63. }
  64. if jsonM, ok := value.(json.Marshaler); ok {
  65. return jsonM.MarshalJSON()
  66. }
  67. return json.Marshal(value)
  68. }
  69. func (defaultTranscoder) Unmarshal(b []byte, outPtr interface{}) error {
  70. if tr, ok := outPtr.(Unmarshaler); ok {
  71. return tr.Unmarshal(b, outPtr)
  72. }
  73. if jsonUM, ok := outPtr.(json.Unmarshaler); ok {
  74. return jsonUM.UnmarshalJSON(b)
  75. }
  76. return json.Unmarshal(b, outPtr)
  77. }
  78. // Marshal returns the gob encoding of "value".
  79. func (GobTranscoder) Marshal(value interface{}) ([]byte, error) {
  80. var (
  81. w = new(bytes.Buffer)
  82. enc = gob.NewEncoder(w)
  83. err error
  84. )
  85. if v, ok := value.(reflect.Value); ok {
  86. err = enc.EncodeValue(v)
  87. } else {
  88. err = enc.Encode(&value)
  89. }
  90. if err != nil {
  91. return nil, err
  92. }
  93. return w.Bytes(), nil
  94. }
  95. // Unmarshal parses the gob-encoded data "b" and stores the result
  96. // in the value pointed to by "outPtr".
  97. func (GobTranscoder) Unmarshal(b []byte, outPtr interface{}) error {
  98. dec := gob.NewDecoder(bytes.NewBuffer(b))
  99. if v, ok := outPtr.(reflect.Value); ok {
  100. return dec.DecodeValue(v)
  101. }
  102. return dec.Decode(outPtr)
  103. }