For references within the same file, if the blocks are shuffled, the ids in the tree need to be updated.  I feel that's the simplest solution...  it gets really hard to track unique ids for the data blocks given all of the ways that they can be created.  Imagine the user completely replaces an array in the tree with a new one of the same size.  That unique id is lost, but we can still reuse the empty "slot" of the old block.  One of the reasons the design includes additional space between the tree and the first block is so that the tree can be updated without an expensive insertion for exactly this reason.  I already have some semi-working code for shuffling blocks and this approach works quite well.

But importantly, and unlike FITS, these IDs don't leak into "user space" -- users refer to array data by the path of names given in the tree.

Now, for external references (below), maybe the numerical indexing is not the best approach.  I'll have to think about this.

The important aspect of this PR is that it makes the tree entirely optional so that external data files in exploded form are in fact themselves FINF files.  (We no longer have two distinct file formats).  Once you've done that, it seems logical that one should be able to reference specific blocks (using the "fragment" part of the URL) within an external file as well, but admittedly I don't really have a use case for that in mind, and maybe it's best left out.