ENH: Add masked engine
- [ ] closes #xxxx (Replace xxxx with the GitHub issue number)
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [ ] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.

```
       before           after         ratio
     [626b6510]       [efde9dd0]
-        270±10μs          148±3μs     0.55  indexing.NumericMaskedIndexing.time_get_indexer('UInt64', True)
-         210±5μs          106±1μs     0.51  indexing.NumericMaskedIndexing.time_get_indexer('Int64', True)
-        306±50μs          150±3μs     0.49  indexing.NumericMaskedIndexing.time_get_indexer('UInt64', False)
-       340±100μs          158±3μs     0.46  indexing.NumericMaskedIndexing.time_get_indexer_dups('Float64', False)
-        237±20μs        107±0.6μs     0.45  indexing.NumericMaskedIndexing.time_get_indexer('Int64', False)
-        360±70μs          157±2μs     0.44  indexing.NumericMaskedIndexing.time_get_indexer_dups('Float64', True)
-       369±100μs          155±3μs     0.42  indexing.NumericMaskedIndexing.time_get_indexer('Float64', False)
-        330±80μs          137±1μs     0.42  indexing.NumericMaskedIndexing.time_get_indexer_dups('UInt64', True)
-        335±50μs          140±2μs     0.42  indexing.NumericMaskedIndexing.time_get_indexer_dups('UInt64', False)
-       373±200μs          155±3μs     0.42  indexing.NumericMaskedIndexing.time_get_indexer('Float64', True)
-        270±30μs          106±1μs     0.39  indexing.NumericMaskedIndexing.time_get_indexer_dups('Int64', False)
-        310±60μs          110±1μs     0.36  indexing.NumericMaskedIndexing.time_get_indexer_dups('Int64', True)
```

Lets see if ci passes

im not wild about the complexity this adds to the non-cython indexing code.  wondering if we can push more of it up into the cython code.

longer-term anticipating the need for a pyarrow-engine.  is that something we can expect pyarrow to implement? @jbrockmendel so you would prefer unpacking data and mask on the cython level in the engine specific code? > @jbrockmendel so you would prefer unpacking data and mask on the cython level in the engine specific code?

I think so, yes.  but i kinda think it'll be messy regardless so either way is no big deal
 This is less ugly now :) cc @jbrockmendel Could you have another look? Added Thanks @phofl  Nice! Way to press through Thanks!

I'll work on deduplicating some parts of the code soonish (as discussed sometime during the review)