Functional Weave
Code in Rust

text.mask@1.0.0

README.md

1,599 bytes · view raw

# text.mask

Replaces every character except the last `visible` with `maskChar`:
"4242424242424242" with 4 visible is "************4242".

## Separators

With `keepSeparators` on, ASCII spaces and hyphens stay where they are and are
not counted, so a card printed in groups keeps its shape and still shows its
last four digits: "4242 4242 4242 4242" becomes "**** **** **** 4242", and the
sort code "12-34-56" with 2 visible becomes "**-**-56". Only those two
characters are separators; dots, slashes and brackets are masked like
anything else, because they are just as often part of the secret.

With it off, separators are ordinary characters: they are masked and they
count towards `visible`, so the output never reveals how a value was grouped.

## Counting

Characters are Unicode code points in all three languages, so an accented
letter or an emoji counts once, and the result always has the same number of
code points as the input. A letter written as a base letter plus a combining
accent is two code points and is masked as two.

## Edge cases

- `visible` of 0 masks everything; `visible` at or above the length returns
  the value unchanged. Nothing is padded: a short value stays short.
- A negative `visible`, or a `maskChar` that is not exactly one code point,
  is an error.

## What masking is not

Masking is for display. The digits you show must be ones you are allowed to
show - PCI DSS permits at most the first six and last four of a card number -
and the full value must not be sent to the page at all if it is not needed
there. This function does not know what the value is.