github.com/LagrangeDev/LagrangeGo@v0.0.0-20240512064304-ad4a85e10cb4/utils/binary/reader.go (about)

     1  package binary
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  	"strconv"
     7  	"unsafe"
     8  
     9  	"github.com/LagrangeDev/LagrangeGo/utils"
    10  )
    11  
    12  type Reader struct {
    13  	reader io.Reader
    14  	buffer []byte
    15  	pos    int
    16  }
    17  
    18  func ParseReader(reader io.Reader) *Reader {
    19  	return &Reader{
    20  		reader: reader,
    21  	}
    22  }
    23  
    24  func NewReader(buffer []byte) *Reader {
    25  	return &Reader{
    26  		buffer: buffer,
    27  	}
    28  }
    29  
    30  func (r *Reader) Len() int {
    31  	if r.reader != nil {
    32  		return -1
    33  	}
    34  	return len(r.buffer) - r.pos
    35  }
    36  
    37  // String means read all available data and return them as a string
    38  //
    39  // if r.reader got error, it will returns as err.Error()
    40  func (r *Reader) String() string {
    41  	if r.reader != nil {
    42  		data, err := io.ReadAll(r.reader)
    43  		if err != nil {
    44  			return err.Error()
    45  		}
    46  		return utils.B2S(data)
    47  	}
    48  	s := string(r.buffer[r.pos:])
    49  	r.pos = 0
    50  	r.buffer = r.buffer[:0]
    51  	return s
    52  }
    53  
    54  // ReadAll means read all available data and return them
    55  //
    56  // if r.reader got error, it will return nil
    57  func (r *Reader) ReadAll() []byte {
    58  	if r.reader != nil {
    59  		data, err := io.ReadAll(r.reader)
    60  		if err != nil {
    61  			return nil
    62  		}
    63  		return data
    64  	}
    65  	s := r.buffer[r.pos:]
    66  	r.pos = 0
    67  	r.buffer = r.buffer[:0]
    68  	buf := make([]byte, len(s))
    69  	copy(buf, s)
    70  	return s
    71  }
    72  
    73  func (r *Reader) ReadU8() (v uint8) {
    74  	if r.reader != nil {
    75  		_, _ = r.reader.Read(unsafe.Slice(&v, 1))
    76  		return
    77  	}
    78  	v = r.buffer[r.pos]
    79  	r.pos++
    80  	return
    81  }
    82  
    83  func readint[T ~uint16 | ~uint32 | ~uint64](r *Reader) (v T) {
    84  	sz := unsafe.Sizeof(v)
    85  	buf := make([]byte, 8)
    86  	if r.reader != nil {
    87  		_, _ = r.reader.Read(buf[8-sz:])
    88  	} else {
    89  		copy(buf[8-sz:], r.buffer[r.pos:r.pos+int(sz)])
    90  		r.pos += int(sz)
    91  	}
    92  	v = (T)(binary.BigEndian.Uint64(buf))
    93  	return
    94  }
    95  
    96  func (r *Reader) ReadU16() (v uint16) {
    97  	return readint[uint16](r)
    98  }
    99  
   100  func (r *Reader) ReadU32() (v uint32) {
   101  	return readint[uint32](r)
   102  }
   103  func (r *Reader) ReadU64() (v uint64) {
   104  	return readint[uint64](r)
   105  }
   106  
   107  func (r *Reader) SkipBytes(length int) {
   108  	if r.reader != nil {
   109  		_, _ = r.reader.Read(make([]byte, length))
   110  		return
   111  	}
   112  	r.pos += length
   113  }
   114  
   115  // ReadBytesNoCopy 不拷贝读取的数据, 用于读取后立即使用, 慎用
   116  //
   117  // 如需使用, 请确保 Reader 未被回收
   118  func (r *Reader) ReadBytesNoCopy(length int) (v []byte) {
   119  	if r.reader != nil {
   120  		return r.ReadBytes(length)
   121  	}
   122  	v = r.buffer[r.pos : r.pos+length]
   123  	r.pos += length
   124  	return
   125  }
   126  
   127  func (r *Reader) ReadBytes(length int) (v []byte) {
   128  	// 返回一个全新的数组罢
   129  	v = make([]byte, length)
   130  	if r.reader != nil {
   131  		_, _ = r.reader.Read(v)
   132  	} else {
   133  		copy(v, r.buffer[r.pos:r.pos+length])
   134  		r.pos += length
   135  	}
   136  	return
   137  }
   138  
   139  func (r *Reader) ReadString(length int) string {
   140  	return utils.B2S(r.ReadBytes(length))
   141  }
   142  
   143  func (r *Reader) SkipBytesWithLength(prefix string, withPerfix bool) {
   144  	var length int
   145  	switch prefix {
   146  	case "u8":
   147  		length = int(r.ReadU8())
   148  	case "u16":
   149  		length = int(r.ReadU16())
   150  	case "u32":
   151  		length = int(r.ReadU32())
   152  	case "u64":
   153  		length = int(r.ReadU64())
   154  	default:
   155  		panic("invaild prefix")
   156  	}
   157  	if withPerfix {
   158  		plus, err := strconv.Atoi(prefix[1:])
   159  		if err != nil {
   160  			panic(err)
   161  		}
   162  		length -= plus / 8
   163  	}
   164  	r.SkipBytes(length)
   165  }
   166  
   167  func (r *Reader) ReadBytesWithLength(prefix string, withPerfix bool) []byte {
   168  	var length int
   169  	switch prefix {
   170  	case "u8":
   171  		length = int(r.ReadU8())
   172  	case "u16":
   173  		length = int(r.ReadU16())
   174  	case "u32":
   175  		length = int(r.ReadU32())
   176  	case "u64":
   177  		length = int(r.ReadU64())
   178  	default:
   179  		panic("invaild prefix")
   180  	}
   181  	if withPerfix {
   182  		plus, err := strconv.Atoi(prefix[1:])
   183  		if err != nil {
   184  			panic(err)
   185  		}
   186  		length -= plus / 8
   187  	}
   188  	return r.ReadBytes(length)
   189  }
   190  
   191  func (r *Reader) ReadStringWithLength(prefix string, withPerfix bool) string {
   192  	return utils.B2S(r.ReadBytesWithLength(prefix, withPerfix))
   193  }
   194  
   195  func (r *Reader) ReadTlv() (result map[uint16][]byte) {
   196  	result = map[uint16][]byte{}
   197  	count := r.ReadU16()
   198  
   199  	for i := 0; i < int(count); i++ {
   200  		tag := r.ReadU16()
   201  		result[tag] = r.ReadBytes(int(r.ReadU16()))
   202  	}
   203  	return
   204  }
   205  
   206  func (r *Reader) ReadI8() (v int8) {
   207  	return int8(r.ReadU8())
   208  }
   209  
   210  func (r *Reader) ReadI16() (v int16) {
   211  	return int16(r.ReadU16())
   212  }
   213  
   214  func (r *Reader) ReadI32() (v int32) {
   215  	return int32(r.ReadU32())
   216  }
   217  
   218  func (r *Reader) ReadI64() (v int64) {
   219  	return int64(r.ReadU64())
   220  }