encode.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package yaml
  2. import (
  3. "reflect"
  4. "sort"
  5. "strconv"
  6. "time"
  7. )
  8. type encoder struct {
  9. emitter yaml_emitter_t
  10. event yaml_event_t
  11. out []byte
  12. flow bool
  13. }
  14. func newEncoder() (e *encoder) {
  15. e = &encoder{}
  16. e.must(yaml_emitter_initialize(&e.emitter))
  17. yaml_emitter_set_output_string(&e.emitter, &e.out)
  18. e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING))
  19. e.emit()
  20. e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true))
  21. e.emit()
  22. return e
  23. }
  24. func (e *encoder) finish() {
  25. e.must(yaml_document_end_event_initialize(&e.event, true))
  26. e.emit()
  27. e.emitter.open_ended = false
  28. e.must(yaml_stream_end_event_initialize(&e.event))
  29. e.emit()
  30. }
  31. func (e *encoder) destroy() {
  32. yaml_emitter_delete(&e.emitter)
  33. }
  34. func (e *encoder) emit() {
  35. // This will internally delete the e.event value.
  36. if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT {
  37. e.must(false)
  38. }
  39. }
  40. func (e *encoder) must(ok bool) {
  41. if !ok {
  42. msg := e.emitter.problem
  43. if msg == "" {
  44. msg = "Unknown problem generating YAML content"
  45. }
  46. panic(msg)
  47. }
  48. }
  49. func (e *encoder) marshal(tag string, in reflect.Value) {
  50. var value interface{}
  51. if getter, ok := in.Interface().(Getter); ok {
  52. tag, value = getter.GetYAML()
  53. if value == nil {
  54. e.nilv()
  55. return
  56. }
  57. in = reflect.ValueOf(value)
  58. }
  59. switch in.Kind() {
  60. case reflect.Interface:
  61. if in.IsNil() {
  62. e.nilv()
  63. } else {
  64. e.marshal(tag, in.Elem())
  65. }
  66. case reflect.Map:
  67. e.mapv(tag, in)
  68. case reflect.Ptr:
  69. if in.IsNil() {
  70. e.nilv()
  71. } else {
  72. e.marshal(tag, in.Elem())
  73. }
  74. case reflect.Struct:
  75. e.structv(tag, in)
  76. case reflect.Slice:
  77. e.slicev(tag, in)
  78. case reflect.String:
  79. e.stringv(tag, in)
  80. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  81. if in.Type() == durationType {
  82. e.stringv(tag, reflect.ValueOf(in.Interface().(time.Duration).String()))
  83. } else {
  84. e.intv(tag, in)
  85. }
  86. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  87. e.uintv(tag, in)
  88. case reflect.Float32, reflect.Float64:
  89. e.floatv(tag, in)
  90. case reflect.Bool:
  91. e.boolv(tag, in)
  92. default:
  93. panic("Can't marshal type yet: " + in.Type().String())
  94. }
  95. }
  96. func (e *encoder) mapv(tag string, in reflect.Value) {
  97. e.mappingv(tag, func() {
  98. keys := keyList(in.MapKeys())
  99. sort.Sort(keys)
  100. for _, k := range keys {
  101. e.marshal("", k)
  102. e.marshal("", in.MapIndex(k))
  103. }
  104. })
  105. }
  106. func (e *encoder) structv(tag string, in reflect.Value) {
  107. sinfo, err := getStructInfo(in.Type())
  108. if err != nil {
  109. panic(err)
  110. }
  111. e.mappingv(tag, func() {
  112. for _, info := range sinfo.FieldsList {
  113. var value reflect.Value
  114. if info.Inline == nil {
  115. value = in.Field(info.Num)
  116. } else {
  117. value = in.FieldByIndex(info.Inline)
  118. }
  119. if info.OmitEmpty && isZero(value) {
  120. continue
  121. }
  122. e.marshal("", reflect.ValueOf(info.Key))
  123. e.flow = info.Flow
  124. e.marshal("", value)
  125. }
  126. })
  127. }
  128. func (e *encoder) mappingv(tag string, f func()) {
  129. implicit := tag == ""
  130. style := yaml_BLOCK_MAPPING_STYLE
  131. if e.flow {
  132. e.flow = false
  133. style = yaml_FLOW_MAPPING_STYLE
  134. }
  135. e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
  136. e.emit()
  137. f()
  138. e.must(yaml_mapping_end_event_initialize(&e.event))
  139. e.emit()
  140. }
  141. func (e *encoder) slicev(tag string, in reflect.Value) {
  142. implicit := tag == ""
  143. style := yaml_BLOCK_SEQUENCE_STYLE
  144. if e.flow {
  145. e.flow = false
  146. style = yaml_FLOW_SEQUENCE_STYLE
  147. }
  148. e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
  149. e.emit()
  150. n := in.Len()
  151. for i := 0; i < n; i++ {
  152. e.marshal("", in.Index(i))
  153. }
  154. e.must(yaml_sequence_end_event_initialize(&e.event))
  155. e.emit()
  156. }
  157. func (e *encoder) stringv(tag string, in reflect.Value) {
  158. var style yaml_scalar_style_t
  159. s := in.String()
  160. if rtag, _ := resolve("", s); rtag != "!!str" {
  161. style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
  162. } else {
  163. style = yaml_PLAIN_SCALAR_STYLE
  164. }
  165. e.emitScalar(s, "", tag, style)
  166. }
  167. func (e *encoder) boolv(tag string, in reflect.Value) {
  168. var s string
  169. if in.Bool() {
  170. s = "true"
  171. } else {
  172. s = "false"
  173. }
  174. e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
  175. }
  176. func (e *encoder) intv(tag string, in reflect.Value) {
  177. s := strconv.FormatInt(in.Int(), 10)
  178. e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
  179. }
  180. func (e *encoder) uintv(tag string, in reflect.Value) {
  181. s := strconv.FormatUint(in.Uint(), 10)
  182. e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
  183. }
  184. func (e *encoder) floatv(tag string, in reflect.Value) {
  185. // FIXME: Handle 64 bits here.
  186. s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32)
  187. switch s {
  188. case "+Inf":
  189. s = ".inf"
  190. case "-Inf":
  191. s = "-.inf"
  192. case "NaN":
  193. s = ".nan"
  194. }
  195. e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
  196. }
  197. func (e *encoder) nilv() {
  198. e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
  199. }
  200. func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
  201. implicit := tag == ""
  202. if !implicit {
  203. style = yaml_PLAIN_SCALAR_STYLE
  204. }
  205. e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
  206. e.emit()
  207. }