serialize.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. package cli
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "git.nspix.com/golang/kos/util/pool"
  7. "github.com/mattn/go-runewidth"
  8. "reflect"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. func isNormalKind(kind reflect.Kind) bool {
  14. normalKinds := []reflect.Kind{
  15. reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
  16. reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
  17. reflect.Float32, reflect.Float64,
  18. reflect.String,
  19. }
  20. for _, k := range normalKinds {
  21. if k == kind {
  22. return true
  23. }
  24. }
  25. return false
  26. }
  27. func serializeMap(val map[any]any) ([]byte, error) {
  28. var (
  29. canFormat bool
  30. width int
  31. maxWidth int
  32. )
  33. canFormat = true
  34. for k, v := range val {
  35. if !isNormalKind(reflect.Indirect(reflect.ValueOf(k)).Kind()) || !isNormalKind(reflect.Indirect(reflect.ValueOf(v)).Kind()) {
  36. canFormat = false
  37. break
  38. }
  39. }
  40. if !canFormat {
  41. return json.MarshalIndent(val, "", "\t")
  42. }
  43. ms := make(map[string]string)
  44. for k, v := range val {
  45. sk := fmt.Sprint(k)
  46. ms[sk] = fmt.Sprint(v)
  47. width = runewidth.StringWidth(sk)
  48. if width > maxWidth {
  49. maxWidth = width
  50. }
  51. }
  52. buffer := pool.GetBuffer()
  53. defer pool.PutBuffer(buffer)
  54. for k, v := range ms {
  55. buffer.WriteString(fmt.Sprintf("%-"+strconv.Itoa(maxWidth+4)+"s %s\n", k, v))
  56. }
  57. return buffer.Bytes(), nil
  58. }
  59. func printBorder(w *bytes.Buffer, ws []int) {
  60. for _, l := range ws {
  61. w.WriteString("+")
  62. w.WriteString(strings.Repeat("-", l+2))
  63. }
  64. w.WriteString("+\n")
  65. }
  66. func toString(v any) string {
  67. switch t := v.(type) {
  68. case float32, float64:
  69. return fmt.Sprintf("%.2f", t)
  70. case time.Time:
  71. return t.Format("2006-01-02 15:04:05")
  72. default:
  73. return fmt.Sprint(v)
  74. }
  75. }
  76. func printArray(vals [][]any) (buf []byte) {
  77. var (
  78. cell string
  79. str string
  80. widths []int
  81. maxLength int
  82. width int
  83. rows [][]string
  84. )
  85. rows = make([][]string, 0, len(vals))
  86. for _, value := range vals {
  87. if len(value) > maxLength {
  88. maxLength = len(value)
  89. }
  90. }
  91. widths = make([]int, maxLength)
  92. for _, vs := range vals {
  93. rl := len(vs)
  94. row := make([]string, rl)
  95. for i, val := range vs {
  96. str = toString(val)
  97. if rl > 1 {
  98. width = runewidth.StringWidth(str)
  99. if width > widths[i] {
  100. widths[i] = width
  101. }
  102. }
  103. row[i] = str
  104. }
  105. rows = append(rows, row)
  106. }
  107. buffer := pool.GetBuffer()
  108. defer pool.PutBuffer(buffer)
  109. printBorder(buffer, widths)
  110. for index, row := range rows {
  111. size := len(row)
  112. for i, w := range widths {
  113. cell = ""
  114. buffer.WriteString("|")
  115. if size > i {
  116. cell = row[i]
  117. }
  118. buffer.WriteString(" ")
  119. buffer.WriteString(cell)
  120. cl := runewidth.StringWidth(cell)
  121. if w > cl {
  122. buffer.WriteString(strings.Repeat(" ", w-cl))
  123. }
  124. buffer.WriteString(" ")
  125. }
  126. buffer.WriteString("|\n")
  127. if index == 0 {
  128. printBorder(buffer, widths)
  129. }
  130. }
  131. printBorder(buffer, widths)
  132. return buffer.Bytes()
  133. }
  134. func serializeArray(val []any) (buf []byte, err error) {
  135. var (
  136. ok bool
  137. vs [][]any
  138. normalFormat bool
  139. isArrayElement bool
  140. isStructElement bool
  141. columnName string
  142. )
  143. normalFormat = true
  144. for _, row := range val {
  145. kind := reflect.Indirect(reflect.ValueOf(row)).Kind()
  146. if !isNormalKind(kind) {
  147. normalFormat = false
  148. }
  149. if kind == reflect.Array || kind == reflect.Slice {
  150. isArrayElement = true
  151. }
  152. if kind == reflect.Struct {
  153. isStructElement = true
  154. }
  155. }
  156. if normalFormat {
  157. goto __END
  158. }
  159. if isArrayElement {
  160. vs = make([][]any, 0, len(val))
  161. for _, v := range val {
  162. rv := reflect.Indirect(reflect.ValueOf(v))
  163. if rv.Kind() == reflect.Array || rv.Kind() == reflect.Slice {
  164. row := make([]any, 0, rv.Len())
  165. for i := 0; i < rv.Len(); i++ {
  166. if isNormalKind(rv.Index(i).Kind()) || rv.Index(i).Interface() == nil {
  167. row = append(row, rv.Index(i).Interface())
  168. } else {
  169. goto __END
  170. }
  171. }
  172. vs = append(vs, row)
  173. } else {
  174. goto __END
  175. }
  176. }
  177. }
  178. if isStructElement {
  179. vs = make([][]any, 0, len(val))
  180. for i, v := range val {
  181. rv := reflect.Indirect(reflect.ValueOf(v))
  182. if rv.Kind() == reflect.Struct {
  183. if i == 0 {
  184. row := make([]any, 0, rv.Type().NumField())
  185. for j := 0; j < rv.Type().NumField(); j++ {
  186. st := rv.Type().Field(j).Tag
  187. if columnName, ok = st.Lookup("name"); !ok {
  188. columnName = strings.ToUpper(rv.Type().Field(j).Name)
  189. }
  190. row = append(row, columnName)
  191. }
  192. vs = append(vs, row)
  193. }
  194. row := make([]any, 0, rv.Type().NumField())
  195. for j := 0; j < rv.Type().NumField(); j++ {
  196. row = append(row, rv.Field(j).Interface())
  197. }
  198. vs = append(vs, row)
  199. } else {
  200. goto __END
  201. }
  202. }
  203. }
  204. buf = printArray(vs)
  205. return
  206. __END:
  207. return json.MarshalIndent(val, "", "\t")
  208. }
  209. func serialize(val any) (buf []byte, err error) {
  210. var (
  211. refVal reflect.Value
  212. )
  213. refVal = reflect.Indirect(reflect.ValueOf(val))
  214. switch refVal.Kind() {
  215. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  216. buf = []byte(strconv.FormatInt(refVal.Int(), 10))
  217. case reflect.Float32, reflect.Float64:
  218. buf = []byte(strconv.FormatFloat(refVal.Float(), 'f', -1, 64))
  219. case reflect.String:
  220. buf = []byte(refVal.String())
  221. case reflect.Slice, reflect.Array:
  222. if refVal.Type().Elem().Kind() == reflect.Uint8 {
  223. buf = refVal.Bytes()
  224. } else {
  225. as := make([]any, 0, refVal.Len())
  226. for i := 0; i < refVal.Len(); i++ {
  227. as = append(as, refVal.Index(i).Interface())
  228. }
  229. buf, err = serializeArray(as)
  230. }
  231. case reflect.Map:
  232. ms := make(map[any]any)
  233. keys := refVal.MapKeys()
  234. for _, key := range keys {
  235. ms[key.Interface()] = refVal.MapIndex(key).Interface()
  236. }
  237. buf, err = serializeMap(ms)
  238. default:
  239. buf, err = json.MarshalIndent(refVal.Interface(), "", "\t")
  240. }
  241. return
  242. }