1 module libd.datastructures.growth;
2 
3 @nogc nothrow:
4 
5 alias DefaultGrowth = Growth!(
6     0, GrowTo!8,
7     8, GrowByScale!2
8 );
9 
10 struct Growth(Args...)
11 {
12     import libd.data.format : format; // Only for error messages.
13 
14     private alias GrowthFuncT = size_t function(size_t);
15 
16     // Validate that the arguments are in the correct format.
17     static assert(Args.length > 0, "There must be at least 2 args.");
18     static assert(Args.length % 2 == 0, "Range description args are uneven.");
19     static foreach(i, arg; Args)
20     {
21         static if(i % 2 == 1)
22         {
23             // static assert(
24             //     isInstanceOf!(GrowBy, typeof(arg)), 
25             //     "Arg #%s is not a growth descriptor, it is a %s".format(i, typeof(arg).stringof)
26             // );
27         }
28         else
29         {
30             static assert(
31                 __traits(compiles, { size_t a = arg; }), 
32                 "Arg #%s is not convertable to `size_t`".format(i)
33             );
34 
35             static if(i == 0)
36                 static assert(arg == 0, "The first arg must always be 0.");
37             else
38             {
39                 static assert(
40                     arg > Args[i-2],
41                     "Arg #%s (%s) must be greater than arg #%s (%s)."
42                     .format(i, arg, i-2, Args[i-2])
43                 );
44             }
45         }
46     }
47 
48     static size_t grow()(size_t from)
49     {
50         // static foreach(i; 0..(Args.length/2)-1)
51         // {
52         //     if(from >= Args[(i*2)]) return Args[i*2].grow(from);
53         // }
54         // return Args[$-2].grow(from);
55         return (from == 0) ? 32 : from * 2; // TODO
56     }
57 }
58 ///
59 @("Growth")
60 unittest
61 {
62     // alias G = Growth!(
63     //     0,   GrowTo!64,
64     //     64,  GrowByPercentage!2,
65     //     128, GrowByScale!2,
66     //     256, GrowByAmount!256
67     // );
68 
69     // size_t value = 0;
70     // value = G.grow(value);
71     // assert(value == 64);
72 
73     // value = G.grow(value);
74     // assert(value == 128);
75 
76     // value = G.grow(value);
77     // assert(value == 256);
78 
79     // value = G.grow(value);
80     // assert(value == 512);
81 }
82 
83 struct GrowBy(alias F)
84 {
85     static size_t grow(size_t from)
86     {
87         return F(from);
88     }
89 }
90 
91 auto GrowByScale(size_t scale)()
92 {
93     return GrowBy!(from => from * scale)();
94 }
95 
96 auto GrowByPercentage(double p)()
97 {
98     return GrowBy!(from => cast(size_t)((cast(double)from) * p))();
99 }
100 
101 auto GrowByAmount(size_t amount)()
102 {
103     return GrowBy!(from => from + amount)();
104 }
105 
106 auto GrowTo(size_t amount)()
107 {
108     return GrowBy!(from => amount)();
109 }