Initial commit

Hopefully that's everything
gvs: Fixes for handling properties of object type

* At least until GSerializable does something, the default type
  for an object property is (sa{sv})

* Object properties get wrapped in a maybe, so we need to unwrap
  them when deserializing.
tests: Add a test for handling properties of object type
tests: Add a little docstring to existing tests
Major refactor, bordering on a complete rewrite

So, GObjects are complicated. Objects don't live in a strict
hierarchy; it's possible for objects to have references to parent
objects, or sibling objects, or...

Handling this requires drastic changes in the way we serialize things.
Firstly, if we're not going to duplicate object instances, we need
some context when we're [de]serializing, so that we can look up
objects that we've already [de]serialized.

There are a few ways to do this, but the way I've gone for is to
create GvsSerializer and GvsDeserializer objects. I don't necessarily
like the names and I might change them later, but for now...

We also need a drastic change in the serialization format. Rather
than the nested heirarchy we had before, the toplevel variant is
now an "entity table", where an "entity" is something that's
referred to by a pointer. In practise this means that at the moment
it's an object, but boxed structs will also be entities. It would be
possible to add strings as entities too, but I'm not sure yet whether
this is a good idea. How often to they get shared (not copied) between
objects anyway?

This means that at the highest level, a serialized object looks like
a(sv) -- that is, an array of tuples containing a string and a variant.
For each entry in the table, the string is the GType name of the entity,
and the variant is its serialized representation.

So the serialization process now goes like this. We create the top-level
object, give it a reference number of 0, and add it to a map of
entities->reference numbers. We then add it to a FIFO queue of entities to
be serialized.

Then we start draining the queue. First up will be the toplevel object,
obviously. We start serializing each of its properties in turn. When
we find an "entity property" (at the moment, an object), we add that
entity reference to the hash table with reference number 1, and add that
entity to the serialization queue. The reference number (a uint64) is
saved as part of the object serialization.

Now suppose we're serializing the second object, and it contains a back-
pointer to the first object. At this point, we look up the object entity
in the hash table, find it's already there, and serialize the associated
reference number.

Perhaps this isn't clear, but the point is that object properties are
serialized as reference numbers pointing to the position of that
object in the entity table. When we come across a new object we haven't
seen, it triggers adding a new entity to the table. Amazingly, it all
works...

(If you think of C pointers as just a kind of reference number, then
all we're really doing is establishing a map between one set of numbers
and another...)

For deserialization, things are a little more (even more?) complicated.
We can't just go through and fully create each object in one go, because
there may be circular references. Object0 has a reference to Object1,
which causes Object1 to be constructed; but Object1 has a reference
to Object0, which isn't fully constructed until Object1 is construced...

To solve this, deserialization is now a two-step process. We first go
through and simply create each entity in the table, setting only its
construct-only properties. At this point, all references are
available, so we go through a second time setting all the remaining
properties.

If an object has another object as a construct-only property, which has
not yet been created, then it will force the construction "early". This
isn't a problem. The only way this could be problematic would be if
two objects each had construct-only references to each other; fortuntely,
if you think about it, this is impossible.

Phew! I doubt anybody is ever going to read this but still, it's all
here now...
tests: Add a test for circular references

This was the test that caused the major rewrite. Now it passes.
Hallelujah.