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
|
return nil, err
|
||||||
}
|
}
|
||||||
var b bytes.Buffer
|
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 {
|
if _, err := gz.Write(out); err != nil {
|
||||||
log.Fatal(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := gz.Close(); err != nil {
|
if err := gz.Close(); err != nil {
|
||||||
log.Fatal(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Println(b.Bytes())
|
fmt.Println(b.Bytes())
|
||||||
return b.Bytes(), nil
|
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 {
|
func (contact *ContactCard) WriteCompressed(filename string) error {
|
||||||
out, err := contact.Compress()
|
out, err := contact.Compress()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user