mirror of
https://github.com/fumiama/go-simple-protobuf.git
synced 2026-06-30 00:50:33 +08:00
feat: add iterator
This commit is contained in:
67
reader.go
Normal file
67
reader.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package spb
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
type Iterator struct {
|
||||||
|
r io.Reader
|
||||||
|
structlen, reallen uint32
|
||||||
|
i uint32
|
||||||
|
v []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader 迭代器形式读取而非一次解析完
|
||||||
|
func NewReader(r io.Reader) (it Iterator, err error) {
|
||||||
|
it.structlen, it.reallen, err = ReadNum(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if it.structlen <= 1 || it.structlen >= uint32(1)<<20 {
|
||||||
|
err = ErrInvalidStructLen
|
||||||
|
return
|
||||||
|
}
|
||||||
|
it.r = r
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next 是否有下一个
|
||||||
|
func (it *Iterator) Next() bool {
|
||||||
|
if it.i >= it.structlen {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var offset, datalen, n uint32
|
||||||
|
var err error
|
||||||
|
offset, n, err = ReadNum(it.r)
|
||||||
|
it.reallen += n
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
datalen, n, err = ReadNum(it.r)
|
||||||
|
it.reallen += n
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if datalen == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if datalen > offset {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
it.v = append(it.v[:0], make([]byte, datalen)...)
|
||||||
|
x, err := it.r.Read(it.v)
|
||||||
|
it.reallen += uint32(x)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
it.i += offset
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes 本次迭代的原始值
|
||||||
|
func (it *Iterator) Bytes() []byte {
|
||||||
|
return it.v
|
||||||
|
}
|
||||||
|
|
||||||
|
// String 将本次迭代的值解释为 string
|
||||||
|
func (it *Iterator) String() string {
|
||||||
|
return string(it.v)
|
||||||
|
}
|
||||||
42
reader_test.go
Normal file
42
reader_test.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package spb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReader(t *testing.T) {
|
||||||
|
f, err := os.Open("dict.sp")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
ft, err := os.Open("dict.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ft.Close()
|
||||||
|
sc := bufio.NewScanner(ft)
|
||||||
|
var s Iterator
|
||||||
|
i := 1
|
||||||
|
for sc.Scan() {
|
||||||
|
s, err = NewReader(f)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if !s.Next() {
|
||||||
|
t.Fatal("unexpected no next")
|
||||||
|
}
|
||||||
|
t0 := s.String()
|
||||||
|
if !s.Next() {
|
||||||
|
t.Fatal("unexpected no next")
|
||||||
|
}
|
||||||
|
t1 := s.String()
|
||||||
|
if fmt.Sprint(t0, "\t", t1) != sc.Text() {
|
||||||
|
t.Fatal("invalid text @ line", i)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
11
spb.go
11
spb.go
@@ -2,7 +2,7 @@ package spb
|
|||||||
|
|
||||||
import "io"
|
import "io"
|
||||||
|
|
||||||
func ReadNum(r io.Reader) (n uint32, cnt int, err error) {
|
func ReadNum(r io.Reader) (n uint32, cnt uint32, err error) {
|
||||||
var buf [1]byte
|
var buf [1]byte
|
||||||
for cnt < 5 {
|
for cnt < 5 {
|
||||||
_, err = r.Read(buf[:])
|
_, err = r.Read(buf[:])
|
||||||
@@ -43,7 +43,7 @@ type SimplePB struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewSimplePB(r io.Reader) (s SimplePB, err error) {
|
func NewSimplePB(r io.Reader) (s SimplePB, err error) {
|
||||||
cnt := 0
|
cnt := uint32(0)
|
||||||
s.StructLen, cnt, err = ReadNum(r)
|
s.StructLen, cnt, err = ReadNum(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.RealLen = uint32(cnt)
|
s.RealLen = uint32(cnt)
|
||||||
@@ -55,7 +55,7 @@ func NewSimplePB(r io.Reader) (s SimplePB, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var offset, datalen uint32
|
var offset, datalen uint32
|
||||||
n := 0
|
n := uint32(0)
|
||||||
for i := uint32(0); i < s.StructLen; i += offset {
|
for i := uint32(0); i < s.StructLen; i += offset {
|
||||||
offset, n, err = ReadNum(r)
|
offset, n, err = ReadNum(r)
|
||||||
cnt += n
|
cnt += n
|
||||||
@@ -75,8 +75,9 @@ func NewSimplePB(r io.Reader) (s SimplePB, err error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
t := make([]byte, datalen)
|
t := make([]byte, datalen)
|
||||||
n, err = r.Read(t)
|
x := 0
|
||||||
cnt += n
|
x, err = r.Read(t)
|
||||||
|
cnt += uint32(x)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user