github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/binary/jce/writer.go (about)

     1  package jce
     2  
     3  import (
     4  	"bytes"
     5  	goBinary "encoding/binary"
     6  	"math"
     7  )
     8  
     9  type JceWriter struct {
    10  	buf *bytes.Buffer
    11  }
    12  
    13  func NewJceWriter() *JceWriter {
    14  	return &JceWriter{buf: new(bytes.Buffer)}
    15  }
    16  
    17  func (w *JceWriter) writeHead(t, tag byte) {
    18  	if tag < 0xF {
    19  		w.buf.WriteByte(tag<<4 | t)
    20  	} else {
    21  		w.buf.WriteByte(0xF0 | t)
    22  		w.buf.WriteByte(tag)
    23  	}
    24  }
    25  
    26  func (w *JceWriter) WriteByte(b, tag byte) *JceWriter {
    27  	if b == 0 {
    28  		w.writeHead(12, tag)
    29  	} else {
    30  		w.writeHead(0, tag)
    31  		w.buf.WriteByte(b)
    32  	}
    33  	return w
    34  }
    35  
    36  func (w *JceWriter) WriteBool(b bool, tag byte) {
    37  	var by byte
    38  	if b {
    39  		by = 1
    40  	}
    41  	w.WriteByte(by, tag)
    42  }
    43  
    44  func (w *JceWriter) WriteInt16(n int16, tag byte) {
    45  	switch {
    46  	case n >= -128 && n <= 127:
    47  		w.WriteByte(byte(n), tag)
    48  	default:
    49  		w.putInt16(n, tag)
    50  	}
    51  }
    52  
    53  //go:nosplit
    54  func (w *JceWriter) putInt16(n int16, tag byte) {
    55  	w.writeHead(1, tag)
    56  	var buf [2]byte
    57  	goBinary.BigEndian.PutUint16(buf[:], uint16(n))
    58  	w.buf.Write(buf[:])
    59  }
    60  
    61  func (w *JceWriter) WriteInt32(n int32, tag byte) *JceWriter {
    62  	switch {
    63  	case n >= -128 && n <= 127:
    64  		w.WriteByte(byte(n), tag)
    65  	case n >= -32768 && n <= 32767:
    66  		w.putInt16(int16(n), tag)
    67  	default:
    68  		w.putInt32(n, tag)
    69  	}
    70  	return w
    71  }
    72  
    73  //go:nosplit
    74  func (w *JceWriter) putInt32(n int32, tag byte) {
    75  	w.writeHead(2, tag)
    76  	var buf [4]byte
    77  	goBinary.BigEndian.PutUint32(buf[:], uint32(n))
    78  	w.buf.Write(buf[:])
    79  }
    80  
    81  func (w *JceWriter) WriteInt64(n int64, tag byte) *JceWriter {
    82  	switch {
    83  	case n >= -128 && n <= 127:
    84  		w.WriteByte(byte(n), tag)
    85  	case n >= -32768 && n <= 32767:
    86  		w.putInt16(int16(n), tag)
    87  	case n >= -2147483648 && n <= 2147483647:
    88  		w.putInt32(int32(n), tag)
    89  	default:
    90  		w.putInt64(n, tag)
    91  	}
    92  	return w
    93  }
    94  
    95  //go:nosplit
    96  func (w *JceWriter) putInt64(n int64, tag byte) {
    97  	w.writeHead(3, tag)
    98  	var buf [8]byte
    99  	goBinary.BigEndian.PutUint64(buf[:], uint64(n))
   100  	w.buf.Write(buf[:])
   101  }
   102  
   103  //go:nosplit
   104  func (w *JceWriter) WriteFloat32(n float32, tag byte) {
   105  	w.writeHead(4, tag)
   106  	var buf [4]byte
   107  	goBinary.BigEndian.PutUint32(buf[:], math.Float32bits(n))
   108  	w.buf.Write(buf[:])
   109  }
   110  
   111  //go:nosplit
   112  func (w *JceWriter) WriteFloat64(n float64, tag byte) {
   113  	w.writeHead(5, tag)
   114  	var buf [8]byte
   115  	goBinary.BigEndian.PutUint64(buf[:], math.Float64bits(n))
   116  	w.buf.Write(buf[:])
   117  }
   118  
   119  func (w *JceWriter) WriteString(s string, tag byte) *JceWriter {
   120  	if len(s) > 255 {
   121  		w.writeHead(7, tag)
   122  		var buf [4]byte
   123  		goBinary.BigEndian.PutUint32(buf[:], uint32(len(s)))
   124  		w.buf.Write(buf[:])
   125  		w.buf.WriteString(s)
   126  		return w
   127  	}
   128  	w.writeHead(6, tag)
   129  	w.buf.WriteByte(byte(len(s)))
   130  	w.buf.WriteString(s)
   131  	return w
   132  }
   133  
   134  func (w *JceWriter) WriteBytes(l []byte, tag byte) *JceWriter {
   135  	w.writeHead(13, tag)
   136  	w.buf.WriteByte(0) // w.writeHead(0, 0)
   137  	w.WriteInt32(int32(len(l)), 0)
   138  	w.buf.Write(l)
   139  	return w
   140  }
   141  
   142  func (w *JceWriter) WriteInt64Slice(l []int64, tag byte) {
   143  	w.writeHead(9, tag)
   144  	if len(l) == 0 {
   145  		w.writeHead(12, 0) // w.WriteInt32(0, 0)
   146  		return
   147  	}
   148  	w.WriteInt32(int32(len(l)), 0)
   149  	for _, v := range l {
   150  		w.WriteInt64(v, 0)
   151  	}
   152  }
   153  
   154  func (w *JceWriter) WriteBytesSlice(l [][]byte, tag byte) {
   155  	w.writeHead(9, tag)
   156  	if len(l) == 0 {
   157  		w.writeHead(12, 0) // w.WriteInt32(0, 0)
   158  		return
   159  	}
   160  	w.WriteInt32(int32(len(l)), 0)
   161  	for _, v := range l {
   162  		w.WriteBytes(v, 0)
   163  	}
   164  }
   165  
   166  func (w *JceWriter) writeMapStrStr(m map[string]string, tag byte) {
   167  	if m == nil {
   168  		w.writeHead(8, tag)
   169  		w.writeHead(12, 0) // w.WriteInt32(0, 0)
   170  		return
   171  	}
   172  	w.writeHead(8, tag)
   173  	w.WriteInt32(int32(len(m)), 0)
   174  	for k, v := range m {
   175  		w.WriteString(k, 0)
   176  		w.WriteString(v, 1)
   177  	}
   178  }
   179  
   180  func (w *JceWriter) writeMapStrBytes(m map[string][]byte, tag byte) {
   181  	if m == nil {
   182  		w.writeHead(8, tag)
   183  		w.writeHead(12, 0) // w.WriteInt32(0, 0)
   184  		return
   185  	}
   186  	w.writeHead(8, tag)
   187  	w.WriteInt32(int32(len(m)), 0)
   188  	for k, v := range m {
   189  		w.WriteString(k, 0)
   190  		w.WriteBytes(v, 1)
   191  	}
   192  }
   193  
   194  func (w *JceWriter) writeMapStrMapStrBytes(m map[string]map[string][]byte, tag byte) {
   195  	if m == nil {
   196  		w.writeHead(8, tag)
   197  		w.writeHead(12, 0) // w.WriteInt32(0, 0)
   198  		return
   199  	}
   200  	w.writeHead(8, tag)
   201  	w.WriteInt32(int32(len(m)), 0)
   202  	for k, v := range m {
   203  		w.WriteString(k, 0)
   204  		w.writeMapStrBytes(v, 1)
   205  	}
   206  }
   207  
   208  func (w *JceWriter) Bytes() []byte {
   209  	return w.buf.Bytes()
   210  }