From ab4679f6d951784ab459ae8758187a2bcdc64ce1 Mon Sep 17 00:00:00 2001 From: CorentinClabaut Date: Tue, 15 Nov 2022 11:51:15 +0100 Subject: [PATCH 1/2] Add RandomString --- README.md | 12 ++++++++++++ string.go | 28 ++++++++++++++++++++++++++++ string_test.go | 19 +++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/README.md b/README.md index 210817d6..d2c7df35 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ Supported math helpers: Supported helpers for strings: +- [RandomString](#randomstring) - [Substring](#substring) - [ChunkString](#chunkstring) - [RuneLength](#runelength) @@ -1207,6 +1208,17 @@ sum := lo.SumBy(strings, func(item string) int { [[play](https://go.dev/play/p/Dz_a_7jN_ca)] +### RandomString + +Returns a random string of the specified length and made of the specified charset. + +```go +str := lo.RandomString(5, lo.LettersCharset) +// example: "eIGbt" +``` + +[[play](https://go.dev/play/p/5zFLTHCxe_T)] + ### Substring Return part of a string. diff --git a/string.go b/string.go index a63167cb..b155ab13 100644 --- a/string.go +++ b/string.go @@ -1,9 +1,37 @@ package lo import ( + "math/rand" "unicode/utf8" ) +const ( + LowerCaseLettersCharset = "abcdefghijklmnopqrstuvwxyz" + UpperCaseLettersCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + LettersCharset = LowerCaseLettersCharset + UpperCaseLettersCharset + NumbersCharset = "0123456789" + SpecialCharset = "!@#$%^&*()_+-=[]{}|;':\",./<>?" + AllCharset = LettersCharset + NumbersCharset + SpecialCharset +) + +// RandomString return a random string. +// Play: https://go.dev/play/p/5zFLTHCxe_T +func RandomString[T ~string](size int, charset string) T { + if size <= 0 { + panic("lo.RandomString: Size parameter must be greater than 0") + } + if len(charset) <= 0 { + panic("lo.RandomString: Charset parameter must not be empty") + } + + b := make([]byte, size) + possibleCharactersCount := len(charset) + for i := range b { + b[i] = charset[rand.Intn(possibleCharactersCount)] + } + return T(b) +} + // Substring return part of a string. // Play: https://go.dev/play/p/TQlxQi82Lu1 func Substring[T ~string](str T, offset int, length uint) T { diff --git a/string_test.go b/string_test.go index 02a64160..6c1a43df 100644 --- a/string_test.go +++ b/string_test.go @@ -2,11 +2,30 @@ package lo import ( "math" + "math/rand" "testing" + "time" "github.com/stretchr/testify/assert" ) +func TestRandomString(t *testing.T) { + t.Parallel() + is := assert.New(t) + + rand.Seed(time.Now().UnixNano()) + + str1 := RandomString[string](100, LowerCaseLettersCharset) + is.Equal(100, len(str1)) + is.Subset([]byte(LowerCaseLettersCharset), []byte(str1)) + + str2 := RandomString[string](100, LowerCaseLettersCharset) + is.NotEqual(str1, str2) + + is.Panics(func() { RandomString[string](100, "") }) + is.Panics(func() { RandomString[string](0, LowerCaseLettersCharset) }) +} + func TestChunkString(t *testing.T) { t.Parallel() is := assert.New(t) From a31d33fa64134b73c76ed7ad769679799f1439ef Mon Sep 17 00:00:00 2001 From: CorentinClabaut Date: Tue, 15 Nov 2022 21:05:09 +0100 Subject: [PATCH 2/2] PR update --- README.md | 2 +- string.go | 23 ++++++++++++----------- string_test.go | 17 +++++++++++------ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index d2c7df35..7db5de45 100644 --- a/README.md +++ b/README.md @@ -1217,7 +1217,7 @@ str := lo.RandomString(5, lo.LettersCharset) // example: "eIGbt" ``` -[[play](https://go.dev/play/p/5zFLTHCxe_T)] +[[play](https://go.dev/play/p/rRseOQVVum4)] ### Substring diff --git a/string.go b/string.go index b155ab13..dfe1050b 100644 --- a/string.go +++ b/string.go @@ -5,18 +5,19 @@ import ( "unicode/utf8" ) -const ( - LowerCaseLettersCharset = "abcdefghijklmnopqrstuvwxyz" - UpperCaseLettersCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - LettersCharset = LowerCaseLettersCharset + UpperCaseLettersCharset - NumbersCharset = "0123456789" - SpecialCharset = "!@#$%^&*()_+-=[]{}|;':\",./<>?" - AllCharset = LettersCharset + NumbersCharset + SpecialCharset +var ( + LowerCaseLettersCharset = []rune("abcdefghijklmnopqrstuvwxyz") + UpperCaseLettersCharset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + LettersCharset = append(LowerCaseLettersCharset, UpperCaseLettersCharset...) + NumbersCharset = []rune("0123456789") + AlphanumericCharset = append(LettersCharset, NumbersCharset...) + SpecialCharset = []rune("!@#$%^&*()_+-=[]{}|;':\",./<>?") + AllCharset = append(AlphanumericCharset, SpecialCharset...) ) // RandomString return a random string. -// Play: https://go.dev/play/p/5zFLTHCxe_T -func RandomString[T ~string](size int, charset string) T { +// Play: https://go.dev/play/p/rRseOQVVum4 +func RandomString(size int, charset []rune) string { if size <= 0 { panic("lo.RandomString: Size parameter must be greater than 0") } @@ -24,12 +25,12 @@ func RandomString[T ~string](size int, charset string) T { panic("lo.RandomString: Charset parameter must not be empty") } - b := make([]byte, size) + b := make([]rune, size) possibleCharactersCount := len(charset) for i := range b { b[i] = charset[rand.Intn(possibleCharactersCount)] } - return T(b) + return string(b) } // Substring return part of a string. diff --git a/string_test.go b/string_test.go index 6c1a43df..c423c351 100644 --- a/string_test.go +++ b/string_test.go @@ -15,15 +15,20 @@ func TestRandomString(t *testing.T) { rand.Seed(time.Now().UnixNano()) - str1 := RandomString[string](100, LowerCaseLettersCharset) - is.Equal(100, len(str1)) - is.Subset([]byte(LowerCaseLettersCharset), []byte(str1)) + str1 := RandomString(100, LowerCaseLettersCharset) + is.Equal(100, RuneLength(str1)) + is.Subset(LowerCaseLettersCharset, []rune(str1)) - str2 := RandomString[string](100, LowerCaseLettersCharset) + str2 := RandomString(100, LowerCaseLettersCharset) is.NotEqual(str1, str2) - is.Panics(func() { RandomString[string](100, "") }) - is.Panics(func() { RandomString[string](0, LowerCaseLettersCharset) }) + noneUtf8Charset := []rune("明1好休2林森") + str3 := RandomString(100, noneUtf8Charset) + is.Equal(100, RuneLength(str3)) + is.Subset(noneUtf8Charset, []rune(str3)) + + is.PanicsWithValue("lo.RandomString: Charset parameter must not be empty", func() { RandomString(100, []rune{}) }) + is.PanicsWithValue("lo.RandomString: Size parameter must be greater than 0", func() { RandomString(0, LowerCaseLettersCharset) }) } func TestChunkString(t *testing.T) {