codec: faster perf, reduced allocations and re-organized codebase.

The general idea now for decode:
- dereference pointers till you get down to an actual value you can use
- decode into that value

The general idea now for encode is:
- dereference pointers till you get down to an actual value you can use
- If while dereferencing, you see a nil value, encode as nil
- Else encode the base value (non-pointer)

With this simplification, we can now dereference at the top of the
encodeValue or decodeValue function, and this reduces the number of times
we recursively call these functions.

We also made some changes to reduce allocations:
- set values on pre-declared variables

In addition, we improved performance by using a slice for extHandle (not map).
Typically, only a few extensions are added to an Encoder/Decoder.
A slice (array) with linear search is a better representation.

These changes together improved performance by 5-10%.