(De)Serializing interfaces
Rikki Cattermole via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Aug 23 04:40:49 PDT 2015
On Sunday, 23 August 2015 at 10:37:11 UTC, Rikki Cattermole wrote:
> On 8/23/2015 10:17 PM, nims wrote:
>> On Sunday, 23 August 2015 at 08:38:14 UTC, Rikki Cattermole
>> wrote:
>>> What I was thinking was having a serialize method take an
>>> output range
>>> which you will just pass in a value.
>> I'm not really sure what you mean. Replacing the operator by a
>> range
>> function or serializing everything automatically?
>
> Oh not quite. Humm, how to explain this.
>
> import std.traits : isBasicType, isArray;
>
> interface Serializable {
> void serialize(OutputRange!ubyte);
> void deserialize(InputRange!ubyte);
>
> final void putValue(T)(OutputRange!ubyte output, ref T value) {
> static if (isArray!T) {
> putValue(output, value.length);
> foreach(v; value)
> putValue(v);
> } else static if (isBasicType!T) {
> // convert to ubytes ext. ext. and call put on output.
> } else if (Serializable sv = cast(Serializable)value) {
> sv.serialize(output);
> } else {
> static assert(0, "I don't know how to handle this");
> }
> }
>
> final T getValue(T)(InputRange!ubyte input) {
> ubyte[T.sizeof] ret;
> foreach(i; 0 .. T.sizeof)
> ret[i] = input.moveFront;
> return to!T(ret);
> }
> }
>
> class ... : Serializable {
> int x, y;
> float z;
>
> void serialize(OutputRange!ubyte output) {
> output.putValue(x);
> output.putValue(y);
> output.putValue(z);
> }
>
> void deserialize(InputRange!ubyte input) {
> x = input.getValue!int;
> y = input.getValue!int;
> z = input.getValue!float;
> }
> }
>
>>> A hash? Yeah, TypeInfo_Class should. It will take a pointer.
>>> https://github.com/D-Programming-Language/druntime/blob/master/src/object.d#L261
>>>
>>>
>>> size_t hash = typeid(avalue).getHash(&avalue);
>>>
>>> But keep in mind avalue must be an rvalue.
>> Sounds good! How do I then create an instance having the same
>> type?
>
> The hash value won't help you much really. It's meant for
> comparing instances.
>
>>> My suggestion would be evaluate the type "down" aka get
>>> immutable(char) from immutable(char)[] aka string. So don't
>>> try to
>>> serialize the string straight. Grab the length put that to
>>> the output
>>> range, then try to serialize each of the values of the array
>>> individually as another function call to itself.
>>>
>>> Same sort of deal with other classes, check that they have the
>>> interface and if so, call it's serialize method with yourself.
>>>
>>> A little confusing I must admit.
>> I'm sorry I didn't get that. Would you have a piece of code for
>> illustration?
>
> Take a look at the top code snippet.
> You will probably want a couple of free functions be the
> function you call to serialize and deserialize. That way it can
> control embedding e.g. the class name as the first set of
> values. Which is trivial to use with the help of e.g.
> Object.factory or with the help of TypeInfo.init.
>
> On that note I'll see about getting you a snippet of code that
> may interest you here.
> If you can please come on[0] to make it slightly easier for me.
>
> [0] https://gitter.im/rikkimax/chatWithMe
Short summary of code snippets:
~~~~~~~~~~~~~~~~~~~
module dnetdev.webserver.common.classfinder;
Interface findAndCreateClass(Interface)(string name) if
(is(Interface == class) || is(Interface == interface)) {
import std.experimental.allocator;
auto alloc = theAllocator();
auto classinfo = TypeInfo_Class.find(name);
if (classinfo is null)
return null;
size_t issize = classinfo.init.length;
void[] dataallocated = alloc.allocate(issize);
Object obj;
dataallocated[] = cast(void[])classinfo.init[];
if (dataallocated is null)
return null;
obj = cast(Object)dataallocated.ptr;
if (obj !is null) {
if (classinfo.defaultConstructor !is null)
(cast(void
function(Object))classinfo.defaultConstructor)(obj);
if (Interface obj2 = cast(Interface)obj) {
return obj2;
} else {
alloc.dispose(obj);
return null;
}
} else {
alloc.dispose(dataallocated);
return null;
}
}
~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~
void main() {
int x;
foo!x(x);
}
void foo(alias T)(typeof(T) v) {
pragma(msg, T.stringof);
}
~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~
import std.stdio;
interface Foo {
final void func(this T)(/* output */) {
writeln(T.stringof);
foreach(v; __traits(allMembers, T))
writeln(v);
}
}
class Bar : Foo {
int x;
}
void main() {
Bar b = new Bar;
b.func();
}
~~~~~~~~~~~~~~~~~~~~~
More information about the Digitalmars-d-learn
mailing list