tools.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package rest
  2. import (
  3. "fmt"
  4. "io"
  5. "reflect"
  6. "git.ali33.ru/fcg-xvii/go-tools/json"
  7. )
  8. func prefixFieldName(prefix, fieldName string) string {
  9. if len(prefix) > 0 {
  10. return fmt.Sprintf("%s.%s", prefix, fieldName)
  11. }
  12. return fieldName
  13. }
  14. // конверторы
  15. // Int64ToBytes упаковывает int64 в срез байтов заданной длины
  16. func Int64ToBytes(num int64, byteCount int) []byte {
  17. bytes := make([]byte, byteCount)
  18. for i := 0; i < byteCount; i++ {
  19. shift := uint((byteCount - 1 - i) * 8)
  20. bytes[i] = byte(num >> shift)
  21. }
  22. return bytes
  23. }
  24. // BytesToInt64 конвертирует срез байтов в int64
  25. func BytesToInt64(bytes []byte) int64 {
  26. var num int64
  27. for _, b := range bytes {
  28. num = (num << 8) | int64(b)
  29. }
  30. return num
  31. }
  32. // ioError возвращает ошибку ввода выввода
  33. func ioError(field string, err error) IErrorArgs {
  34. return NewError(
  35. "ErrIO",
  36. json.Map{
  37. "field": field,
  38. "error": err.Error(),
  39. },
  40. )
  41. }
  42. // чтение
  43. // ReadBuf считывает срез заданного колличества байт и возвращает его
  44. func ReadBuf(r io.Reader, size int, field string) ([]byte, IErrorArgs) {
  45. buf := make([]byte, size)
  46. if _, err := r.Read(buf); err != nil {
  47. return nil, ioError(field, err)
  48. }
  49. return buf, nil
  50. }
  51. // ReadBufSize считывает размер байтового среза, затем сам срез и возвращает его.
  52. // lenSize - количество байтов, которыми описывается размер основного среза (см. ReadInt64)
  53. func ReadBufSize(r io.Reader, lenSize int, field string) ([]byte, IErrorArgs) {
  54. var size int64
  55. if err := ReadInt64(r, lenSize, field+"_size", &size); err != nil {
  56. return nil, err
  57. }
  58. buf, err := ReadBuf(r, int(size), field)
  59. return buf, err
  60. }
  61. // ReadInt64 Считывает срез заданного размера, который конвертируется в число типа int64.
  62. // size - размер среза (может быть от 1 до 8 байт).
  63. // Результат записывается в значение указателя result
  64. func ReadInt64(r io.Reader, size int, field string, result *int64) IErrorArgs {
  65. buf := make([]byte, size)
  66. if _, err := r.Read(buf); err != nil {
  67. return ioError(field, err)
  68. }
  69. *result = BytesToInt64(buf)
  70. return nil
  71. }
  72. // ReadString считывает строку (длина строки, затем строку), см. ReadBufSize
  73. func ReadString(r io.Reader, lenSize int, field string, result *string) IErrorArgs {
  74. strBuf, err := ReadBufSize(r, lenSize, field)
  75. if err != nil {
  76. return err
  77. }
  78. *result = string(strBuf)
  79. return nil
  80. }
  81. // ReadByte считывает 1 байт
  82. func ReadByte(r io.Reader, field string, result *byte) IErrorArgs {
  83. buf, err := ReadBuf(r, 1, field)
  84. if err != nil {
  85. return err
  86. }
  87. *result = buf[0]
  88. return nil
  89. }
  90. // запись
  91. // WriteBuf записывает срез байтов
  92. func WriteBuf(w io.Writer, buf []byte, field string) IErrorArgs {
  93. if _, err := w.Write(buf); err != nil {
  94. return ioError(field, err)
  95. }
  96. return nil
  97. }
  98. // WriteInt64 конвертирует число типа int64 в срез заданного размера и записывает его
  99. func WriteInt64(w io.Writer, val int64, size int, field string) IErrorArgs {
  100. buf := Int64ToBytes(val, size)
  101. return WriteBuf(w, buf, field)
  102. }
  103. // WriteString записывает строку в поток.
  104. // Сначала записывается размер строки (lenSize - количество байт в срезе размера).
  105. // Далее строка конвертируется в байтовый срез и записывается в поток
  106. func WriteString(w io.Writer, val, field string, lenSize int) IErrorArgs {
  107. // длина
  108. if err := WriteInt64(w, int64(len(val)), lenSize, field+"_size"); err != nil {
  109. return err
  110. }
  111. // строка
  112. if len(val) == 0 {
  113. return nil
  114. }
  115. return WriteBuf(w, []byte(val), field)
  116. }
  117. // WriteBuf записывает 1 байт в поток
  118. func WriteByte(w io.Writer, val byte, field string) IErrorArgs {
  119. return WriteBuf(w, []byte{val}, field)
  120. }
  121. // WriteBufSize записывает срез байтов в поток.
  122. // Сначала записывается размер среза (lenSize - количество байт в срезе размера).
  123. // Далее в поток записывается сам срез
  124. func WriteBufSize(w io.Writer, val []byte, lenSize int, field string) IErrorArgs {
  125. // длина
  126. if err := WriteInt64(w, int64(len(val)), lenSize, field+"_size"); err != nil {
  127. return err
  128. }
  129. // буфер
  130. return WriteBuf(w, val, field)
  131. }
  132. // ObjectFieldKeys позволяет рекурсивно получить список вложенных объектов запроса для предварительного формирования их в контексте ответа
  133. func ObjectFieldKeys(l []any) (res json.Map) {
  134. res = make(json.Map)
  135. t := reflect.TypeOf(res)
  136. for _, v := range l {
  137. rv := reflect.ValueOf(v)
  138. if reflect.ValueOf(v).Kind() == reflect.Map {
  139. if rv.CanConvert(t) {
  140. m := rv.Convert(t).Interface().(json.Map)
  141. if name := m.String("name", ""); len(name) > 0 {
  142. res[name] = ObjectFieldKeys(m.Slice("fields", []any{}))
  143. }
  144. }
  145. }
  146. }
  147. return
  148. }