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:
google-labs-jules[bot] 2025-11-14 14:39:45 +00:00
parent deff3a80c6
commit fca2880355
7 changed files with 357 additions and 9 deletions

View file

@ -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
View 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
}

View file

@ -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)
}

View 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!
}

View file

@ -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
View 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
}

View file

@ -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 {