Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ For more usage and examples see the [Godoc](http://godoc.org/github.com/ln80/str
- `email`
- `ipv4_addr`
- `credit_card`
- `fullname`

## Limitations
1. Only fields of types convertible to `string` or `*string` are supported, although nesting structs directly or through collections (slices and maps) is also supported.
Expand Down
39 changes: 39 additions & 0 deletions mask/fullname.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package mask

import (
"strings"

"github.com/ln80/struct-sensitive/internal/option"
)

type FullNameConfig struct {
}

// FullName masks a full name in the format "J*** ***** ***** D**".
func FullName(name string, opts ...func(*Config[FullNameConfig])) (string, error) {
cfg := DefaultConfig(FullNameConfig{})
option.Apply(&cfg, opts)

// Split name into words
words := strings.Fields(name)

// Mask all words except the first and last
var builder strings.Builder
for i, word := range words {
if i == 0 || i == len(words)-1 {
builder.WriteRune([]rune(word)[0])
builder.WriteString(strings.Repeat(string(cfg.Symbol), len(word)-1))
} else { // Middle words
builder.WriteString(strings.Repeat(string(cfg.Symbol), len(word)))
}
if i != len(words)-1 {
builder.WriteRune(' ')
}
}

return builder.String(), nil
}

func init() {
Register("fullname", DefaultMasker(FullName))
}
37 changes: 37 additions & 0 deletions mask/fullname_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package mask_test

import (
"testing"

"github.com/ln80/struct-sensitive/mask"
"github.com/ln80/struct-sensitive/masktest"
)

func TestFullName(t *testing.T) {
masktest.Run(t, mask.FullName, []masktest.Tc[mask.FullNameConfig]{
{
Value: "John Doe",
Want: "J*** D**",
OK: true,
},
{
Value: "Emily Anne Doe",
Want: "E**** **** D**",
OK: true,
},
{
Value: "X Æ A-12 Musk",
Want: "X ** **** M***",
OK: true,
},
})
}

func BenchmarkFullname(b *testing.B) {
for i := 0; i < b.N; i++ {
if _, err := mask.FullName("Emily Anne Doe", func(mc *mask.Config[mask.FullNameConfig]) {
}); err != nil {
b.Fatal(err)
}
}
}
Loading