Created
July 23, 2024 14:48
-
-
Save lordofscripts/2b8fdfbb37e6c93484b6c8e5ab736618 to your computer and use it in GitHub Desktop.
Using Go-Restruct for Binary serialization fails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// You can edit this code! | |
// Click here and start typing. | |
// Go-Restruct/restruct (v1.2) appears to serialize well but deserialization doesn't retrieve what I put there. | |
package main | |
import ( | |
"encoding/binary" | |
"encoding/hex" | |
"fmt" | |
"log" | |
"github.com/creker/hashstructure" | |
"github.com/go-restruct/restruct" | |
) | |
type Share struct { | |
Field1 string | |
Field2 uint64 | |
Field3 float64 | |
} | |
type Container struct { | |
Len byte | |
Hash string | |
Data *Share | |
} | |
func (b *Container) Serialize() []byte { | |
hash, err := b.calculateHash() | |
if err != nil { | |
log.Fatal("Serialize Hash", err) | |
} | |
b.Len = byte(len(hash)) | |
b.Hash = hex.EncodeToString(hash) | |
data, err := restruct.Pack(binary.BigEndian, b) | |
if err != nil { | |
log.Fatal(err) | |
} | |
return data | |
} | |
func (b *Container) Deserialize(data []byte) error { | |
// (A) Before it was just b but it was failing. I then tried this newC alternative to confirm that something is wrong | |
newC := Container{0, "", nil} // (A) | |
if err := restruct.Unpack(data, binary.BigEndian, &newC); err != nil { // (A) | |
log.Fatal(err) | |
} | |
fmt.Println("Recovered", newC.String()) | |
b.Len = newC.Len // (A) | |
b.Hash = newC.Hash // (A) | |
b.Data = newC.Data // (A) | |
hash, err := b.calculateHash() | |
if err != nil { | |
log.Fatal("Deserialize Hash", err) | |
} | |
rhash := hex.EncodeToString(hash) | |
if rhash != b.Hash { | |
err := fmt.Errorf("Corrupted! %s != %s", b.Hash, rhash) | |
log.Fatal(err) | |
return err | |
} | |
return nil | |
} | |
func (b *Container) calculateHash() ([]byte, error) { | |
var hash []byte | |
var err error | |
hash, err = hashstructure.Hash(b.Data, hashstructure.FormatV2, nil) | |
if err != nil { | |
return nil, err | |
} | |
return hash, nil | |
} | |
func (b *Container) String() string { | |
return fmt.Sprintf("Container\n\tL: %d\n\tH: %s\n\t%s\n", b.Len, b.Hash, b.Data) | |
} | |
func (s Share) String() string { | |
return fmt.Sprintf("F1: %s F2: %d F3: %f", s.Field1, s.Field2, s.Field3) | |
} | |
func NewContainer(share *Share) *Container { | |
return &Container{0, "", share} | |
} | |
func main() { | |
fmt.Println("Hello, 世界") | |
share1 := Share{"Share #1", 854697, 4689.45} | |
share2 := Share{"Share #2", 9423858221, 1875348.287} | |
fmt.Println("Share #1", share1) // da554b7f921e5ef01b2e7efd9291f3ee4b3151f79f9180337e1181e60a007b2b | |
fmt.Println("Share #2", share2) // 6868640b6bf4a09ff337c489236ad0ad3d85217504e1259c955370430918f0f6 | |
c1 := NewContainer(&share1) | |
c2 := NewContainer(&share2) | |
fmt.Println("Container #1", c1) | |
fmt.Println("Container #2", c2) | |
fmt.Println("Serialize") | |
d1 := c1.Serialize() | |
d2 := c2.Serialize() | |
fmt.Println("Container #1", c1) | |
fmt.Println("Container #2", c2) | |
fmt.Println("Binary #1", len(d1), "\n", hex.EncodeToString(d1)) | |
fmt.Println("Binary #2", len(d2), "\n", hex.EncodeToString(d2)) | |
fmt.Println("Deserialize") | |
c1P := &Container{} | |
c1P.Deserialize(d1) | |
fmt.Println("Container #1'", c1P) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment