-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
255 additions
and
4 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package gtencoding | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
|
||
"github.com/google/uuid" | ||
"github.com/gordian-engine/gordian/gturbine" | ||
) | ||
|
||
const ( | ||
intSize = 8 | ||
uuidSize = 16 | ||
blockHashSize = 32 | ||
prefixSize = intSize*5 + uuidSize + blockHashSize | ||
) | ||
|
||
// BinaryShardCodec represents a codec for encoding and decoding shreds | ||
type BinaryShardCodec struct{} | ||
|
||
func (bsc *BinaryShardCodec) Encode(shred gturbine.Shred) ([]byte, error) { | ||
out := make([]byte, prefixSize+len(shred.Data)) | ||
|
||
// Write full data size | ||
binary.LittleEndian.PutUint64(out[:8], uint64(shred.FullDataSize)) | ||
|
||
// Write block hash | ||
copy(out[8:40], shred.BlockHash) | ||
|
||
uid, err := uuid.Parse(shred.GroupID) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to parse group ID: %w", err) | ||
} | ||
// Write group ID | ||
copy(out[40:56], uid[:]) | ||
|
||
// Write height | ||
binary.LittleEndian.PutUint64(out[56:64], shred.Height) | ||
|
||
// Write index | ||
binary.LittleEndian.PutUint64(out[64:72], uint64(shred.Index)) | ||
|
||
// Write total data shreds | ||
binary.LittleEndian.PutUint64(out[72:80], uint64(shred.TotalDataShreds)) | ||
|
||
// Write total recovery shreds | ||
binary.LittleEndian.PutUint64(out[80:88], uint64(shred.TotalRecoveryShreds)) | ||
|
||
// Write data | ||
copy(out[prefixSize:], shred.Data) | ||
|
||
return out, nil | ||
|
||
} | ||
|
||
func (bsc *BinaryShardCodec) Decode(data []byte) (gturbine.Shred, error) { | ||
shred := gturbine.Shred{} | ||
|
||
// Read full data size | ||
shred.FullDataSize = int(binary.LittleEndian.Uint64(data[:8])) | ||
|
||
// Read block hash | ||
shred.BlockHash = make([]byte, blockHashSize) | ||
copy(shred.BlockHash, data[8:40]) | ||
|
||
// Read group ID | ||
uid := uuid.UUID{} | ||
copy(uid[:], data[40:56]) | ||
shred.GroupID = uid.String() | ||
|
||
// Read height | ||
shred.Height = binary.LittleEndian.Uint64(data[56:64]) | ||
|
||
// Read index | ||
shred.Index = int(binary.LittleEndian.Uint64(data[64:72])) | ||
|
||
// Read total data shreds | ||
shred.TotalDataShreds = int(binary.LittleEndian.Uint64(data[72:80])) | ||
|
||
// Read total recovery shreds | ||
shred.TotalRecoveryShreds = int(binary.LittleEndian.Uint64(data[80:88])) | ||
|
||
// Read data | ||
shred.Data = make([]byte, len(data)-prefixSize) | ||
copy(shred.Data, data[prefixSize:]) | ||
|
||
return shred, nil | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
package gtencoding | ||
|
||
import ( | ||
"bytes" | ||
"testing" | ||
|
||
"github.com/google/uuid" | ||
"github.com/gordian-engine/gordian/gturbine" | ||
) | ||
|
||
func TestBinaryShardCodec_EncodeDecode(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
shred gturbine.Shred | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "basic encode/decode", | ||
shred: gturbine.Shred{ | ||
FullDataSize: 1000, | ||
BlockHash: bytes.Repeat([]byte{1}, 32), | ||
GroupID: uuid.New().String(), | ||
Height: 12345, | ||
Index: 5, | ||
TotalDataShreds: 10, | ||
TotalRecoveryShreds: 2, | ||
Data: []byte("test data"), | ||
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "empty data", | ||
shred: gturbine.Shred{ | ||
FullDataSize: 0, | ||
BlockHash: bytes.Repeat([]byte{2}, 32), | ||
GroupID: uuid.New().String(), | ||
Height: 67890, | ||
Index: 0, | ||
TotalDataShreds: 1, | ||
TotalRecoveryShreds: 0, | ||
Data: []byte{}, | ||
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "large data", | ||
shred: gturbine.Shred{ | ||
FullDataSize: 1000000, | ||
BlockHash: bytes.Repeat([]byte{3}, 32), | ||
GroupID: uuid.New().String(), | ||
Height: 999999, | ||
Index: 50, | ||
TotalDataShreds: 100, | ||
TotalRecoveryShreds: 20, | ||
Data: bytes.Repeat([]byte("large data"), 1000), | ||
}, | ||
wantErr: false, | ||
}, | ||
} | ||
|
||
codec := &BinaryShardCodec{} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
// Test encoding | ||
encoded, err := codec.Encode(tt.shred) | ||
if (err != nil) != tt.wantErr { | ||
t.Errorf("BinaryShardCodec.Encode() error = %v, wantErr %v", err, tt.wantErr) | ||
return | ||
} | ||
|
||
if tt.wantErr { | ||
return | ||
} | ||
|
||
// Test decoding | ||
decoded, err := codec.Decode(encoded) | ||
if err != nil { | ||
t.Errorf("BinaryShardCodec.Decode() error = %v", err) | ||
return | ||
} | ||
|
||
// Verify all fields match | ||
if decoded.FullDataSize != tt.shred.FullDataSize { | ||
t.Errorf("FullDataSize mismatch: got %v, want %v", decoded.FullDataSize, tt.shred.FullDataSize) | ||
} | ||
|
||
if !bytes.Equal(decoded.BlockHash, tt.shred.BlockHash) { | ||
t.Errorf("BlockHash mismatch: got %v, want %v", decoded.BlockHash, tt.shred.BlockHash) | ||
} | ||
|
||
if decoded.GroupID != tt.shred.GroupID { | ||
t.Errorf("GroupID mismatch: got %v, want %v", decoded.GroupID, tt.shred.GroupID) | ||
} | ||
|
||
if decoded.Height != tt.shred.Height { | ||
t.Errorf("Height mismatch: got %v, want %v", decoded.Height, tt.shred.Height) | ||
} | ||
|
||
if decoded.Index != tt.shred.Index { | ||
t.Errorf("Index mismatch: got %v, want %v", decoded.Index, tt.shred.Index) | ||
} | ||
|
||
if decoded.TotalDataShreds != tt.shred.TotalDataShreds { | ||
t.Errorf("TotalDataShreds mismatch: got %v, want %v", decoded.TotalDataShreds, tt.shred.TotalDataShreds) | ||
} | ||
|
||
if decoded.TotalRecoveryShreds != tt.shred.TotalRecoveryShreds { | ||
t.Errorf("TotalRecoveryShreds mismatch: got %v, want %v", decoded.TotalRecoveryShreds, tt.shred.TotalRecoveryShreds) | ||
} | ||
|
||
if !bytes.Equal(decoded.Data, tt.shred.Data) { | ||
t.Errorf("Data mismatch: got %v, want %v", decoded.Data, tt.shred.Data) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestBinaryShardCodec_InvalidGroupID(t *testing.T) { | ||
codec := &BinaryShardCodec{} | ||
shred := gturbine.Shred{ | ||
GroupID: "invalid-uuid", | ||
// Other fields can be empty for this test | ||
} | ||
|
||
_, err := codec.Encode(shred) | ||
if err == nil { | ||
t.Error("Expected error when encoding invalid GroupID, got nil") | ||
} | ||
} | ||
|
||
func TestBinaryShardCodec_DataSizes(t *testing.T) { | ||
codec := &BinaryShardCodec{} | ||
shred := gturbine.Shred{ | ||
FullDataSize: 1000, | ||
BlockHash: bytes.Repeat([]byte{1}, 32), | ||
GroupID: uuid.New().String(), | ||
Height: 12345, | ||
Index: 5, | ||
TotalDataShreds: 10, | ||
TotalRecoveryShreds: 2, | ||
Data: []byte("test data"), | ||
} | ||
|
||
encoded, err := codec.Encode(shred) | ||
if err != nil { | ||
t.Fatalf("Failed to encode shred: %v", err) | ||
} | ||
|
||
expectedPrefixSize := intSize*5 + uuidSize + blockHashSize | ||
if len(encoded) != expectedPrefixSize+len(shred.Data) { | ||
t.Errorf("Encoded data size mismatch: got %v, want %v", len(encoded), expectedPrefixSize+len(shred.Data)) | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package gtencoding | ||
|
||
import "github.com/gordian-engine/gordian/gturbine" | ||
|
||
type ShardCodec interface { | ||
Encode(shred gturbine.Shred) ([]byte, error) | ||
Decode(data []byte) (gturbine.Shred, error) | ||
} |
2 changes: 1 addition & 1 deletion
2
gturbine/shredding/process_shred_test.go → gturbine/gtshredding/process_shred_test.go
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package shredding | ||
package gtshredding | ||
|
||
import ( | ||
"bytes" | ||
|
2 changes: 1 addition & 1 deletion
2
gturbine/shredding/processor.go → gturbine/gtshredding/processor.go
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package shredding | ||
package gtshredding | ||
|
||
import ( | ||
"fmt" | ||
|
2 changes: 1 addition & 1 deletion
2
gturbine/shredding/processor_test.go → gturbine/gtshredding/processor_test.go
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package shredding | ||
package gtshredding | ||
|
||
// import ( | ||
// "bytes" | ||
|
This file contains 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