Contact card decompress, split, merge
This commit is contained in:
parent
b464a855ae
commit
d5760e8439
66
buffer.go
Normal file
66
buffer.go
Normal file
@ -0,0 +1,66 @@
|
||||
package meowlib
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func min(a, b int) int {
|
||||
if a <= b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func BufferSplit(buffer []byte, parts uint8) (packets [][]byte, err error) {
|
||||
if int(parts) > len(buffer) {
|
||||
return nil, errors.New("too many parts(" + strconv.Itoa(int(parts)) + ") for buffer len(" + strconv.Itoa(len(buffer)) + ")")
|
||||
}
|
||||
chunksize := int(len(buffer)/int(parts)) + 1
|
||||
packets = make([][]byte, parts)
|
||||
for c := 0; c < int(parts); c++ {
|
||||
if c == 0 {
|
||||
packets[c] = []byte{byte(c), byte(parts)}
|
||||
} else {
|
||||
packets[c] = []byte{byte(c)}
|
||||
}
|
||||
}
|
||||
chunk := 0
|
||||
for i := 0; i < len(buffer); i += chunksize {
|
||||
batch := buffer[i:min(i+chunksize, len(buffer))]
|
||||
packets[chunk] = append(packets[chunk], batch...)
|
||||
chunk++
|
||||
}
|
||||
return packets, nil
|
||||
}
|
||||
|
||||
func BufferMerge(packets [][]byte) (buffer []byte, err error) {
|
||||
var parts int
|
||||
found := false
|
||||
buffer = []byte{}
|
||||
for _, b := range packets {
|
||||
if b[0] == 0 {
|
||||
parts = int(b[1])
|
||||
buffer = append(buffer, b[2:]...)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, errors.New("start packet not found")
|
||||
}
|
||||
for i := 1; i < parts; i++ {
|
||||
found = false
|
||||
for _, b := range packets {
|
||||
if b[0] == byte(i) {
|
||||
buffer = append(buffer, b[1:]...)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, errors.New("packet #" + strconv.Itoa(i) + " not found")
|
||||
}
|
||||
}
|
||||
return buffer, nil
|
||||
}
|
24
buffer_test.go
Normal file
24
buffer_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
package meowlib
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBufferSplit(t *testing.T) {
|
||||
|
||||
source := []byte("Hello World, I need to slice you, but in equal parts, not the capitalist way")
|
||||
packets, err := BufferSplit(source, 3)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to encode address book:", err)
|
||||
}
|
||||
println(len(packets))
|
||||
destination, err := BufferMerge(packets)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to encode address book:", err)
|
||||
}
|
||||
println(string(destination))
|
||||
assert.Equal(t, source, destination, "The two buffers should be the same.")
|
||||
}
|
@ -43,17 +43,53 @@ func (contact *ContactCard) Compress() ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
var b bytes.Buffer
|
||||
gz := gzip.NewWriter(&b)
|
||||
gz, err := gzip.NewWriterLevel(&b, gzip.BestCompression)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := gz.Write(out); err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := gz.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println(b.Bytes())
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
func (contact *ContactCard) Split(parts uint8) (packets [][]byte, err error) {
|
||||
data, err := contact.Compress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return BufferSplit(data, parts)
|
||||
}
|
||||
|
||||
func NewContactCardFromCompressed(compressed []byte) (*ContactCard, error) {
|
||||
cc := &ContactCard{}
|
||||
reader := bytes.NewReader([]byte(compressed))
|
||||
gzreader, err := gzip.NewReader(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
output, err := ioutil.ReadAll(gzreader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := proto.Unmarshal(output, cc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func NewContactCardFromSplit(packets [][]byte) (*ContactCard, error) {
|
||||
data, err := BufferMerge(packets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewContactCardFromCompressed(data)
|
||||
}
|
||||
|
||||
func (contact *ContactCard) WriteCompressed(filename string) error {
|
||||
out, err := contact.Compress()
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user