Maps were not completely implemented before and we only had the ability
to read them from streams. In order to support every stream type on
maps, let the user define the read or write function to call for the key
and value.
Since we have to allow every fucnction type, pass the functions as
`interface{}` and call them using reflect. Note that ReadMap() currently
does not support every stream type, like structures, because we would
have to get the structure we want to read and pass it as an argument
when making the call.
While the hierarchy implementation from #27 works in some cases, it
has two problems:
- It only works for NEX version <3.5, as we aren't writing the stucture
header. This isn't exactly a problem of the PR, as it was already
wrong.
- It only checks for one layer of hierarchy, because there is no
recursion applied.
Solve this by using `WriteStructure()` instead of getting the raw bytes,
since the object data is already a `StructureInterface`.
On `ExtractFromStream()` there is no need to use reflect as the object
data will be the correct structure. Using reflect also breaks with
hierarchy for unknown reasons, so just pass the dataType to
`ReadStructure()`.
Also fix a bug where the data holder is written twice when calling
`WriteDataHolder()` because of reusing the same stream on
`dataHolder.Bytes()`.
Streams now have basic methods for reading and writing lists of all number types as well as writing a list of Structure types. Reading Structure types is currently done by the protocol lib where those types are defined
Structure.Bytes() now requires an instance of StreamOut. This is so any Structures who contain properties which are also Structures can be passed the same stream during their encoding process and retain the stream content/settings
Split the Stream struct into 2 separate stream types for clearer intent. Also now pass them a reference to the server pointer to access server config (namely the NEX minor version)
Structure NEX types are now being implemented (a push to nex-protocols-go will follow shortly). However the implementation is pretty jank and could use some work. Currently uses emulated inheritance