Last active
August 29, 2015 14:15
-
-
Save MrSmith33/c3bec83f624575f5ac2a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private import std.string : format; | |
private import std.traits; | |
private import std.typecons : Flag; | |
private import std.range : isInputRange, isOutputRange, ElementType; | |
private import std.typecons : isTuple; | |
/// Encodes value E into output range sink. | |
/// Returns number of bytes written to sink. | |
size_t encodeCbor(R, E)(auto ref R sink, E value) | |
if(isOutputRange!(R, ubyte)) | |
{ | |
return encodeCborArray(sink, value); | |
} | |
/// Encodes array of any items or a tuple as cbor array. | |
size_t encodeCborArray(R, E)(auto ref R sink, E value) | |
if(isOutputRange!(R, ubyte) && | |
(isInputRange!E || isArray!E || isTuple!E)) | |
{ | |
foreach(item; value) | |
encodeCbor(sink, item); | |
return 0; | |
} | |
/// Encodes structs and classes as cbor array. | |
size_t encodeCborArray(R, A)(auto ref R sink, A aggregate) | |
if(isOutputRange!(R, ubyte) && | |
(is(A == struct) || is(A == class)) && | |
!isTuple!A) | |
{ | |
return encodeCborAggregate!(Flag!"WithFieldName".no)(sink, aggregate); | |
} | |
/// Encodes classes and structs. If withFieldName is yes, than value is encoded as map. | |
/// If withFieldName is no, then value is encoded as an array. | |
size_t encodeCborAggregate(Flag!"WithFieldName" withFieldName, R, A)(auto ref R sink, auto ref A aggregate) | |
if (isOutputRange!(R, ubyte) && (is(A == struct) || is(A == class))) | |
{ | |
size_t size; | |
size += numEncodableMembers!A; | |
foreach(i, member; aggregate.tupleof) | |
{ | |
static if (__traits(compiles, { encodeCbor(sink, member); })) | |
{ | |
static if (withFieldName) | |
size += encodeCborString(sink, __traits(identifier, aggregate.tupleof[i])); | |
size += encodeCbor(sink, member); | |
} | |
} | |
return size; | |
} | |
private template isEncodedField(T) | |
{ | |
enum isEncodedField = __traits(compiles, { encodeCbor((ubyte[]).init, T.init); }); | |
} | |
/// Returns a number of aggregate members that will be encoded by cbor-d. | |
template numEncodableMembers(alias T) | |
{ | |
enum numEncodableMembers = numEncodableMembersImpl!(T.tupleof); | |
} | |
private template numEncodableMembersImpl(members ...) | |
{ | |
static if (members.length == 0) | |
enum numEncodableMembersImpl = 0; | |
else | |
enum numEncodableMembersImpl = | |
cast(int)__traits(compiles, { encodeCbor(cast(ubyte[])null, members[0].init); }) + | |
numEncodableMembersImpl!(members[1..$]); | |
} | |
unittest | |
{ | |
import std.array : Appender; | |
Appender!(ubyte[]) a; | |
class Class | |
{ | |
Class[] groups; | |
} | |
size_t b = __traits(compiles, { encodeCbor(cast(ubyte[])null, members[0].init); }); | |
encodeCborArray(a, Class[].init); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment