feat: add 100% docstring coverage
Adds comprehensive docstrings and runnable examples to all public APIs in the `crypt`, `enchantrix`, and `trix` packages. This change is intended to bring the project's documentation to a production-ready standard and to provide high-quality, verifiable examples for the official Go documentation website.
This commit is contained in:
parent
deff3a80c6
commit
fca2880355
7 changed files with 357 additions and 9 deletions
|
|
@ -17,12 +17,14 @@ import (
|
|||
)
|
||||
|
||||
// Service is the main struct for the crypt service.
|
||||
// It provides methods for hashing, checksums, and encryption.
|
||||
type Service struct {
|
||||
rsa *rsa.Service
|
||||
pgp *pgp.Service
|
||||
}
|
||||
|
||||
// NewService creates a new crypt Service and initialises its embedded services.
|
||||
// It returns a new Service.
|
||||
func NewService() *Service {
|
||||
return &Service{
|
||||
rsa: rsa.NewService(),
|
||||
|
|
@ -34,11 +36,16 @@ func NewService() *Service {
|
|||
type HashType string
|
||||
|
||||
const (
|
||||
LTHN HashType = "lthn"
|
||||
// LTHN is a custom quasi-salted hashing algorithm.
|
||||
LTHN HashType = "lthn"
|
||||
// SHA512 is the SHA-512 hashing algorithm.
|
||||
SHA512 HashType = "sha512"
|
||||
// SHA256 is the SHA-256 hashing algorithm.
|
||||
SHA256 HashType = "sha256"
|
||||
SHA1 HashType = "sha1"
|
||||
MD5 HashType = "md5"
|
||||
// SHA1 is the SHA-1 hashing algorithm.
|
||||
SHA1 HashType = "sha1"
|
||||
// MD5 is the MD5 hashing algorithm.
|
||||
MD5 HashType = "md5"
|
||||
)
|
||||
|
||||
// --- Hashing ---
|
||||
|
|
@ -54,6 +61,7 @@ func (s *Service) IsHashAlgo(algo string) bool {
|
|||
}
|
||||
|
||||
// Hash computes a hash of the payload using the specified algorithm.
|
||||
// It returns the hash as a hex-encoded string.
|
||||
func (s *Service) Hash(lib HashType, payload string) string {
|
||||
switch lib {
|
||||
case LTHN:
|
||||
|
|
@ -78,6 +86,7 @@ func (s *Service) Hash(lib HashType, payload string) string {
|
|||
// --- Checksums ---
|
||||
|
||||
// Luhn validates a number using the Luhn algorithm.
|
||||
// It is typically used to validate credit card numbers.
|
||||
func (s *Service) Luhn(payload string) bool {
|
||||
payload = strings.ReplaceAll(payload, " ", "")
|
||||
if len(payload) <= 1 {
|
||||
|
|
@ -106,6 +115,7 @@ func (s *Service) Luhn(payload string) bool {
|
|||
}
|
||||
|
||||
// Fletcher16 computes the Fletcher-16 checksum.
|
||||
// It is a fast checksum algorithm that is more reliable than a simple sum.
|
||||
func (s *Service) Fletcher16(payload string) uint16 {
|
||||
data := []byte(payload)
|
||||
var sum1, sum2 uint16
|
||||
|
|
@ -117,6 +127,7 @@ func (s *Service) Fletcher16(payload string) uint16 {
|
|||
}
|
||||
|
||||
// Fletcher32 computes the Fletcher-32 checksum.
|
||||
// It provides better error detection than Fletcher-16.
|
||||
func (s *Service) Fletcher32(payload string) uint32 {
|
||||
data := []byte(payload)
|
||||
if len(data)%2 != 0 {
|
||||
|
|
@ -133,6 +144,7 @@ func (s *Service) Fletcher32(payload string) uint32 {
|
|||
}
|
||||
|
||||
// Fletcher64 computes the Fletcher-64 checksum.
|
||||
// It provides the best error detection of the Fletcher algorithms.
|
||||
func (s *Service) Fletcher64(payload string) uint64 {
|
||||
data := []byte(payload)
|
||||
if len(data)%4 != 0 {
|
||||
|
|
@ -186,36 +198,42 @@ func (s *Service) ensurePGP() {
|
|||
}
|
||||
|
||||
// GeneratePGPKeyPair creates a new PGP key pair.
|
||||
// It returns the public and private keys in PEM format.
|
||||
func (s *Service) GeneratePGPKeyPair(name, email, comment string) (publicKey, privateKey []byte, err error) {
|
||||
s.ensurePGP()
|
||||
return s.pgp.GenerateKeyPair(name, email, comment)
|
||||
}
|
||||
|
||||
// EncryptPGP encrypts data with a public key.
|
||||
// It returns the encrypted data.
|
||||
func (s *Service) EncryptPGP(publicKey, data []byte) ([]byte, error) {
|
||||
s.ensurePGP()
|
||||
return s.pgp.Encrypt(publicKey, data)
|
||||
}
|
||||
|
||||
// DecryptPGP decrypts data with a private key.
|
||||
// It returns the decrypted data.
|
||||
func (s *Service) DecryptPGP(privateKey, ciphertext []byte) ([]byte, error) {
|
||||
s.ensurePGP()
|
||||
return s.pgp.Decrypt(privateKey, ciphertext)
|
||||
}
|
||||
|
||||
// SignPGP creates a detached signature for a message.
|
||||
// It returns the signature.
|
||||
func (s *Service) SignPGP(privateKey, data []byte) ([]byte, error) {
|
||||
s.ensurePGP()
|
||||
return s.pgp.Sign(privateKey, data)
|
||||
}
|
||||
|
||||
// VerifyPGP verifies a detached signature for a message.
|
||||
// It returns an error if the signature is invalid.
|
||||
func (s *Service) VerifyPGP(publicKey, data, signature []byte) error {
|
||||
s.ensurePGP()
|
||||
return s.pgp.Verify(publicKey, data, signature)
|
||||
}
|
||||
|
||||
// SymmetricallyEncryptPGP encrypts data with a passphrase.
|
||||
// It returns the encrypted data.
|
||||
func (s *Service) SymmetricallyEncryptPGP(passphrase, data []byte) ([]byte, error) {
|
||||
s.ensurePGP()
|
||||
if len(passphrase) == 0 {
|
||||
|
|
|
|||
170
pkg/crypt/examples_test.go
Normal file
170
pkg/crypt/examples_test.go
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
package crypt_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
)
|
||||
|
||||
func ExampleService_Hash() {
|
||||
cryptService := crypt.NewService()
|
||||
payload := "Enchantrix"
|
||||
|
||||
hashTypes := []crypt.HashType{
|
||||
crypt.LTHN,
|
||||
crypt.MD5,
|
||||
crypt.SHA1,
|
||||
crypt.SHA256,
|
||||
crypt.SHA512,
|
||||
}
|
||||
|
||||
fmt.Printf("Payload to hash: \"%s\"\n", payload)
|
||||
for _, hashType := range hashTypes {
|
||||
hash := cryptService.Hash(hashType, payload)
|
||||
fmt.Printf(" - %-6s: %s\n", hashType, hash)
|
||||
}
|
||||
// Output:
|
||||
// Payload to hash: "Enchantrix"
|
||||
// - lthn : 331f24f86375846ac8d0d06cfb80cb2877e8900548a88d4ac8d39177cd854dab
|
||||
// - md5 : 7c54903a10f058a93fd1f21ea802cb27
|
||||
// - sha1 : 399f776c4b97e558a2c4f319b223dd481c6d43f1
|
||||
// - sha256: 2ae653f74554abfdb2343013925f5184a0f05e4c2e0c3881448fc80caeb667c2
|
||||
// - sha512: 9638018a9720b5d83fba7f3899e4ba5ab78018781f9c600f0c0738ff8ccf1ea54e1c783ee8778542b70aa26283d87ce88784b2df5697322546d3b8029c4b6797
|
||||
}
|
||||
|
||||
func ExampleService_Luhn() {
|
||||
cryptService := crypt.NewService()
|
||||
luhnPayloadGood := "49927398716"
|
||||
luhnPayloadBad := "49927398717"
|
||||
fmt.Printf("Luhn Checksum:\n")
|
||||
fmt.Printf(" - Payload '%s' is valid: %v\n", luhnPayloadGood, cryptService.Luhn(luhnPayloadGood))
|
||||
fmt.Printf(" - Payload '%s' is valid: %v\n", luhnPayloadBad, cryptService.Luhn(luhnPayloadBad))
|
||||
// Output:
|
||||
// Luhn Checksum:
|
||||
// - Payload '49927398716' is valid: true
|
||||
// - Payload '49927398717' is valid: false
|
||||
}
|
||||
|
||||
func ExampleService_Fletcher16() {
|
||||
cryptService := crypt.NewService()
|
||||
fletcherPayload := "abcde"
|
||||
fmt.Printf("Fletcher16 Checksum (Payload: \"%s\"): %d\n", fletcherPayload, cryptService.Fletcher16(fletcherPayload))
|
||||
// Output:
|
||||
// Fletcher16 Checksum (Payload: "abcde"): 51440
|
||||
}
|
||||
|
||||
func ExampleService_Fletcher32() {
|
||||
cryptService := crypt.NewService()
|
||||
fletcherPayload := "abcde"
|
||||
fmt.Printf("Fletcher32 Checksum (Payload: \"%s\"): %d\n", fletcherPayload, cryptService.Fletcher32(fletcherPayload))
|
||||
// Output:
|
||||
// Fletcher32 Checksum (Payload: "abcde"): 4031760169
|
||||
}
|
||||
|
||||
func ExampleService_Fletcher64() {
|
||||
cryptService := crypt.NewService()
|
||||
fletcherPayload := "abcde"
|
||||
fmt.Printf("Fletcher64 Checksum (Payload: \"%s\"): %d\n", fletcherPayload, cryptService.Fletcher64(fletcherPayload))
|
||||
// Output:
|
||||
// Fletcher64 Checksum (Payload: "abcde"): 14467467625952928454
|
||||
}
|
||||
|
||||
func ExampleService_GeneratePGPKeyPair() {
|
||||
cryptService := crypt.NewService()
|
||||
publicKey, privateKey, err := cryptService.GeneratePGPKeyPair("test", "test@example.com", "test key")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate PGP key pair: %v", err)
|
||||
}
|
||||
fmt.Printf("PGP public key is not empty: %v\n", len(publicKey) > 0)
|
||||
fmt.Printf("PGP private key is not empty: %v\n", len(privateKey) > 0)
|
||||
// Output:
|
||||
// PGP public key is not empty: true
|
||||
// PGP private key is not empty: true
|
||||
}
|
||||
|
||||
func ExampleService_EncryptPGP() {
|
||||
cryptService := crypt.NewService()
|
||||
publicKey, _, err := cryptService.GeneratePGPKeyPair("test", "test@example.com", "test key")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate PGP key pair: %v", err)
|
||||
}
|
||||
message := []byte("This is a secret message for PGP.")
|
||||
ciphertext, err := cryptService.EncryptPGP(publicKey, message)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encrypt with PGP: %v", err)
|
||||
}
|
||||
fmt.Printf("PGP ciphertext is not empty: %v\n", len(ciphertext) > 0)
|
||||
// Output:
|
||||
// PGP ciphertext is not empty: true
|
||||
}
|
||||
|
||||
func ExampleService_DecryptPGP() {
|
||||
cryptService := crypt.NewService()
|
||||
publicKey, privateKey, err := cryptService.GeneratePGPKeyPair("test", "test@example.com", "test key")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate PGP key pair: %v", err)
|
||||
}
|
||||
message := []byte("This is a secret message for PGP.")
|
||||
ciphertext, err := cryptService.EncryptPGP(publicKey, message)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encrypt with PGP: %v", err)
|
||||
}
|
||||
decrypted, err := cryptService.DecryptPGP(privateKey, ciphertext)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to decrypt with PGP: %v", err)
|
||||
}
|
||||
fmt.Printf("Decrypted message: %s\n", decrypted)
|
||||
// Output:
|
||||
// Decrypted message: This is a secret message for PGP.
|
||||
}
|
||||
|
||||
func ExampleService_SignPGP() {
|
||||
cryptService := crypt.NewService()
|
||||
_, privateKey, err := cryptService.GeneratePGPKeyPair("test", "test@example.com", "test key")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate PGP key pair: %v", err)
|
||||
}
|
||||
message := []byte("This is a message to be signed.")
|
||||
signature, err := cryptService.SignPGP(privateKey, message)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to sign with PGP: %v", err)
|
||||
}
|
||||
fmt.Printf("PGP signature is not empty: %v\n", len(signature) > 0)
|
||||
// Output:
|
||||
// PGP signature is not empty: true
|
||||
}
|
||||
|
||||
func ExampleService_VerifyPGP() {
|
||||
cryptService := crypt.NewService()
|
||||
publicKey, privateKey, err := cryptService.GeneratePGPKeyPair("test", "test@example.com", "test key")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate PGP key pair: %v", err)
|
||||
}
|
||||
message := []byte("This is a message to be signed.")
|
||||
signature, err := cryptService.SignPGP(privateKey, message)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to sign with PGP: %v", err)
|
||||
}
|
||||
err = cryptService.VerifyPGP(publicKey, message, signature)
|
||||
if err != nil {
|
||||
fmt.Println("PGP signature verification failed.")
|
||||
} else {
|
||||
fmt.Println("PGP signature verified successfully.")
|
||||
}
|
||||
// Output:
|
||||
// PGP signature verified successfully.
|
||||
}
|
||||
|
||||
func ExampleService_SymmetricallyEncryptPGP() {
|
||||
cryptService := crypt.NewService()
|
||||
passphrase := []byte("my secret passphrase")
|
||||
message := []byte("This is a symmetric secret.")
|
||||
ciphertext, err := cryptService.SymmetricallyEncryptPGP(passphrase, message)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to symmetrically encrypt with PGP: %v", err)
|
||||
}
|
||||
fmt.Printf("Symmetric PGP ciphertext is not empty: %v\n", len(ciphertext) > 0)
|
||||
// Output:
|
||||
// Symmetric PGP ciphertext is not empty: true
|
||||
}
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
package enchantrix
|
||||
|
||||
// Sigil defines the interface for a data transformer.
|
||||
// A Sigil is a reversible or irreversible transformation of a byte slice.
|
||||
type Sigil interface {
|
||||
// In transforms the data.
|
||||
In(data []byte) ([]byte, error)
|
||||
// Out reverses the transformation.
|
||||
Out(data []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
|
|
|
|||
44
pkg/enchantrix/examples_test.go
Normal file
44
pkg/enchantrix/examples_test.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package enchantrix_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/enchantrix"
|
||||
)
|
||||
|
||||
func ExampleTransmute() {
|
||||
data := []byte("Hello, World!")
|
||||
sigils := []enchantrix.Sigil{
|
||||
&enchantrix.ReverseSigil{},
|
||||
&enchantrix.HexSigil{},
|
||||
}
|
||||
transformed, err := enchantrix.Transmute(data, sigils)
|
||||
if err != nil {
|
||||
log.Fatalf("Transmute failed: %v", err)
|
||||
}
|
||||
fmt.Printf("Transformed data: %s\n", transformed)
|
||||
// Output:
|
||||
// Transformed data: 21646c726f57202c6f6c6c6548
|
||||
}
|
||||
|
||||
func ExampleNewSigil() {
|
||||
sigil, err := enchantrix.NewSigil("base64")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create sigil: %v", err)
|
||||
}
|
||||
data := []byte("Hello, World!")
|
||||
encoded, err := sigil.In(data)
|
||||
if err != nil {
|
||||
log.Fatalf("Sigil In failed: %v", err)
|
||||
}
|
||||
fmt.Printf("Encoded data: %s\n", encoded)
|
||||
decoded, err := sigil.Out(encoded)
|
||||
if err != nil {
|
||||
log.Fatalf("Sigil Out failed: %v", err)
|
||||
}
|
||||
fmt.Printf("Decoded data: %s\n", decoded)
|
||||
// Output:
|
||||
// Encoded data: SGVsbG8sIFdvcmxkIQ==
|
||||
// Decoded data: Hello, World!
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ import (
|
|||
)
|
||||
|
||||
// ReverseSigil is a Sigil that reverses the bytes of the payload.
|
||||
// It is a symmetrical Sigil, meaning that the In and Out methods perform the same operation.
|
||||
type ReverseSigil struct{}
|
||||
|
||||
// In reverses the bytes of the data.
|
||||
|
|
@ -42,6 +43,7 @@ func (s *ReverseSigil) Out(data []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
// HexSigil is a Sigil that encodes/decodes data to/from hexadecimal.
|
||||
// The In method encodes the data, and the Out method decodes it.
|
||||
type HexSigil struct{}
|
||||
|
||||
// In encodes the data to hexadecimal.
|
||||
|
|
@ -65,6 +67,7 @@ func (s *HexSigil) Out(data []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
// Base64Sigil is a Sigil that encodes/decodes data to/from base64.
|
||||
// The In method encodes the data, and the Out method decodes it.
|
||||
type Base64Sigil struct{}
|
||||
|
||||
// In encodes the data to base64.
|
||||
|
|
@ -88,6 +91,7 @@ func (s *Base64Sigil) Out(data []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
// GzipSigil is a Sigil that compresses/decompresses data using gzip.
|
||||
// The In method compresses the data, and the Out method decompresses it.
|
||||
type GzipSigil struct {
|
||||
writer io.Writer
|
||||
}
|
||||
|
|
@ -126,6 +130,7 @@ func (s *GzipSigil) Out(data []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
// JSONSigil is a Sigil that compacts or indents JSON data.
|
||||
// The Out method is a no-op.
|
||||
type JSONSigil struct{ Indent bool }
|
||||
|
||||
// In compacts or indents the JSON data.
|
||||
|
|
@ -147,6 +152,7 @@ func (s *JSONSigil) Out(data []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
// HashSigil is a Sigil that hashes the data using a specified algorithm.
|
||||
// The In method hashes the data, and the Out method is a no-op.
|
||||
type HashSigil struct {
|
||||
Hash crypto.Hash
|
||||
}
|
||||
|
|
@ -211,6 +217,7 @@ func (s *HashSigil) Out(data []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
// NewSigil is a factory function that returns a Sigil based on a string name.
|
||||
// It is the primary way to create Sigil instances.
|
||||
func NewSigil(name string) (Sigil, error) {
|
||||
switch name {
|
||||
case "reverse":
|
||||
|
|
|
|||
93
pkg/trix/examples_test.go
Normal file
93
pkg/trix/examples_test.go
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package trix_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
"github.com/Snider/Enchantrix/pkg/trix"
|
||||
)
|
||||
|
||||
func ExampleEncode() {
|
||||
t := &trix.Trix{
|
||||
Header: map[string]interface{}{"author": "Jules"},
|
||||
Payload: []byte("Hello, Trix!"),
|
||||
}
|
||||
encoded, err := trix.Encode(t, "TRIX", nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Encode failed: %v", err)
|
||||
}
|
||||
fmt.Printf("Encoded data is not empty: %v\n", len(encoded) > 0)
|
||||
// Output:
|
||||
// Encoded data is not empty: true
|
||||
}
|
||||
|
||||
func ExampleDecode() {
|
||||
t := &trix.Trix{
|
||||
Header: map[string]interface{}{"author": "Jules"},
|
||||
Payload: []byte("Hello, Trix!"),
|
||||
}
|
||||
encoded, err := trix.Encode(t, "TRIX", nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Encode failed: %v", err)
|
||||
}
|
||||
decoded, err := trix.Decode(encoded, "TRIX", nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Decode failed: %v", err)
|
||||
}
|
||||
fmt.Printf("Decoded payload: %s\n", decoded.Payload)
|
||||
fmt.Printf("Decoded header: %v\n", decoded.Header)
|
||||
// Output:
|
||||
// Decoded payload: Hello, Trix!
|
||||
// Decoded header: map[author:Jules]
|
||||
}
|
||||
|
||||
func ExampleTrix_Pack() {
|
||||
t := &trix.Trix{
|
||||
Payload: []byte("secret message"),
|
||||
InSigils: []string{"base64", "reverse"},
|
||||
}
|
||||
err := t.Pack()
|
||||
if err != nil {
|
||||
log.Fatalf("Pack failed: %v", err)
|
||||
}
|
||||
fmt.Printf("Packed payload: %s\n", t.Payload)
|
||||
// Output:
|
||||
// Packed payload: =U2ZhN3cl1GI0VmcjV2c
|
||||
}
|
||||
|
||||
func ExampleTrix_Unpack() {
|
||||
t := &trix.Trix{
|
||||
Payload: []byte("=U2ZhN3cl1GI0VmcjV2c"),
|
||||
OutSigils: []string{"base64", "reverse"},
|
||||
}
|
||||
err := t.Unpack()
|
||||
if err != nil {
|
||||
log.Fatalf("Unpack failed: %v", err)
|
||||
}
|
||||
fmt.Printf("Unpacked payload: %s\n", t.Payload)
|
||||
// Output:
|
||||
// Unpacked payload: secret message
|
||||
}
|
||||
|
||||
func ExampleTrix_Pack_checksum() {
|
||||
t := &trix.Trix{
|
||||
Header: map[string]interface{}{},
|
||||
Payload: []byte("secret message"),
|
||||
InSigils: []string{"base64", "reverse"},
|
||||
ChecksumAlgo: crypt.SHA256,
|
||||
}
|
||||
encoded, err := trix.Encode(t, "TRIX", nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Encode failed: %v", err)
|
||||
}
|
||||
decoded, err := trix.Decode(encoded, "TRIX", nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Decode failed: %v", err)
|
||||
}
|
||||
fmt.Printf("Decoded payload: %s\n", decoded.Payload)
|
||||
fmt.Printf("Checksum verified: %v\n", decoded.Header["checksum"] != nil)
|
||||
// Output:
|
||||
// Decoded payload: secret message
|
||||
// Checksum verified: true
|
||||
}
|
||||
|
|
@ -13,20 +13,29 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
Version = 2
|
||||
// Version is the current version of the .trix file format.
|
||||
Version = 2
|
||||
// MaxHeaderSize is the maximum allowed size for the header.
|
||||
MaxHeaderSize = 16 * 1024 * 1024 // 16 MB
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidMagicNumber is returned when the magic number is incorrect.
|
||||
ErrInvalidMagicNumber = errors.New("trix: invalid magic number")
|
||||
ErrInvalidVersion = errors.New("trix: invalid version")
|
||||
ErrMagicNumberLength = errors.New("trix: magic number must be 4 bytes long")
|
||||
ErrNilSigil = errors.New("trix: sigil cannot be nil")
|
||||
ErrChecksumMismatch = errors.New("trix: checksum mismatch")
|
||||
ErrHeaderTooLarge = errors.New("trix: header size exceeds maximum allowed")
|
||||
// ErrInvalidVersion is returned when the version is incorrect.
|
||||
ErrInvalidVersion = errors.New("trix: invalid version")
|
||||
// ErrMagicNumberLength is returned when the magic number is not 4 bytes long.
|
||||
ErrMagicNumberLength = errors.New("trix: magic number must be 4 bytes long")
|
||||
// ErrNilSigil is returned when a sigil is nil.
|
||||
ErrNilSigil = errors.New("trix: sigil cannot be nil")
|
||||
// ErrChecksumMismatch is returned when the checksum does not match.
|
||||
ErrChecksumMismatch = errors.New("trix: checksum mismatch")
|
||||
// ErrHeaderTooLarge is returned when the header size exceeds the maximum allowed.
|
||||
ErrHeaderTooLarge = errors.New("trix: header size exceeds maximum allowed")
|
||||
)
|
||||
|
||||
// Trix represents the structure of a .trix file.
|
||||
// It contains a header, a payload, and optional sigils for data transformation.
|
||||
type Trix struct {
|
||||
Header map[string]interface{}
|
||||
Payload []byte
|
||||
|
|
@ -36,6 +45,7 @@ type Trix struct {
|
|||
}
|
||||
|
||||
// Encode serializes a Trix struct into the .trix binary format.
|
||||
// It returns the encoded data as a byte slice.
|
||||
func Encode(trix *Trix, magicNumber string, w io.Writer) ([]byte, error) {
|
||||
if len(magicNumber) != 4 {
|
||||
return nil, ErrMagicNumberLength
|
||||
|
|
@ -99,6 +109,7 @@ func Encode(trix *Trix, magicNumber string, w io.Writer) ([]byte, error) {
|
|||
}
|
||||
|
||||
// Decode deserializes the .trix binary format into a Trix struct.
|
||||
// It returns the decoded Trix struct.
|
||||
// Note: Sigils are not stored in the format and must be re-attached by the caller.
|
||||
func Decode(data []byte, magicNumber string, r io.Reader) (*Trix, error) {
|
||||
if len(magicNumber) != 4 {
|
||||
|
|
@ -176,6 +187,7 @@ func Decode(data []byte, magicNumber string, r io.Reader) (*Trix, error) {
|
|||
}
|
||||
|
||||
// Pack applies the In method of all attached sigils to the payload.
|
||||
// It modifies the Trix struct in place.
|
||||
func (t *Trix) Pack() error {
|
||||
for _, sigilName := range t.InSigils {
|
||||
sigil, err := enchantrix.NewSigil(sigilName)
|
||||
|
|
@ -191,6 +203,7 @@ func (t *Trix) Pack() error {
|
|||
}
|
||||
|
||||
// Unpack applies the Out method of all sigils in reverse order.
|
||||
// It modifies the Trix struct in place.
|
||||
func (t *Trix) Unpack() error {
|
||||
sigilNames := t.OutSigils
|
||||
if len(sigilNames) == 0 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue