Advertisement
Guest User

Untitled

a guest
Oct 17th, 2016
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 5.52 KB | None | 0 0
  1. module cbor;
  2.  
  3. private import std.string : format;
  4. private import std.traits : Unqual, isArray, isAssociativeArray, isBoolean, isDynamicArray,
  5.     isExpressionTuple, isFloatingPoint, isIntegral, isSomeChar, isStaticArray, isUnsigned;
  6. public import std.typecons : Flag, Yes, No;
  7. private import std.range : ElementEncodingType, hasLength, save, tee;
  8. private import std.conv : to;
  9. private import std.utf : byChar;
  10. private import std.range : isInputRange, isOutputRange, ElementType;
  11. private import std.typecons : isTuple;
  12.  
  13.  
  14. /// Encodes value E into output range sink.
  15. /// Returns number of bytes written to sink.
  16. /// If flatten flag is yes then static arrays and structs will be encoded in place without headers.
  17. size_t encodeCbor(R, E)(auto ref R sink, auto ref const E value)
  18.     if(isOutputRange!(R, ubyte))
  19. {
  20.     static if (is(E == struct)) {
  21.         return encodeCborArray(sink, value);
  22.     }
  23.     // { ... }
  24.     else {
  25.         // void* gets here
  26.         static assert(false, "Unable to encode " ~ E.stringof);
  27.     }
  28. }
  29.  
  30. size_t encodeCborArray(R, A)(auto ref R sink, A aggregate)
  31.     if(isOutputRange!(R, ubyte) && is(A == struct))
  32. {
  33.     return encodeCborAggregate(sink, aggregate);
  34. }
  35.  
  36. size_t encodeCborAggregate(R,A)(auto ref R sink, auto ref A aggregate)
  37.     if (isOutputRange!(R, ubyte) && is(A == struct))
  38. {
  39.     size_t size;
  40.  
  41.     foreach(i, member; aggregate.tupleof)
  42.     {
  43.         enum bool encoded = isEncodedField!(member);
  44.         enum bool encoded2 = isEncodedField!(typeof(member));
  45.         pragma(msg, "encode ", typeof(member), ": ", encoded, " ", encoded2);
  46.  
  47.         static if (encoded)
  48.         {
  49.             size += encodeCbor(sink, member);
  50.         }
  51.     }
  52.     return size;
  53. }
  54.  
  55. enum ignore;
  56.  
  57. private bool hasAttribute(alias T, UDA)() {
  58.     foreach(attr; __traits(getAttributes, T)) {
  59.         // if attribute is a type
  60.         static if(is(attr) && is(attr == UDA))
  61.             return true;
  62.         // if attribute is a value
  63.         else static if(!is(attr) && is(typeof(attr) == UDA))
  64.             return true;
  65.     }
  66.     return false;
  67. }
  68.  
  69. unittest {
  70.     enum TypeAttribute;
  71.     @TypeAttribute int i1;
  72.     static assert(hasAttribute!(i1, TypeAttribute));
  73.     int i2;
  74.     static assert(!hasAttribute!(i2, TypeAttribute));
  75.  
  76.     struct ValueAttribute {};
  77.     @ValueAttribute() int i3;
  78.     static assert(hasAttribute!(i3, ValueAttribute));
  79.     int i4;
  80.     static assert(!hasAttribute!(i4, ValueAttribute));
  81. }
  82.  
  83. private template isEncodedField(member)
  84. {
  85.     //pragma(msg, member.stringof, " is type");
  86.     enum bool isEncodedField = isEncodedType!(member);
  87.     //  && !hasAttribute!(member, ignore)
  88. }
  89.  
  90. private template isEncodedField(alias member)
  91. {
  92.     enum bool isEncodedField = isEncodedType!(typeof(member));
  93.     //pragma(msg, typeof(member), " ", member.stringof, " ", isEncodedField, " is value");
  94. }
  95.  
  96. unittest
  97. {
  98.     static class C{}
  99.     static struct Inner {}
  100.     static struct S {
  101.         Inner inner;
  102.         void* pointer;
  103.     }
  104.  
  105.     int v1;
  106.     float v2;
  107.     bool v3;
  108.     int[] v4;
  109.     C v5;
  110.     S v6;
  111.     int[int] v7;
  112.     int* v8;
  113.     void* v9;
  114.     static assert(isEncodedField!v1);
  115.     static assert(isEncodedField!v2);
  116.     static assert(isEncodedField!v3);
  117.     static assert(isEncodedField!v4);
  118.     static assert(isEncodedField!v5);
  119.     static assert(isEncodedField!v6);
  120.     static assert(isEncodedField!v7);
  121.     static assert(!isEncodedField!v8);
  122.     static assert(!isEncodedField!v9);
  123.  
  124.     foreach(i, member; v6.tupleof)
  125.     {
  126.         static if (is(typeof(member) == void*))
  127.         {
  128.             static assert(!isEncodedField!member);
  129.             static assert(!isEncodedType!(typeof(member)));
  130.         }
  131.     }
  132. }
  133.  
  134. private enum bool isEncodedType(T) = isIntegral!T || isFloatingPoint!T || isBoolean!T ||
  135.     is(Unqual!T == typeof(null)) || isArray!T || isInputRange!T || isAssociativeArray!T ||
  136.     isTuple!T || is(T == string) || is(T == class) || is(T == struct);
  137.  
  138. unittest
  139. {
  140.     static class C{}
  141.     static struct Inner {}
  142.     static struct S {
  143.         Inner inner;
  144.         void* pointer;
  145.     }
  146.  
  147.     static assert(isEncodedType!int);
  148.     static assert(isEncodedType!float);
  149.     static assert(isEncodedType!bool);
  150.     static assert(isEncodedType!(typeof(null)));
  151.     static assert(isEncodedType!(int[]));
  152.     static assert(isEncodedType!(C));
  153.     static assert(isEncodedType!(S));
  154.     static assert(isEncodedType!(int[int]));
  155.     static assert(!isEncodedType!(int*));
  156.     static assert(!isEncodedType!(void*));
  157.  
  158.     static assert(isEncodedField!int);
  159.     static assert(isEncodedField!float);
  160.     static assert(isEncodedField!bool);
  161.     static assert(isEncodedField!(typeof(null)));
  162.     static assert(isEncodedField!(int[]));
  163.     static assert(isEncodedField!(C));
  164.     static assert(isEncodedField!(S));
  165.     static assert(isEncodedField!(int[int]));
  166.     static assert(!isEncodedField!(int*));
  167.     static assert(!isEncodedField!(S.pointer));
  168.     static assert(!isEncodedField!(void*));
  169. }
  170.  
  171. /// Tests if type can be encoded in flat mode, i.e. without header
  172. private template canBeFlattened(T)
  173. {
  174.     enum bool canBeFlattened =
  175.         isStaticArray!T ||
  176.         (isTuple!T && isExpressionTuple!T) ||
  177.         is(T == struct);
  178. }
  179.  
  180. private enum bool needsFlattening(T, Flag!"Flatten" flatten) = canBeFlattened!T && flatten;
  181.  
  182. /// Returns a number of aggregate members that will be encoded by cbor-d.
  183. template numEncodableMembers(alias T)
  184. {
  185.     enum numEncodableMembers = numEncodableMembersImpl!(T.tupleof);
  186. }
  187.  
  188. private template numEncodableMembersImpl(members ...)
  189. {
  190.     static if (members.length == 0)
  191.         enum numEncodableMembersImpl = 0;
  192.     else
  193.         enum numEncodableMembersImpl =
  194.             cast(int)isEncodedField!(members[0]) +
  195.             numEncodableMembersImpl!(members[1..$]);
  196. }
  197.  
  198. unittest
  199. {
  200.     static struct Inner
  201.     {
  202.     }
  203.  
  204.     static struct Test1
  205.     {
  206.         Inner inner;
  207.         void* pointer; // not encoded
  208.     }
  209.  
  210.     ubyte[1024] buf1;
  211.     size_t size;
  212.  
  213.     Test1 test;
  214.     size = encodeCborAggregate(buf1[], test);
  215. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement