tools.go 5.1 KB

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