gitee.com/sy_183/go-common@v1.0.5-0.20231205030221-958cfe129b47/utils/io/op-writer.go (about)

     1  package io
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"gitee.com/sy_183/go-common/errors"
     7  	sliceUnsafe "gitee.com/sy_183/go-common/slice/unsafe"
     8  	stringUnsafe "gitee.com/sy_183/go-common/strings/unsafe"
     9  	unsafeUtil "gitee.com/sy_183/go-common/unsafe"
    10  	"io"
    11  	"math"
    12  	"unsafe"
    13  )
    14  
    15  type Data interface {
    16  	Bytes() []byte
    17  }
    18  
    19  const (
    20  	opTypeBytes = iota
    21  	opTypeString
    22  	opTypeEmbedded
    23  	opTypeWriter
    24  
    25  	bytesSize  = int(unsafe.Sizeof([]byte{}))
    26  	stringSize = int(unsafe.Sizeof(""))
    27  	byteSize   = 1
    28  	uint16Size = 2
    29  	uint32Size = 4
    30  	uint64Size = 8
    31  	writerSize = int(unsafe.Sizeof(io.WriterTo(nil)))
    32  
    33  	BytesOpSize  = 1 + bytesSize
    34  	StringOpSize = 1 + stringSize
    35  )
    36  
    37  type OpWriter struct {
    38  	opBuf  []byte
    39  	size   int
    40  	typ    uint8
    41  	typOff int
    42  	embLen uint16
    43  }
    44  
    45  func NewOpWriter(buf []byte) *OpWriter {
    46  	return &OpWriter{opBuf: buf[:0]}
    47  }
    48  
    49  func (w *OpWriter) SetBuf(buf []byte) *OpWriter {
    50  	w.opBuf = append(buf[:0], w.opBuf...)
    51  	return w
    52  }
    53  
    54  func (w *OpWriter) AppendBytes(bs []byte) *OpWriter {
    55  	w.typ, w.typOff = opTypeBytes, len(w.opBuf)
    56  	w.opBuf = append(append(w.opBuf, opTypeBytes),
    57  		sliceUnsafe.Build[byte](unsafeUtil.ToPointer(&bs), bytesSize, bytesSize)...)
    58  	w.size += len(bs)
    59  	return w
    60  }
    61  
    62  func (w *OpWriter) AppendString(s string) *OpWriter {
    63  	w.typ, w.typOff = opTypeString, len(w.opBuf)
    64  	w.opBuf = append(append(w.opBuf, opTypeString),
    65  		sliceUnsafe.Build[byte](unsafeUtil.ToPointer(&s), stringSize, stringSize)...)
    66  	w.size += len(s)
    67  	return w
    68  }
    69  
    70  func (w *OpWriter) AppendEmbeddedBytes(bs []byte) *OpWriter {
    71  	if len(bs) > math.MaxUint16 {
    72  		panic(errors.NewSizeOutOfRange("嵌入型数据", 0, math.MaxUint16, int64(len(bs)), true))
    73  	}
    74  	bsl := uint16(len(bs))
    75  	if w.typ != opTypeEmbedded || w.embLen+bsl > math.MaxUint16 {
    76  		w.typ, w.typOff, w.embLen = opTypeEmbedded, len(w.opBuf), bsl
    77  		w.opBuf = append(binary.LittleEndian.AppendUint16(append(w.opBuf, opTypeEmbedded), bsl), bs...)
    78  	} else {
    79  		w.opBuf = append(w.opBuf, bs...)
    80  		w.embLen += bsl
    81  		*unsafeUtil.ConvertPointer[byte, uint16](&w.opBuf[w.typOff+1]) = w.embLen
    82  	}
    83  	w.size += int(bsl)
    84  	return w
    85  }
    86  
    87  func (w *OpWriter) AppendEmbeddedString(s string) *OpWriter {
    88  	if len(s) > math.MaxUint16 {
    89  		panic(errors.NewSizeOutOfRange("嵌入型字符串", 0, math.MaxUint16, int64(len(s)), true))
    90  	}
    91  	sl := uint16(len(s))
    92  	if w.typ != opTypeEmbedded || w.embLen+sl > math.MaxUint16 {
    93  		w.typ, w.typOff, w.embLen = opTypeEmbedded, len(w.opBuf), sl
    94  		w.opBuf = append(binary.LittleEndian.AppendUint16(append(w.opBuf, opTypeEmbedded), sl), s...)
    95  	} else {
    96  		w.opBuf = append(w.opBuf, s...)
    97  		w.embLen += sl
    98  		*unsafeUtil.ConvertPointer[byte, uint16](&w.opBuf[w.typOff+1]) = w.embLen
    99  	}
   100  	w.size += int(sl)
   101  	return w
   102  }
   103  
   104  func (w *OpWriter) AppendByte(b byte) *OpWriter {
   105  	if w.typ != opTypeEmbedded || w.embLen+byteSize > math.MaxUint16 {
   106  		w.typ, w.typOff, w.embLen = opTypeEmbedded, len(w.opBuf), byteSize
   107  		w.opBuf = append(binary.LittleEndian.AppendUint16(append(w.opBuf, opTypeEmbedded), byteSize), b)
   108  	} else {
   109  		w.opBuf = append(w.opBuf, b)
   110  		w.embLen += byteSize
   111  		*unsafeUtil.ConvertPointer[byte, uint16](&w.opBuf[w.typOff+1]) = w.embLen
   112  	}
   113  	w.size += byteSize
   114  	return w
   115  }
   116  
   117  func (w *OpWriter) AppendUint16(u uint16) *OpWriter {
   118  	if w.typ != opTypeEmbedded || w.embLen+uint16Size > math.MaxUint16 {
   119  		w.typ, w.typOff, w.embLen = opTypeEmbedded, len(w.opBuf), uint16Size
   120  		w.opBuf = binary.LittleEndian.AppendUint16(binary.LittleEndian.AppendUint16(
   121  			append(w.opBuf, opTypeEmbedded), uint16Size), u)
   122  	} else {
   123  		w.opBuf = binary.LittleEndian.AppendUint16(w.opBuf, u)
   124  		w.embLen += uint16Size
   125  		*unsafeUtil.ConvertPointer[byte, uint16](&w.opBuf[w.typOff+1]) = w.embLen
   126  	}
   127  	w.size += uint16Size
   128  	return w
   129  }
   130  
   131  func (w *OpWriter) AppendUint32(u uint32) *OpWriter {
   132  	if w.typ != opTypeEmbedded || w.embLen+uint32Size > math.MaxUint16 {
   133  		w.typ, w.typOff, w.embLen = opTypeEmbedded, len(w.opBuf), uint32Size
   134  		w.opBuf = binary.LittleEndian.AppendUint32(binary.LittleEndian.AppendUint16(
   135  			append(w.opBuf, opTypeEmbedded), uint32Size), u)
   136  	} else {
   137  		w.opBuf = binary.LittleEndian.AppendUint32(w.opBuf, u)
   138  		w.embLen += uint32Size
   139  		*unsafeUtil.ConvertPointer[byte, uint16](&w.opBuf[w.typOff+1]) = w.embLen
   140  	}
   141  	w.size += uint32Size
   142  	return w
   143  }
   144  
   145  func (w *OpWriter) AppendUint64(u uint64) *OpWriter {
   146  	if w.typ != opTypeEmbedded || w.embLen+uint64Size > math.MaxUint16 {
   147  		w.typ, w.typOff, w.embLen = opTypeEmbedded, len(w.opBuf), uint64Size
   148  		w.opBuf = binary.LittleEndian.AppendUint64(binary.LittleEndian.AppendUint16(
   149  			append(w.opBuf, opTypeEmbedded), uint64Size), u)
   150  	} else {
   151  		w.opBuf = binary.LittleEndian.AppendUint64(w.opBuf, u)
   152  		w.embLen += uint64Size
   153  		*unsafeUtil.ConvertPointer[byte, uint16](&w.opBuf[w.typOff+1]) = w.embLen
   154  	}
   155  	w.size += uint64Size
   156  	return w
   157  }
   158  
   159  func OpWriterAppendEmbedded[T any](w *OpWriter, emb T) *OpWriter {
   160  	ss := unsafe.Sizeof(emb)
   161  	if ss > math.MaxUint16 {
   162  		panic(errors.NewSizeOutOfRange("嵌入型数据结构", 0, math.MaxUint16, int64(ss), true))
   163  	}
   164  	s := uint16(ss)
   165  	if w.typ != opTypeEmbedded || w.embLen+s > math.MaxUint16 {
   166  		w.typ, w.typOff, w.embLen = opTypeEmbedded, len(w.opBuf), s
   167  		w.opBuf = append(binary.LittleEndian.AppendUint16(append(w.opBuf, opTypeEmbedded), s),
   168  			sliceUnsafe.Build[byte](unsafeUtil.ToPointer(&emb), int(s), int(s))...)
   169  	} else {
   170  		w.opBuf = append(w.opBuf, sliceUnsafe.Build[byte](unsafeUtil.ToPointer(&emb), int(s), int(s))...)
   171  		w.embLen += s
   172  		*unsafeUtil.ConvertPointer[byte, uint16](&w.opBuf[w.typOff+1]) = w.embLen
   173  	}
   174  	w.size += int(s)
   175  	return w
   176  }
   177  
   178  func (w *OpWriter) AppendWriter(writer io.WriterTo, size int) *OpWriter {
   179  	if size < 0 {
   180  		panic(errors.NewSizeOutOfRange("Writer", 0, math.MinInt64, int64(size), true))
   181  	}
   182  	w.typ, w.typOff = opTypeWriter, len(w.opBuf)
   183  	w.opBuf = append(binary.LittleEndian.AppendUint64(append(w.opBuf, opTypeWriter), uint64(size)),
   184  		sliceUnsafe.Build[byte](unsafeUtil.ToPointer(&writer), writerSize, writerSize)...)
   185  	w.size += size
   186  	return w
   187  }
   188  
   189  func (w *OpWriter) Size() int {
   190  	return w.size
   191  }
   192  
   193  func (w *OpWriter) Bytes() []byte {
   194  	writer := Writer{Buf: make([]byte, w.Size())}
   195  	n, _ := w.WriteTo(&writer)
   196  	return writer.Buf[:n]
   197  }
   198  
   199  func (w *OpWriter) Read(p []byte) (n int, err error) {
   200  	writer := Writer{Buf: p}
   201  	_n, _ := w.WriteTo(&writer)
   202  	return int(_n), io.EOF
   203  }
   204  
   205  func (w *OpWriter) WriteTo(_w io.Writer) (n int64, err error) {
   206  	defer func() { err = HandleRecovery(recover()) }()
   207  	p := w.opBuf
   208  	for len(p) > 0 {
   209  		switch p[0] {
   210  		case opTypeBytes:
   211  			WritePanic(_w, unsafeUtil.ConvertFromPointer[byte, []byte](&p[1]), &n)
   212  			p = p[1+bytesSize:]
   213  		case opTypeString:
   214  			WritePanic(_w, stringUnsafe.Bytes(unsafeUtil.ConvertFromPointer[byte, string](&p[1])), &n)
   215  			p = p[1+stringSize:]
   216  		case opTypeEmbedded:
   217  			s := int(unsafeUtil.ConvertFromPointer[byte, uint16](&p[1]))
   218  			WritePanic(_w, sliceUnsafe.Build[byte](unsafeUtil.ToPointer(&p[1+uint16Size]), s, s), &n)
   219  			p = p[1+uint16Size+s:]
   220  		case opTypeWriter:
   221  			WriteToPanic(unsafeUtil.ConvertFromPointer[byte, io.WriterTo](&p[1+uint64Size]), _w, &n)
   222  			p = p[1+uint64Size+writerSize:]
   223  		default:
   224  			panic(fmt.Errorf("非法的操作类型(%d)", p[0]))
   225  		}
   226  	}
   227  	return
   228  }
   229  
   230  func (w *OpWriter) Reset() {
   231  	w.opBuf = w.opBuf[:0]
   232  	w.size = 0
   233  	w.typ = opTypeBytes
   234  	w.typOff = 0
   235  	w.embLen = 0
   236  }
   237  
   238  func (w *OpWriter) Clear() {
   239  	w.Reset()
   240  }