gitea

Development moved to Codeberg

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99
  100. 100
  101. 101
  102. 102
  103. 103
  104. 104
  105. 105
  106. 106
  107. 107
  108. 108
  109. 109
  110. 110
  111. 111
  112. 112
  113. 113
  114. 114
  115. 115
  116. 116
  117. 117
// Copyright 2015 go-swagger maintainers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package runtime

import (
	"bytes"
	"encoding"
	"errors"
	"fmt"
	"io"
	"reflect"

	"github.com/go-openapi/swag"
)

// TextConsumer creates a new text consumer
func TextConsumer() Consumer {
	return ConsumerFunc(func(reader io.Reader, data interface{}) error {
		if reader == nil {
			return errors.New("TextConsumer requires a reader") // early exit
		}

		buf := new(bytes.Buffer)
		_, err := buf.ReadFrom(reader)
		if err != nil {
			return err
		}
		b := buf.Bytes()

		// If the buffer is empty, no need to unmarshal it, which causes a panic.
		if len(b) == 0 {
			data = ""
			return nil
		}

		if tu, ok := data.(encoding.TextUnmarshaler); ok {
			err := tu.UnmarshalText(b)
			if err != nil {
				return fmt.Errorf("text consumer: %v", err)
			}

			return nil
		}

		t := reflect.TypeOf(data)
		if data != nil && t.Kind() == reflect.Ptr {
			v := reflect.Indirect(reflect.ValueOf(data))
			if t.Elem().Kind() == reflect.String {
				v.SetString(string(b))
				return nil
			}
		}

		return fmt.Errorf("%v (%T) is not supported by the TextConsumer, %s",
			data, data, "can be resolved by supporting TextUnmarshaler interface")
	})
}

// TextProducer creates a new text producer
func TextProducer() Producer {
	return ProducerFunc(func(writer io.Writer, data interface{}) error {
		if writer == nil {
			return errors.New("TextProducer requires a writer") // early exit
		}

		if data == nil {
			return errors.New("no data given to produce text from")
		}

		if tm, ok := data.(encoding.TextMarshaler); ok {
			txt, err := tm.MarshalText()
			if err != nil {
				return fmt.Errorf("text producer: %v", err)
			}
			_, err = writer.Write(txt)
			return err
		}

		if str, ok := data.(error); ok {
			_, err := writer.Write([]byte(str.Error()))
			return err
		}

		if str, ok := data.(fmt.Stringer); ok {
			_, err := writer.Write([]byte(str.String()))
			return err
		}

		v := reflect.Indirect(reflect.ValueOf(data))
		if t := v.Type(); t.Kind() == reflect.Struct || t.Kind() == reflect.Slice {
			b, err := swag.WriteJSON(data)
			if err != nil {
				return err
			}
			_, err = writer.Write(b)
			return err
		}
		if v.Kind() != reflect.String {
			return fmt.Errorf("%T is not a supported type by the TextProducer", data)
		}

		_, err := writer.Write([]byte(v.String()))
		return err
	})
}