You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
2.8 KiB

  1. // Copyright 2015 go-swagger maintainers
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package runtime
  15. import (
  16. "bytes"
  17. "encoding"
  18. "errors"
  19. "fmt"
  20. "io"
  21. "reflect"
  22. "github.com/go-openapi/swag"
  23. )
  24. // TextConsumer creates a new text consumer
  25. func TextConsumer() Consumer {
  26. return ConsumerFunc(func(reader io.Reader, data interface{}) error {
  27. if reader == nil {
  28. return errors.New("TextConsumer requires a reader") // early exit
  29. }
  30. buf := new(bytes.Buffer)
  31. _, err := buf.ReadFrom(reader)
  32. if err != nil {
  33. return err
  34. }
  35. b := buf.Bytes()
  36. // If the buffer is empty, no need to unmarshal it, which causes a panic.
  37. if len(b) == 0 {
  38. data = ""
  39. return nil
  40. }
  41. if tu, ok := data.(encoding.TextUnmarshaler); ok {
  42. err := tu.UnmarshalText(b)
  43. if err != nil {
  44. return fmt.Errorf("text consumer: %v", err)
  45. }
  46. return nil
  47. }
  48. t := reflect.TypeOf(data)
  49. if data != nil && t.Kind() == reflect.Ptr {
  50. v := reflect.Indirect(reflect.ValueOf(data))
  51. if t.Elem().Kind() == reflect.String {
  52. v.SetString(string(b))
  53. return nil
  54. }
  55. }
  56. return fmt.Errorf("%v (%T) is not supported by the TextConsumer, %s",
  57. data, data, "can be resolved by supporting TextUnmarshaler interface")
  58. })
  59. }
  60. // TextProducer creates a new text producer
  61. func TextProducer() Producer {
  62. return ProducerFunc(func(writer io.Writer, data interface{}) error {
  63. if writer == nil {
  64. return errors.New("TextProducer requires a writer") // early exit
  65. }
  66. if data == nil {
  67. return errors.New("no data given to produce text from")
  68. }
  69. if tm, ok := data.(encoding.TextMarshaler); ok {
  70. txt, err := tm.MarshalText()
  71. if err != nil {
  72. return fmt.Errorf("text producer: %v", err)
  73. }
  74. _, err = writer.Write(txt)
  75. return err
  76. }
  77. if str, ok := data.(error); ok {
  78. _, err := writer.Write([]byte(str.Error()))
  79. return err
  80. }
  81. if str, ok := data.(fmt.Stringer); ok {
  82. _, err := writer.Write([]byte(str.String()))
  83. return err
  84. }
  85. v := reflect.Indirect(reflect.ValueOf(data))
  86. if t := v.Type(); t.Kind() == reflect.Struct || t.Kind() == reflect.Slice {
  87. b, err := swag.WriteJSON(data)
  88. if err != nil {
  89. return err
  90. }
  91. _, err = writer.Write(b)
  92. return err
  93. }
  94. if v.Kind() != reflect.String {
  95. return fmt.Errorf("%T is not a supported type by the TextProducer", data)
  96. }
  97. _, err := writer.Write([]byte(v.String()))
  98. return err
  99. })
  100. }