mirror of
				https://github.com/openobserve/goflow2.git
				synced 2025-11-04 05:53:14 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			129 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package utils
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/binary"
 | 
						|
	"errors"
 | 
						|
	"io"
 | 
						|
	"reflect"
 | 
						|
)
 | 
						|
 | 
						|
type BytesBuffer interface {
 | 
						|
	io.Reader
 | 
						|
	Next(int) []byte
 | 
						|
}
 | 
						|
 | 
						|
func BinaryDecoder(payload *bytes.Buffer, dests ...interface{}) error {
 | 
						|
	for _, dest := range dests {
 | 
						|
		err := BinaryRead(payload, binary.BigEndian, dest)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
func BinaryRead(payload BytesBuffer, order binary.ByteOrder, data any) error {
 | 
						|
	// Fast path for basic types and slices.
 | 
						|
	if n := intDataSize(data); n != 0 {
 | 
						|
		bs := payload.Next(n)
 | 
						|
		if len(bs) < n {
 | 
						|
			return io.ErrUnexpectedEOF
 | 
						|
		}
 | 
						|
		switch data := data.(type) {
 | 
						|
		case *bool:
 | 
						|
			*data = bs[0] != 0
 | 
						|
		case *int8:
 | 
						|
			*data = int8(bs[0])
 | 
						|
		case *uint8:
 | 
						|
			*data = bs[0]
 | 
						|
		case *int16:
 | 
						|
			*data = int16(order.Uint16(bs))
 | 
						|
		case *uint16:
 | 
						|
			*data = order.Uint16(bs)
 | 
						|
		case *int32:
 | 
						|
			*data = int32(order.Uint32(bs))
 | 
						|
		case *uint32:
 | 
						|
			*data = order.Uint32(bs)
 | 
						|
		case *int64:
 | 
						|
			*data = int64(order.Uint64(bs))
 | 
						|
		case *uint64:
 | 
						|
			*data = order.Uint64(bs)
 | 
						|
		case []bool:
 | 
						|
			for i, x := range bs { // Easier to loop over the input for 8-bit values.
 | 
						|
				data[i] = x != 0
 | 
						|
			}
 | 
						|
		case []int8:
 | 
						|
			for i, x := range bs {
 | 
						|
				data[i] = int8(x)
 | 
						|
			}
 | 
						|
		case []uint8:
 | 
						|
			copy(data, bs)
 | 
						|
		case []int16:
 | 
						|
			for i := range data {
 | 
						|
				data[i] = int16(order.Uint16(bs[2*i:]))
 | 
						|
			}
 | 
						|
		case []uint16:
 | 
						|
			for i := range data {
 | 
						|
				data[i] = order.Uint16(bs[2*i:])
 | 
						|
			}
 | 
						|
		case []int32:
 | 
						|
			for i := range data {
 | 
						|
				data[i] = int32(order.Uint32(bs[4*i:]))
 | 
						|
			}
 | 
						|
		case []uint32:
 | 
						|
			for i := range data {
 | 
						|
				data[i] = order.Uint32(bs[4*i:])
 | 
						|
			}
 | 
						|
		case []int64:
 | 
						|
			for i := range data {
 | 
						|
				data[i] = int64(order.Uint64(bs[8*i:]))
 | 
						|
			}
 | 
						|
		case []uint64:
 | 
						|
			for i := range data {
 | 
						|
				data[i] = order.Uint64(bs[8*i:])
 | 
						|
			}
 | 
						|
		default:
 | 
						|
			n = 0 // fast path doesn't apply
 | 
						|
		}
 | 
						|
		if n != 0 {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
 | 
						|
}
 | 
						|
 | 
						|
// intDataSize returns the size of the data required to represent the data when encoded.
 | 
						|
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
 | 
						|
func intDataSize(data any) int {
 | 
						|
	switch data := data.(type) {
 | 
						|
	case bool, int8, uint8, *bool, *int8, *uint8:
 | 
						|
		return 1
 | 
						|
	case []bool:
 | 
						|
		return len(data)
 | 
						|
	case []int8:
 | 
						|
		return len(data)
 | 
						|
	case []uint8:
 | 
						|
		return len(data)
 | 
						|
	case int16, uint16, *int16, *uint16:
 | 
						|
		return 2
 | 
						|
	case []int16:
 | 
						|
		return 2 * len(data)
 | 
						|
	case []uint16:
 | 
						|
		return 2 * len(data)
 | 
						|
	case int32, uint32, *int32, *uint32:
 | 
						|
		return 4
 | 
						|
	case []int32:
 | 
						|
		return 4 * len(data)
 | 
						|
	case []uint32:
 | 
						|
		return 4 * len(data)
 | 
						|
	case int64, uint64, *int64, *uint64:
 | 
						|
		return 8
 | 
						|
	case []int64:
 | 
						|
		return 8 * len(data)
 | 
						|
	case []uint64:
 | 
						|
		return 8 * len(data)
 | 
						|
	}
 | 
						|
	return 0
 | 
						|
}
 |