From 1d0f2238b3a9e8ea99afbefe12039dbc8deac814 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Fri, 14 Mar 2025 19:50:24 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=9A=20Move=20Slug/Hash=20Generators=20?= =?UTF-8?q?to=20own=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gen_file.go | 81 +++++++++++++++++++++++++++++++++++++ gen_file_examples_test.go | 66 ++++++++++++++++++++++++++++++ gen_file_test.go | 42 +++++++++++++++++++ generators.go | 77 ----------------------------------- generators_examples_test.go | 46 --------------------- generators_test.go | 35 ---------------- hashtype_string.go | 8 ++-- 7 files changed, 193 insertions(+), 162 deletions(-) create mode 100644 gen_file.go create mode 100644 gen_file_examples_test.go create mode 100644 gen_file_test.go diff --git a/gen_file.go b/gen_file.go new file mode 100644 index 0000000..ef239cb --- /dev/null +++ b/gen_file.go @@ -0,0 +1,81 @@ +package nomino + +import ( + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "errors" + "fmt" + "hash" + + "github.com/gosimple/slug" +) + +// ErrMissingOriginal is the error returned by Slug if there is no filename +var ErrMissingOriginal = errors.New("missing original filename") + +func getOriginal(c *Config) (string, error) { + if c.original == "" { + return "", ErrMissingOriginal + } + name := c.original + c.original = "" + return name, nil +} + +// Slug generates a name from the original filename. +// When this is used, the original filename will be removed from the final filename. +// If a language is specified, that may affect the resulting slug. +func Slug(lang ...string) Generator { + ret := slug.Make + if len(lang) > 0 { + ret = func(in string) string { + return slug.MakeLang(in, lang[0]) + } + } + return func(c *Config) (string, error) { + name, err := getOriginal(c) + return ret(name), err + } +} + +// HashingFunc is a function that generates a hash.Hash +type HashingFunc func() hash.Hash + +//go:generate stringer -type=HashType -trimprefix=Hash + +// HashType represents a particular hashing algorithm +type HashType uint8 + +const ( + HashMD5 HashType = iota + 1 + HashSHA1 + HashSHA256 +) + +// ErrInvalidHashType is returned by the Hash generator when an invalid HashType is passed +var ErrInvalidHashType = errors.New("invalid hash type") + +var hashMap = map[HashType]HashingFunc{ + HashMD5: md5.New, + HashSHA1: sha1.New, + HashSHA256: sha256.New, +} + +// Hash generates a name from a hash of the filename. +// When this is used, the original filename will be removed from the final filename. +func Hash(t HashType) Generator { + f, ok := hashMap[t] + return func(c *Config) (string, error) { + if !ok { + return "", fmt.Errorf("%w: %s", ErrInvalidHashType, t) + } + name, err := getOriginal(c) + if err != nil { + return "", err + } + hs := f() + hs.Write([]byte(name)) + return fmt.Sprintf("%x", hs.Sum(nil)), nil + } +} diff --git a/gen_file_examples_test.go b/gen_file_examples_test.go new file mode 100644 index 0000000..3d8036f --- /dev/null +++ b/gen_file_examples_test.go @@ -0,0 +1,66 @@ +package nomino_test + +import ( + "fmt" + + "codeberg.org/danjones000/nomino" +) + +func ExampleSlug() { + conf := nomino.NewConfig( + nomino.WithOriginal("My name is Jimmy"), + nomino.WithGenerator(nomino.Slug()), + ) + str, _ := nomino.Make(conf) + fmt.Println(str) + + // Output: my-name-is-jimmy.txt +} + +func ExampleSlug_withLang() { + conf := nomino.NewConfig( + nomino.WithOriginal("Diese & Dass"), + nomino.WithGenerator(nomino.Slug("de")), + ) + + str, _ := nomino.Make(conf) + fmt.Println(str) + + // Output: diese-und-dass.txt +} + +func ExampleHash_mD5() { + conf := nomino.NewConfig( + nomino.WithOriginal("foobar"), + nomino.WithGenerator( + nomino.Hash(nomino.HashMD5), + ), + ) + str, _ := nomino.Make(conf) + fmt.Println(str) + // Output: 3858f62230ac3c915f300c664312c63f.txt +} + +func ExampleHash_sHA1() { + conf := nomino.NewConfig( + nomino.WithOriginal("foobar"), + nomino.WithGenerator( + nomino.Hash(nomino.HashSHA1), + ), + ) + str, _ := nomino.Make(conf) + fmt.Println(str) + // Output: 8843d7f92416211de9ebb963ff4ce28125932878.txt +} + +func ExampleHash_sHA256() { + conf := nomino.NewConfig( + nomino.WithOriginal("foobar"), + nomino.WithGenerator( + nomino.Hash(nomino.HashSHA256), + ), + ) + str, _ := nomino.Make(conf) + fmt.Println(str) + // Output: c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2.txt +} diff --git a/gen_file_test.go b/gen_file_test.go new file mode 100644 index 0000000..0d03d16 --- /dev/null +++ b/gen_file_test.go @@ -0,0 +1,42 @@ +package nomino + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSlugMissingFilename(t *testing.T) { + conf := NewConfig(WithGenerator(Slug())) + st, err := conf.generator(&conf) + assert.Zero(t, st) + assert.ErrorIs(t, err, ErrMissingOriginal) +} + +func TestSlugRemovesOriginal(t *testing.T) { + conf := NewConfig(WithGenerator(Slug()), WithOriginal("Hello, World")) + st, err := conf.generator(&conf) + assert.Zero(t, conf.original) + assert.Equal(t, "hello-world", st) + assert.NoError(t, err) +} + +func TestHashBadHash(t *testing.T) { + conf := NewConfig(WithOriginal("foobar"), WithGenerator(Hash(0))) + st, err := conf.generator(&conf) + assert.Equal(t, "", st) + assert.ErrorIs(t, err, ErrInvalidHashType) + assert.ErrorContains(t, err, "invalid hash type: HashType(0)") +} + +func TestHashMissingOriginal(t *testing.T) { + conf := NewConfig(WithGenerator(Hash(HashMD5))) + st, err := conf.generator(&conf) + assert.Equal(t, "", st) + assert.ErrorIs(t, err, ErrMissingOriginal) +} + +func TestHashTypeStringer(t *testing.T) { + s := HashMD5.String() + assert.Equal(t, "MD5", s) +} diff --git a/generators.go b/generators.go index 2a12236..25cd36e 100644 --- a/generators.go +++ b/generators.go @@ -1,15 +1,9 @@ package nomino import ( - "crypto/md5" - "crypto/sha1" - "crypto/sha256" "errors" - "fmt" - "hash" "github.com/google/uuid" - "github.com/gosimple/slug" ) // Generator is a function that returns the "random" portion of the returned filename. @@ -62,74 +56,3 @@ func uuidGen(*Config) (string, error) { func UUID() Generator { return uuidGen } - -// ErrMissingOriginal is the error returned by Slug if there is no filename -var ErrMissingOriginal = errors.New("missing original filename") - -func getOriginal(c *Config) (string, error) { - if c.original == "" { - return "", ErrMissingOriginal - } - name := c.original - c.original = "" - return name, nil -} - -// Slug generates a name from the original filename. -// When this is used, the original filename will be removed from the final filename. -func Slug() Generator { - return func(c *Config) (string, error) { - name, err := getOriginal(c) - return slug.Make(name), err - } -} - -// SlugWithLang generates a name from the original filename, accounting for the given language. -// When this is used, the original filename will be removed from the final filename. -func SlugWithLang(lang string) Generator { - return func(c *Config) (string, error) { - name, err := getOriginal(c) - return slug.MakeLang(name, lang), err - } -} - -// HashingFunc is a function that generates a hash.Hash -type HashingFunc func() hash.Hash - -//go:generate stringer -type=HashType - -// HashType represents a particular hashing algorithm -type HashType uint8 - -const ( - MD5 HashType = iota + 1 - SHA1 - SHA256 -) - -// ErrInvalidHashType is returned by the Hash generator when an invalid HashType is passed -var ErrInvalidHashType = errors.New("invalid hash type") - -var hashMap = map[HashType]HashingFunc{ - MD5: md5.New, - SHA1: sha1.New, - SHA256: sha256.New, -} - -// Hash generates a name from a hash of the filename. -// When this is used, the original filename will be removed from the final filename. -func Hash(t HashType) Generator { - f, ok := hashMap[t] - return func(c *Config) (string, error) { - if !ok { - return "", fmt.Errorf("%w: %s", ErrInvalidHashType, t) - } - name, err := getOriginal(c) - if err != nil { - return "", err - } - hs := f() - hs.Write([]byte(name)) - return fmt.Sprintf("%x", hs.Sum(nil)), nil - } -} diff --git a/generators_examples_test.go b/generators_examples_test.go index 85563f9..d46ebef 100644 --- a/generators_examples_test.go +++ b/generators_examples_test.go @@ -18,49 +18,3 @@ func ExampleWithGenerator_custom_generator() { // hello.txt // hello } - -func ExampleSlug() { - conf := NewConfig(WithGenerator(Slug()), WithOriginal("My name is Jimmy")) - str, _ := Make(conf) - fmt.Println(str) - - // Output: my-name-is-jimmy.txt -} - -func ExampleSlugWithLang() { - conf := NewConfig(WithGenerator(SlugWithLang("de")), WithOriginal("Diese & Dass")) - str, _ := Make(conf) - fmt.Println(str) - - // Output: diese-und-dass.txt -} - -func ExampleHash_mD5() { - conf := NewConfig( - WithOriginal("foobar"), - WithGenerator(Hash(MD5)), - ) - str, _ := Make(conf) - fmt.Println(str) - // Output: 3858f62230ac3c915f300c664312c63f.txt -} - -func ExampleHash_sHA1() { - conf := NewConfig( - WithOriginal("foobar"), - WithGenerator(Hash(SHA1)), - ) - str, _ := Make(conf) - fmt.Println(str) - // Output: 8843d7f92416211de9ebb963ff4ce28125932878.txt -} - -func ExampleHash_sHA256() { - conf := NewConfig( - WithOriginal("foobar"), - WithGenerator(Hash(SHA256)), - ) - str, _ := Make(conf) - fmt.Println(str) - // Output: c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2.txt -} diff --git a/generators_test.go b/generators_test.go index 330b169..7886ded 100644 --- a/generators_test.go +++ b/generators_test.go @@ -82,38 +82,3 @@ func TestUUIDFail(t *testing.T) { _, err := UUID()(nil) assert.Equal(t, errors.New("sorry"), err) } - -func TestSlugMissingFilename(t *testing.T) { - conf := NewConfig(WithGenerator(Slug())) - st, err := conf.generator(&conf) - assert.Zero(t, st) - assert.ErrorIs(t, err, ErrMissingOriginal) -} - -func TestSlugRemovesOriginal(t *testing.T) { - conf := NewConfig(WithGenerator(Slug()), WithOriginal("Hello, World")) - st, err := conf.generator(&conf) - assert.Zero(t, conf.original) - assert.Equal(t, "hello-world", st) - assert.NoError(t, err) -} - -func TestHashBadHash(t *testing.T) { - conf := NewConfig(WithOriginal("foobar"), WithGenerator(Hash(0))) - st, err := conf.generator(&conf) - assert.Equal(t, "", st) - assert.ErrorIs(t, err, ErrInvalidHashType) - assert.ErrorContains(t, err, "invalid hash type: HashType(0)") -} - -func TestHashMissingOriginal(t *testing.T) { - conf := NewConfig(WithGenerator(Hash(MD5))) - st, err := conf.generator(&conf) - assert.Equal(t, "", st) - assert.ErrorIs(t, err, ErrMissingOriginal) -} - -func TestHashTypeStringer(t *testing.T) { - s := MD5.String() - assert.Equal(t, "MD5", s) -} diff --git a/hashtype_string.go b/hashtype_string.go index 16aa752..a4ce423 100644 --- a/hashtype_string.go +++ b/hashtype_string.go @@ -1,4 +1,4 @@ -// Code generated by "stringer -type=HashType"; DO NOT EDIT. +// Code generated by "stringer -type=HashType -trimprefix=Hash"; DO NOT EDIT. package nomino @@ -8,9 +8,9 @@ func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} - _ = x[MD5-1] - _ = x[SHA1-2] - _ = x[SHA256-3] + _ = x[HashMD5-1] + _ = x[HashSHA1-2] + _ = x[HashSHA256-3] } const _HashType_name = "MD5SHA1SHA256"