Align node and sigil APIs with AX principles
Some checks failed
CI / auto-fix (push) Failing after 0s
CI / auto-merge (push) Failing after 0s
CI / test (push) Failing after 4s

This commit is contained in:
Virgil 2026-03-31 05:24:39 +00:00
parent 6aa96dc7b7
commit 1cc185cb35
4 changed files with 31 additions and 81 deletions

View file

@ -122,11 +122,6 @@ func (node *Node) LoadTar(data []byte) error {
return nil
}
// Example: _ = nodeTree.WalkNode("config", func(_ string, _ fs.DirEntry, _ error) error { return nil })
func (node *Node) WalkNode(root string, fn fs.WalkDirFunc) error {
return node.Walk(root, fn)
}
// Example: options := node.WalkOptions{MaxDepth: 1, SkipErrors: true}
type WalkOptions struct {
MaxDepth int
@ -135,21 +130,16 @@ type WalkOptions struct {
}
// Example: _ = nodeTree.Walk(".", func(_ string, _ fs.DirEntry, _ error) error { return nil }, node.WalkOptions{MaxDepth: 1, SkipErrors: true})
func (node *Node) Walk(root string, fn fs.WalkDirFunc, options ...WalkOptions) error {
walkOptions := WalkOptions{}
if len(options) > 0 {
walkOptions = options[0]
}
if walkOptions.SkipErrors {
func (node *Node) Walk(root string, fn fs.WalkDirFunc, options WalkOptions) error {
if options.SkipErrors {
if _, err := node.Stat(root); err != nil {
return nil
}
}
return fs.WalkDir(node, root, func(entryPath string, entry fs.DirEntry, err error) error {
if walkOptions.Filter != nil && err == nil {
if !walkOptions.Filter(entryPath, entry) {
if options.Filter != nil && err == nil {
if !options.Filter(entryPath, entry) {
if entry != nil && entry.IsDir() {
return fs.SkipDir
}
@ -159,11 +149,11 @@ func (node *Node) Walk(root string, fn fs.WalkDirFunc, options ...WalkOptions) e
result := fn(entryPath, entry, err)
if result == nil && walkOptions.MaxDepth > 0 && entry != nil && entry.IsDir() && entryPath != root {
if result == nil && options.MaxDepth > 0 && entry != nil && entry.IsDir() && entryPath != root {
rel := core.TrimPrefix(entryPath, root)
rel = core.TrimPrefix(rel, "/")
depth := len(core.Split(rel, "/"))
if depth >= walkOptions.MaxDepth {
if depth >= options.MaxDepth {
return fs.SkipDir
}
}
@ -172,11 +162,6 @@ func (node *Node) Walk(root string, fn fs.WalkDirFunc, options ...WalkOptions) e
})
}
// Example: _ = nodeTree.WalkWithOptions(".", func(_ string, _ fs.DirEntry, _ error) error { return nil }, node.WalkOptions{MaxDepth: 1, SkipErrors: true})
func (node *Node) WalkWithOptions(root string, fn fs.WalkDirFunc, options WalkOptions) error {
return node.Walk(root, fn, options)
}
// Example: content, _ := nodeTree.ReadFile("config/app.yaml")
func (node *Node) ReadFile(name string) ([]byte, error) {
name = core.TrimPrefix(name, "/")

View file

@ -357,23 +357,6 @@ func TestNode_Walk_Good(t *testing.T) {
})
}
func TestNode_WalkNode_Good(t *testing.T) {
n := New()
n.AddData("alpha.txt", []byte("alpha"))
n.AddData("nested/beta.txt", []byte("beta"))
var paths []string
err := n.WalkNode(".", func(p string, d fs.DirEntry, err error) error {
require.NoError(t, err)
paths = append(paths, p)
return nil
})
require.NoError(t, err)
sort.Strings(paths)
assert.Equal(t, []string{".", "alpha.txt", "nested", "nested/beta.txt"}, paths)
}
// ---------------------------------------------------------------------------
// CopyFile
// ---------------------------------------------------------------------------

View file

@ -1,4 +1,4 @@
// Example: cipherSigil, _ := sigil.NewChaChaPolySigil([]byte("0123456789abcdef0123456789abcdef"))
// Example: cipherSigil, _ := sigil.NewChaChaPolySigil([]byte("0123456789abcdef0123456789abcdef"), nil)
// Example: ciphertext, _ := cipherSigil.In([]byte("payload"))
// Example: plaintext, _ := cipherSigil.Out(ciphertext)
package sigil
@ -171,7 +171,7 @@ func (obfuscator *ShuffleMaskObfuscator) deriveMask(entropy []byte, length int)
}
// Example: cipherSigil, _ := sigil.NewChaChaPolySigil(
// Example: key,
// Example: []byte("0123456789abcdef0123456789abcdef"),
// Example: &sigil.ShuffleMaskObfuscator{},
// Example: )
type ChaChaPolySigil struct {
@ -180,10 +180,10 @@ type ChaChaPolySigil struct {
randomReader goio.Reader
}
// Example: cipherSigil, _ := sigil.NewChaChaPolySigil([]byte("0123456789abcdef0123456789abcdef"))
// Example: cipherSigil, _ := sigil.NewChaChaPolySigil([]byte("0123456789abcdef0123456789abcdef"), nil)
// Example: ciphertext, _ := cipherSigil.In([]byte("payload"))
// Example: plaintext, _ := cipherSigil.Out(ciphertext)
func NewChaChaPolySigil(key []byte, obfuscators ...PreObfuscator) (*ChaChaPolySigil, error) {
func NewChaChaPolySigil(key []byte, obfuscator PreObfuscator) (*ChaChaPolySigil, error) {
if len(key) != 32 {
return nil, InvalidKeyError
}
@ -191,9 +191,8 @@ func NewChaChaPolySigil(key []byte, obfuscators ...PreObfuscator) (*ChaChaPolySi
keyCopy := make([]byte, 32)
copy(keyCopy, key)
obfuscator := PreObfuscator(&XORObfuscator{})
if len(obfuscators) > 0 && obfuscators[0] != nil {
obfuscator = obfuscators[0]
if obfuscator == nil {
obfuscator = &XORObfuscator{}
}
return &ChaChaPolySigil{
@ -203,23 +202,6 @@ func NewChaChaPolySigil(key []byte, obfuscators ...PreObfuscator) (*ChaChaPolySi
}, nil
}
// Example: cipherSigil, _ := sigil.NewChaChaPolySigil(
// Example: []byte("0123456789abcdef0123456789abcdef"),
// Example: &sigil.ShuffleMaskObfuscator{},
// Example: )
// Example: ciphertext, _ := cipherSigil.In([]byte("payload"))
// Example: plaintext, _ := cipherSigil.Out(ciphertext)
func NewChaChaPolySigilWithObfuscator(key []byte, obfuscator PreObfuscator) (*ChaChaPolySigil, error) {
cipherSigil, err := NewChaChaPolySigil(key, obfuscator)
if err != nil {
return nil, err
}
if obfuscator != nil {
cipherSigil.Obfuscator = obfuscator
}
return cipherSigil, nil
}
func (sigil *ChaChaPolySigil) In(data []byte) ([]byte, error) {
if sigil.Key == nil {
return nil, NoKeyConfiguredError

View file

@ -150,7 +150,7 @@ func TestCryptoSigil_NewChaChaPolySigil_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, err := NewChaChaPolySigil(key)
s, err := NewChaChaPolySigil(key, nil)
require.NoError(t, err)
assert.NotNil(t, s)
assert.Equal(t, key, s.Key)
@ -163,7 +163,7 @@ func TestCryptoSigil_NewChaChaPolySigil_KeyIsCopied_Good(t *testing.T) {
original := make([]byte, 32)
copy(original, key)
s, err := NewChaChaPolySigil(key)
s, err := NewChaChaPolySigil(key, nil)
require.NoError(t, err)
// Mutating the original key should not affect the sigil.
@ -172,17 +172,17 @@ func TestCryptoSigil_NewChaChaPolySigil_KeyIsCopied_Good(t *testing.T) {
}
func TestCryptoSigil_NewChaChaPolySigil_ShortKey_Bad(t *testing.T) {
_, err := NewChaChaPolySigil([]byte("too short"))
_, err := NewChaChaPolySigil([]byte("too short"), nil)
assert.ErrorIs(t, err, InvalidKeyError)
}
func TestCryptoSigil_NewChaChaPolySigil_LongKey_Bad(t *testing.T) {
_, err := NewChaChaPolySigil(make([]byte, 64))
_, err := NewChaChaPolySigil(make([]byte, 64), nil)
assert.ErrorIs(t, err, InvalidKeyError)
}
func TestCryptoSigil_NewChaChaPolySigil_EmptyKey_Bad(t *testing.T) {
_, err := NewChaChaPolySigil(nil)
_, err := NewChaChaPolySigil(nil, nil)
assert.ErrorIs(t, err, InvalidKeyError)
}
@ -219,7 +219,7 @@ func TestCryptoSigil_ChaChaPolySigil_RoundTrip_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, err := NewChaChaPolySigil(key)
s, err := NewChaChaPolySigil(key, nil)
require.NoError(t, err)
plaintext := []byte("consciousness does not merely avoid causing harm")
@ -253,7 +253,7 @@ func TestCryptoSigil_ChaChaPolySigil_NilData_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, err := NewChaChaPolySigil(key)
s, err := NewChaChaPolySigil(key, nil)
require.NoError(t, err)
enc, err := s.In(nil)
@ -269,7 +269,7 @@ func TestCryptoSigil_ChaChaPolySigil_EmptyPlaintext_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, err := NewChaChaPolySigil(key)
s, err := NewChaChaPolySigil(key, nil)
require.NoError(t, err)
ciphertext, err := s.In([]byte{})
@ -285,7 +285,7 @@ func TestCryptoSigil_ChaChaPolySigil_DifferentCiphertextsPerCall_Good(t *testing
key := make([]byte, 32)
_, _ = rand.Read(key)
s, err := NewChaChaPolySigil(key)
s, err := NewChaChaPolySigil(key, nil)
require.NoError(t, err)
plaintext := []byte("same input")
@ -312,8 +312,8 @@ func TestCryptoSigil_ChaChaPolySigil_WrongKey_Bad(t *testing.T) {
_, _ = rand.Read(key1)
_, _ = rand.Read(key2)
s1, _ := NewChaChaPolySigil(key1)
s2, _ := NewChaChaPolySigil(key2)
s1, _ := NewChaChaPolySigil(key1, nil)
s2, _ := NewChaChaPolySigil(key2, nil)
ciphertext, err := s1.In([]byte("secret"))
require.NoError(t, err)
@ -326,7 +326,7 @@ func TestCryptoSigil_ChaChaPolySigil_TruncatedCiphertext_Bad(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, _ := NewChaChaPolySigil(key)
s, _ := NewChaChaPolySigil(key, nil)
_, err := s.Out([]byte("too short"))
assert.ErrorIs(t, err, CiphertextTooShortError)
}
@ -335,7 +335,7 @@ func TestCryptoSigil_ChaChaPolySigil_TamperedCiphertext_Bad(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, _ := NewChaChaPolySigil(key)
s, _ := NewChaChaPolySigil(key, nil)
ciphertext, _ := s.In([]byte("authentic data"))
// Flip a bit in the ciphertext body (after nonce).
@ -356,7 +356,7 @@ func TestCryptoSigil_ChaChaPolySigil_RandomReaderFailure_Bad(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, _ := NewChaChaPolySigil(key)
s, _ := NewChaChaPolySigil(key, nil)
s.randomReader = &failReader{}
_, err := s.In([]byte("data"))
@ -369,7 +369,7 @@ func TestCryptoSigil_ChaChaPolySigil_NoObfuscator_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, _ := NewChaChaPolySigil(key)
s, _ := NewChaChaPolySigil(key, nil)
s.Obfuscator = nil // Disable pre-obfuscation.
plaintext := []byte("raw encryption without pre-obfuscation")
@ -387,7 +387,7 @@ func TestCryptoSigil_GetNonceFromCiphertext_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, _ := NewChaChaPolySigil(key)
s, _ := NewChaChaPolySigil(key, nil)
ciphertext, _ := s.In([]byte("nonce extraction test"))
nonce, err := GetNonceFromCiphertext(ciphertext)
@ -402,7 +402,7 @@ func TestCryptoSigil_GetNonceFromCiphertext_NonceCopied_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, _ := NewChaChaPolySigil(key)
s, _ := NewChaChaPolySigil(key, nil)
ciphertext, _ := s.In([]byte("data"))
nonce, _ := GetNonceFromCiphertext(ciphertext)
@ -430,7 +430,7 @@ func TestCryptoSigil_ChaChaPolySigil_InTransmutePipeline_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, _ := NewChaChaPolySigil(key)
s, _ := NewChaChaPolySigil(key, nil)
hexSigil, _ := NewSigil("hex")
chain := []Sigil{s, hexSigil}
@ -509,7 +509,7 @@ func TestCryptoSigil_ChaChaPolySigil_NilRandomReader_Good(t *testing.T) {
key := make([]byte, 32)
_, _ = rand.Read(key)
s, _ := NewChaChaPolySigil(key)
s, _ := NewChaChaPolySigil(key, nil)
s.randomReader = nil // Should fall back to crypto/rand.Reader.
ciphertext, err := s.In([]byte("fallback reader"))