123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- package rest
- import (
- "fmt"
- "io"
- "reflect"
- "git.ali33.ru/fcg-xvii/go-tools/json"
- )
- func prefixFieldName(prefix, fieldName string) string {
- if len(prefix) > 0 {
- return fmt.Sprintf("%s.%s", prefix, fieldName)
- }
- return fieldName
- }
- // конверторы
- // Int64ToBytes упаковывает int64 в срез байтов заданной длины
- func Int64ToBytes(num int64, byteCount int) []byte {
- bytes := make([]byte, byteCount)
- for i := 0; i < byteCount; i++ {
- shift := uint((byteCount - 1 - i) * 8)
- bytes[i] = byte(num >> shift)
- }
- return bytes
- }
- // BytesToInt64 конвертирует срез байтов в int64
- func BytesToInt64(bytes []byte) int64 {
- var num int64
- for _, b := range bytes {
- num = (num << 8) | int64(b)
- }
- return num
- }
- // ioError возвращает ошибку ввода выввода
- func ioError(field string, err error) IErrorArgs {
- return NewError(
- "ErrIO",
- json.Map{
- "field": field,
- "error": err.Error(),
- },
- )
- }
- // чтение
- // ReadBuf считывает срез заданного колличества байт и возвращает его
- func ReadBuf(r io.Reader, size int, field string) ([]byte, IErrorArgs) {
- buf := make([]byte, size)
- if _, err := r.Read(buf); err != nil {
- return nil, ioError(field, err)
- }
- return buf, nil
- }
- // ReadBufSize считывает размер байтового среза, затем сам срез и возвращает его.
- // lenSize - количество байтов, которыми описывается размер основного среза (см. ReadInt64)
- func ReadBufSize(r io.Reader, lenSize int, field string) ([]byte, IErrorArgs) {
- var size int64
- if err := ReadInt64(r, lenSize, field+"_size", &size); err != nil {
- return nil, err
- }
- buf, err := ReadBuf(r, int(size), field)
- return buf, err
- }
- // ReadInt64 Считывает срез заданного размера, который конвертируется в число типа int64.
- // size - размер среза (может быть от 1 до 8 байт).
- // Результат записывается в значение указателя result
- func ReadInt64(r io.Reader, size int, field string, result *int64) IErrorArgs {
- buf := make([]byte, size)
- if _, err := r.Read(buf); err != nil {
- return ioError(field, err)
- }
- *result = BytesToInt64(buf)
- return nil
- }
- // ReadString считывает строку (длина строки, затем строку), см. ReadBufSize
- func ReadString(r io.Reader, lenSize int, field string, result *string) IErrorArgs {
- strBuf, err := ReadBufSize(r, lenSize, field)
- if err != nil {
- return err
- }
- *result = string(strBuf)
- return nil
- }
- // ReadByte считывает 1 байт
- func ReadByte(r io.Reader, field string, result *byte) IErrorArgs {
- buf, err := ReadBuf(r, 1, field)
- if err != nil {
- return err
- }
- *result = buf[0]
- return nil
- }
- // запись
- // WriteBuf записывает срез байтов
- func WriteBuf(w io.Writer, buf []byte, field string) IErrorArgs {
- if _, err := w.Write(buf); err != nil {
- return ioError(field, err)
- }
- return nil
- }
- // WriteInt64 конвертирует число типа int64 в срез заданного размера и записывает его
- func WriteInt64(w io.Writer, val int64, size int, field string) IErrorArgs {
- buf := Int64ToBytes(val, size)
- return WriteBuf(w, buf, field)
- }
- // WriteString записывает строку в поток.
- // Сначала записывается размер строки (lenSize - количество байт в срезе размера).
- // Далее строка конвертируется в байтовый срез и записывается в поток
- func WriteString(w io.Writer, val, field string, lenSize int) IErrorArgs {
- // длина
- if err := WriteInt64(w, int64(len(val)), lenSize, field+"_size"); err != nil {
- return err
- }
- // строка
- if len(val) == 0 {
- return nil
- }
- return WriteBuf(w, []byte(val), field)
- }
- // WriteBuf записывает 1 байт в поток
- func WriteByte(w io.Writer, val byte, field string) IErrorArgs {
- return WriteBuf(w, []byte{val}, field)
- }
- // WriteBufSize записывает срез байтов в поток.
- // Сначала записывается размер среза (lenSize - количество байт в срезе размера).
- // Далее в поток записывается сам срез
- func WriteBufSize(w io.Writer, val []byte, lenSize int, field string) IErrorArgs {
- // длина
- if err := WriteInt64(w, int64(len(val)), lenSize, field+"_size"); err != nil {
- return err
- }
- // буфер
- return WriteBuf(w, val, field)
- }
- // ObjectFieldKeys позволяет рекурсивно получить список вложенных объектов запроса для предварительного формирования их в контексте ответа
- func ObjectFieldKeys(l []any) (res json.Map) {
- res = make(json.Map)
- t := reflect.TypeOf(res)
- for _, v := range l {
- rv := reflect.ValueOf(v)
- if reflect.ValueOf(v).Kind() == reflect.Map {
- if rv.CanConvert(t) {
- m := rv.Convert(t).Interface().(json.Map)
- if name := m.String("name", ""); len(name) > 0 {
- res[name] = ObjectFieldKeys(m.Slice("fields", []any{}))
- }
- }
- }
- }
- return
- }
|