Range interface for std.serialization

Dmitry Olshansky dmitry.olsh at gmail.com
Sun Aug 25 13:50:21 PDT 2013


25-Aug-2013 23:15, Dicebot пишет:
> On Sunday, 25 August 2013 at 08:36:40 UTC, Dmitry Olshansky wrote:
>> Same thoughts here.
>> Serializer is an output range for pretty much anything (that is
>> serializable). Literally isOutputRange!T would be true for a whole lot
>> of things, making it possible to dumping any ranges of Ts via copy.
>> Just make its put method work on a variety of types and you have it.
>
> Can't it be both OutputRange itself and provide InputRange via
> `serialize` call (for filters & similar pipe processing)?

I see that you potentially want to say compress serialized data on the 
fly via some range-based compressor. Or send over network... with some 
byChunk(favoriteBufferSize) or rather some kind of adapter that outputs 
no less then X bytes if not at end. Then indeed it becomes awkward to 
model a 'sink' kind of range as it is a transformer (no matter how 
convenient it makes putting stuff into it).

It looks like the serializer has 2 "ends" - one accepts any element 
type, the other produces ubyte[] chunks.

A problem is how to connect that output end, or more precisely this puts 
our "ranges are the pipeline" idea into an awkward situation. Basically 
on the front end data may arrive in various chunks and ditto on the 
output. More then that it isn't just an input range translation to 
ubyte[] (at least that'd be very ineffective and restrictive). But I 
have an idea.

With all that said I get to the main point hopefully. here is an example 
far simpler then serialization.

No matter how we look at this there has to be a way to connect 2 sinks, 
say I want to do:

//can only use output range with it
formattedWrite(compressor, "Hey, %s !\n", name);

And have said compressor use LZMA on the data that is put into it, but 
it has to go somewhere. Thus problem of say compressing formatted text 
is not solved by input range, nor is the filtering of said text before 
'put'-ing it somewhere.

What's lacking is a way to connect a sink to another sink.

My view of it is:
auto app = appender!(ubyte[])();
//thus compression is an output range wrapper
auto compressor = compress!LZMA(app);

In other words an output range could be a filter, or rather forwarder of 
the transformed result to some other output range. And we need this not 
only for serialization (though formattedWrite can arguably  be seen as a 
serialization) but anytime we have to turn heterogeneous input into 
homogeneous output and post-process THAT output.

TL;DR: Simply put - make serialization an output range, and set an 
example by making archiver the first output range adapter.

Adapting the code by Jacob (Alternative AO2)

auto archiver = new XmlArchive!(char)(outputRange);
auto serializer = new Serializer(archiver);
serializer.put(new Object);
serializer.put([1, 2, 3, 4]); //mix and match stuff as you see fit

And even
copy(iota(1, 10), serializer);

Would all work just fine.

-- 
Dmitry Olshansky


More information about the Digitalmars-d mailing list