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 }