Modify Serializer::Reader to work from an externally provided ByteRange

For #2643.

This eliminates the pointless allocation and copying that happened when Reader had its own copy of the data in a std::string, and makes it easy to create a Reader to unserialise data from a FileData object (ie, easy to use with FileSystem).

(**warning**: completely untested apart from checking that it compiles)