Normalization¶
A decoded document is a tree of objects, which says exactly how the data was encoded. An application
usually wants the values instead. Objects that can give them implement the Normalizable interface, whose
normalize() method returns a native PHP value:
$text = TextStringObject::create('Hello');
$text->normalize(); // string: "Hello"
$int = UnsignedIntegerObject::create(42);
$int->normalize(); // string: "42"
$map = MapObject::create()
->add(TextStringObject::create('key'), UnsignedIntegerObject::create(100));
$map->normalize(); // array: ['key' => '100']
Normalizing a list or a map normalizes what it holds, so one call on the decoded root gives the whole document as PHP arrays and scalars.
An integer normalizes to a string
CBOR integers run to 64 bits unsigned, and the bignum tags further still, which is wider than the
integers of PHP on every platform. normalize() therefore returns a numeric string for every integer,
small ones included: a value never silently loses its precision on the way out. Cast it yourself when
you know it fits, or hand the string to brick/math.
A few objects have nothing to normalize to, and say so by not implementing the interface: the tags that
only announce how a byte string is meant to be written out, for instance
(tags 21, 22 and 23), hand back the object they wrap through
getValue() instead.
Normalization is also where a hostile document can cost the most, because a few tags expand far beyond the bytes they occupy. The bounds that keep that in check are described in the cost of a hostile document.