mirror of
https://github.com/fumiama/go-simple-protobuf.git
synced 2026-06-20 02:40:42 +08:00
feat: add writer
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
# go-simple-protobuf
|
# go-simple-protobuf
|
||||||
> Note: Only supports reading.
|
|
||||||
|
|
||||||
Golang implementation of [simple-protobuf](https://github.com/fumiama/simple-protobuf)
|
Golang implementation of [simple-protobuf](https://github.com/fumiama/simple-protobuf)
|
||||||
|
|||||||
10
reader.go
10
reader.go
@@ -65,3 +65,13 @@ func (it *Iterator) Bytes() []byte {
|
|||||||
func (it *Iterator) String() string {
|
func (it *Iterator) String() string {
|
||||||
return string(it.v)
|
return string(it.v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cap structlen 结构体带 padding 的长度
|
||||||
|
func (it *Iterator) Cap() uint32 {
|
||||||
|
return it.structlen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len reallen (迭代器目前迭代到的实值总长, 不带 padding)
|
||||||
|
func (it *Iterator) Len() uint32 {
|
||||||
|
return it.reallen
|
||||||
|
}
|
||||||
|
|||||||
35
spb.go
35
spb.go
@@ -2,41 +2,6 @@ package spb
|
|||||||
|
|
||||||
import "io"
|
import "io"
|
||||||
|
|
||||||
func ReadNum(r io.Reader) (n uint32, cnt uint32, err error) {
|
|
||||||
var buf [1]byte
|
|
||||||
for cnt < 5 {
|
|
||||||
_, err = r.Read(buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n |= uint32(buf[0]&0x7f) << (7 * cnt)
|
|
||||||
cnt++
|
|
||||||
if buf[0]&0x80 == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func WriteNum(w io.Writer, n uint32) (cnt int, err error) {
|
|
||||||
var buf [1]byte
|
|
||||||
for n > 0 {
|
|
||||||
buf[0] = uint8(n & 0x7f)
|
|
||||||
if n>>7 > 0 {
|
|
||||||
buf[0] |= 0x80
|
|
||||||
}
|
|
||||||
_, err = w.Write(buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n >>= 7
|
|
||||||
cnt++
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
type SimplePB struct {
|
type SimplePB struct {
|
||||||
StructLen, RealLen uint32
|
StructLen, RealLen uint32
|
||||||
Target [][]byte
|
Target [][]byte
|
||||||
|
|||||||
36
utils.go
Normal file
36
utils.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package spb
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
func ReadNum(r io.Reader) (n uint32, cnt uint32, err error) {
|
||||||
|
var buf [1]byte
|
||||||
|
for cnt < 5 {
|
||||||
|
_, err = r.Read(buf[:])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n |= uint32(buf[0]&0x7f) << (7 * cnt)
|
||||||
|
cnt++
|
||||||
|
if buf[0]&0x80 == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteNum(w io.Writer, n uint32) (cnt uint32, err error) {
|
||||||
|
var buf [1]byte
|
||||||
|
for n > 0 {
|
||||||
|
buf[0] = uint8(n & 0x7f)
|
||||||
|
if n>>7 > 0 {
|
||||||
|
buf[0] |= 0x80
|
||||||
|
}
|
||||||
|
_, err = w.Write(buf[:])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n >>= 7
|
||||||
|
cnt++
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
62
writer.go
Normal file
62
writer.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package spb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Constructor struct {
|
||||||
|
structlen, reallen uint32
|
||||||
|
body bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWriter 新的写入构造器
|
||||||
|
func NewWriter(buf []byte) (c Constructor) {
|
||||||
|
c.body = *bytes.NewBuffer(buf)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteString 按字符串写入一项
|
||||||
|
func (c *Constructor) WriteString(s string, cap uint32) error {
|
||||||
|
if int(cap) < len(s) {
|
||||||
|
return ErrInvalidDataLen
|
||||||
|
}
|
||||||
|
cnt, err := WriteNum(&c.body, cap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.structlen += cap
|
||||||
|
c.reallen += cnt
|
||||||
|
cnt, err = WriteNum(&c.body, uint32(len(s)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.reallen += cnt
|
||||||
|
_, err = c.body.WriteString(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.reallen += uint32(len(s))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cap structlen 目前写入的总长, 带 padding
|
||||||
|
func (c *Constructor) Cap() uint32 {
|
||||||
|
return c.structlen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len reallen 目前写入的实值总长, 不带 padding
|
||||||
|
func (c *Constructor) Len() uint32 {
|
||||||
|
return c.reallen
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo 将当前结果写出, 返回写入的实际长度
|
||||||
|
func (c *Constructor) WriteTo(w io.Writer) (int64, error) {
|
||||||
|
cnt, err := WriteNum(w, c.structlen)
|
||||||
|
if err != nil {
|
||||||
|
return int64(cnt), err
|
||||||
|
}
|
||||||
|
n, err := w.Write(c.body.Bytes())
|
||||||
|
cnt += uint32(n)
|
||||||
|
return int64(cnt), err
|
||||||
|
}
|
||||||
36
writer_test.go
Normal file
36
writer_test.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package spb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWriter(t *testing.T) {
|
||||||
|
f := bytes.NewBuffer(make([]byte, 0, 65536))
|
||||||
|
ft, err := os.Open("dict.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ft.Close()
|
||||||
|
sc := bufio.NewScanner(ft)
|
||||||
|
for sc.Scan() {
|
||||||
|
c := Constructor{}
|
||||||
|
for _, s := range strings.Split(sc.Text(), "\t") {
|
||||||
|
err = c.WriteString(s, 127)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.WriteTo(f)
|
||||||
|
}
|
||||||
|
real, err := os.ReadFile("dict.sp")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(real, f.Bytes()) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user