serialize.go 5.9 KB

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