Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module cbor;
- private import std.string : format;
- private import std.traits : Unqual, isArray, isAssociativeArray, isBoolean, isDynamicArray,
- isExpressionTuple, isFloatingPoint, isIntegral, isSomeChar, isStaticArray, isUnsigned;
- public import std.typecons : Flag, Yes, No;
- private import std.range : ElementEncodingType, hasLength, save, tee;
- private import std.conv : to;
- private import std.utf : byChar;
- 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.
- /// If flatten flag is yes then static arrays and structs will be encoded in place without headers.
- size_t encodeCbor(R, E)(auto ref R sink, auto ref const E value)
- if(isOutputRange!(R, ubyte))
- {
- static if (is(E == struct)) {
- return encodeCborArray(sink, value);
- }
- // { ... }
- else {
- // void* gets here
- static assert(false, "Unable to encode " ~ E.stringof);
- }
- }
- size_t encodeCborArray(R, A)(auto ref R sink, A aggregate)
- if(isOutputRange!(R, ubyte) && is(A == struct))
- {
- return encodeCborAggregate(sink, aggregate);
- }
- size_t encodeCborAggregate(R,A)(auto ref R sink, auto ref A aggregate)
- if (isOutputRange!(R, ubyte) && is(A == struct))
- {
- size_t size;
- foreach(i, member; aggregate.tupleof)
- {
- enum bool encoded = isEncodedField!(member);
- enum bool encoded2 = isEncodedField!(typeof(member));
- pragma(msg, "encode ", typeof(member), ": ", encoded, " ", encoded2);
- static if (encoded)
- {
- size += encodeCbor(sink, member);
- }
- }
- return size;
- }
- enum ignore;
- private bool hasAttribute(alias T, UDA)() {
- foreach(attr; __traits(getAttributes, T)) {
- // if attribute is a type
- static if(is(attr) && is(attr == UDA))
- return true;
- // if attribute is a value
- else static if(!is(attr) && is(typeof(attr) == UDA))
- return true;
- }
- return false;
- }
- unittest {
- enum TypeAttribute;
- @TypeAttribute int i1;
- static assert(hasAttribute!(i1, TypeAttribute));
- int i2;
- static assert(!hasAttribute!(i2, TypeAttribute));
- struct ValueAttribute {};
- @ValueAttribute() int i3;
- static assert(hasAttribute!(i3, ValueAttribute));
- int i4;
- static assert(!hasAttribute!(i4, ValueAttribute));
- }
- private template isEncodedField(member)
- {
- //pragma(msg, member.stringof, " is type");
- enum bool isEncodedField = isEncodedType!(member);
- // && !hasAttribute!(member, ignore)
- }
- private template isEncodedField(alias member)
- {
- enum bool isEncodedField = isEncodedType!(typeof(member));
- //pragma(msg, typeof(member), " ", member.stringof, " ", isEncodedField, " is value");
- }
- unittest
- {
- static class C{}
- static struct Inner {}
- static struct S {
- Inner inner;
- void* pointer;
- }
- int v1;
- float v2;
- bool v3;
- int[] v4;
- C v5;
- S v6;
- int[int] v7;
- int* v8;
- void* v9;
- static assert(isEncodedField!v1);
- static assert(isEncodedField!v2);
- static assert(isEncodedField!v3);
- static assert(isEncodedField!v4);
- static assert(isEncodedField!v5);
- static assert(isEncodedField!v6);
- static assert(isEncodedField!v7);
- static assert(!isEncodedField!v8);
- static assert(!isEncodedField!v9);
- foreach(i, member; v6.tupleof)
- {
- static if (is(typeof(member) == void*))
- {
- static assert(!isEncodedField!member);
- static assert(!isEncodedType!(typeof(member)));
- }
- }
- }
- private enum bool isEncodedType(T) = isIntegral!T || isFloatingPoint!T || isBoolean!T ||
- is(Unqual!T == typeof(null)) || isArray!T || isInputRange!T || isAssociativeArray!T ||
- isTuple!T || is(T == string) || is(T == class) || is(T == struct);
- unittest
- {
- static class C{}
- static struct Inner {}
- static struct S {
- Inner inner;
- void* pointer;
- }
- static assert(isEncodedType!int);
- static assert(isEncodedType!float);
- static assert(isEncodedType!bool);
- static assert(isEncodedType!(typeof(null)));
- static assert(isEncodedType!(int[]));
- static assert(isEncodedType!(C));
- static assert(isEncodedType!(S));
- static assert(isEncodedType!(int[int]));
- static assert(!isEncodedType!(int*));
- static assert(!isEncodedType!(void*));
- static assert(isEncodedField!int);
- static assert(isEncodedField!float);
- static assert(isEncodedField!bool);
- static assert(isEncodedField!(typeof(null)));
- static assert(isEncodedField!(int[]));
- static assert(isEncodedField!(C));
- static assert(isEncodedField!(S));
- static assert(isEncodedField!(int[int]));
- static assert(!isEncodedField!(int*));
- static assert(!isEncodedField!(S.pointer));
- static assert(!isEncodedField!(void*));
- }
- /// Tests if type can be encoded in flat mode, i.e. without header
- private template canBeFlattened(T)
- {
- enum bool canBeFlattened =
- isStaticArray!T ||
- (isTuple!T && isExpressionTuple!T) ||
- is(T == struct);
- }
- private enum bool needsFlattening(T, Flag!"Flatten" flatten) = canBeFlattened!T && flatten;
- /// 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)isEncodedField!(members[0]) +
- numEncodableMembersImpl!(members[1..$]);
- }
- unittest
- {
- static struct Inner
- {
- }
- static struct Test1
- {
- Inner inner;
- void* pointer; // not encoded
- }
- ubyte[1024] buf1;
- size_t size;
- Test1 test;
- size = encodeCborAggregate(buf1[], test);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement