···88// SecretMask replaces secret values in strings with "***".
99type SecretMask struct {
1010 replacer *strings.Replacer
1111+ // length of the longest secret. writers keep the last window-1
1212+ // bytes unflushed so a secret split across writes can still match
1313+ // whole
1414+ window int
1115}
12161317// NewSecretMask creates a mask for the given secret values.
···3741 return nil
3842 }
39434444+ window := 0
4545+ for i := 0; i < len(pairs); i += 2 {
4646+ window = max(window, len(pairs[i]))
4747+ }
4848+4049 return &SecretMask{
4150 replacer: strings.NewReplacer(pairs...),
5151+ window: window,
4252 }
5353+}
5454+5555+// trailing bytes a streaming caller must keep unflushed so a secret
5656+// spanning a write boundary still matches
5757+func (m *SecretMask) Window() int {
5858+ if m == nil {
5959+ return 0
6060+ }
6161+ if m.window <= 1 {
6262+ return 0
6363+ }
6464+ return m.window - 1
4365}
44664567// Mask replaces all registered secret values with "***".