1 /**
2  * Several trivial functions and structures
3  */
4 module iz.sugar;
5 
6 import
7     std.traits, std.meta, std.typecons, std.functional;
8 import
9     std.range.primitives: isInputRange, ElementType, ElementEncodingType,
10         isBidirectionalRange;
11 
12 /**
13  * Alternative to std.range primitives for arrays.
14  *
15  * The source is never consumed.
16  * The range always verifies isInputRange and isForwardRange. When the source
17  * array element type if not a character type or if the template parameter
18  * assumeDecoded is set to true then the range also verifies
19  * isForwardRange.
20  *
21  * When the source is an array of character and if assumeDecoded is set to false
22  * (the default) then the ArrayRange front type is always dchar because of the
23  * UTF decoding. The parameter can be set to true if the source is known to
24  * contains only SBCs.
25  *
26  * The template parameter infinite allows to turn the range in an infinite range
27  * that loops over the elements.
28  */
29 struct ArrayRange(T, bool assumeDecoded = false, bool infinite = false)
30 {
31     static if (!isSomeChar!T || assumeDecoded || is(T==dchar))
32     {
33         private T* _front, _back;
34         private static if(infinite) T* _first;
35         ///
36         this(ref T[] stuff)
37         {
38             _front = stuff.ptr;
39             _back = _front + stuff.length - 1;
40             static if(infinite) _first = _front;
41         }
42         ///
43         @property bool empty()
44         {
45             static if (infinite)
46                 return false;
47             else
48                 return _front > _back;
49         }
50         ///
51         T front()
52         {
53             return *_front;
54         }
55         ///
56         T back()
57         {
58             return *_back;
59         }
60         ///
61         void popFront()
62         {
63             ++_front;
64             static if (infinite)
65             {
66                 if (_front > _back)
67                     _front = _first;
68             }
69         }
70         ///
71         void popBack()
72         {
73             --_back;
74         }
75         /// returns a slice of the source, according to front and back.
76         T[] array()
77         {
78             return _front[0 .. _back - _front + 1];
79         }
80         ///
81         typeof(this) save()
82         {
83             typeof(this) result;
84             result._front = _front;
85             result._back = _back;
86             return result;
87         }
88     }
89     else
90     {
91 
92     private:
93 
94         import std.utf: decode;
95         size_t _position, _previous, _len;
96         dchar _decoded;
97         T* _front;
98         bool _decode;
99 
100         void readNext()
101         {
102             _previous = _position;
103             auto str = _front[0 .. _len];
104             _decoded = decode(str, _position);
105         }
106 
107     public:
108 
109         ///
110         this(ref T[] stuff)
111         {
112             _front = stuff.ptr;
113             _len = stuff.length;
114             _decode = true;
115         }
116         ///
117         @property bool empty()
118         {
119             return _position >= _len;
120         }
121         ///
122         dchar front()
123         {
124             if (_decode)
125             {
126                 _decode = false;
127                 readNext;
128             }
129             return _decoded;
130         }
131         ///
132         void popFront()
133         {
134             if (_decode) readNext;
135             _decode = true;
136         }
137         /// returns a slice of the source, according to front and back.
138         T[] array()
139         {
140             return _front[_previous .. _len];
141         }
142         ///
143         typeof(this) save()
144         {
145             typeof(this) result;
146             result._position   = _position;
147             result._previous   = _previous;
148             result._len        = _len;
149             result._decoded    = _decoded;
150             result._front      = _front;
151             result._decode     = _decode;
152             return result;
153         }
154     }
155 }
156 
157 unittest
158 {
159     auto arr = "bla";
160     auto rng = ArrayRange!(immutable(char))(arr);
161     assert(rng.array == "bla", rng.array);
162     assert(rng.front == 'b');
163     rng.popFront();
164     assert(rng.front == 'l');
165     rng.popFront();
166     assert(rng.front == 'a');
167     rng.popFront();
168     assert(rng.empty);
169     assert(arr == "bla");
170     //
171     auto t1 = "é_é";
172     auto r1 = ArrayRange!(immutable(char))(t1);
173     auto r2 = r1.save;
174     foreach(i; 0 .. 3) r1.popFront();
175     assert(r1.empty);
176     r1 = r2;
177     assert(r1.front == 'é');
178     //
179     auto r3 = ArrayRange!(immutable(char),true)(t1);
180     foreach(i; 0 .. 5) r3.popFront();
181     assert(r3.empty);
182 }
183 
184 unittest
185 {
186     ubyte[] src = [1,2,3,4,5];
187     ubyte[] arr = src.dup;
188     auto rng = ArrayRange!ubyte(arr);
189     ubyte cnt = 1;
190     while (!rng.empty)
191     {
192         assert(rng.front == cnt++);
193         rng.popFront();
194     }
195     assert(arr == src);
196     auto bck = ArrayRange!ubyte(arr);
197     assert(bck.back == 5);
198     bck.popBack;
199     assert(bck.back == 4);
200     assert(bck.array == [1,2,3,4]);
201     auto sbk = bck.save;
202     bck.popBack;
203     sbk.popBack;
204     assert(bck.back == sbk.back);
205 }
206 
207 
208 /**
209  * Calls a function according to a probability
210  *
211  * Params:
212  *      t = The chance to call, in percentage.
213  *      fun = The function to call. It must be a void function.
214  *      a = The variadic argument passed to fun.
215  *
216  * Returns:
217  *      false if no luck.
218  */
219 bool pickAndCall(T, Fun, A...)(T t, Fun fun, auto ref A a)
220 if (isNumeric!T && isCallable!Fun && is(ReturnType!Fun == void))
221 in
222 {
223     static immutable string err = "chance to pick must be in the 0..100 range";
224     assert(t <= 100, err);
225     assert(t >= 0, err);
226 }
227 do
228 {
229     import std.random: uniform;
230     static immutable T min = 0;
231     static immutable T max = 100;
232     const bool result = uniform!"[]"(min, max) > max - t;
233     if (result) fun(a);
234     return result;
235 }
236 ///
237 @safe unittest
238 {
239     uint cnt;
240     bool test;
241     void foo(uint param0, out bool param1) @safe
242     {
243         cnt += param0;
244         param1 = true;
245     }
246     foreach(immutable i; 0 .. 100)
247         pickAndCall!(double)(75.0, &foo, 1, test);
248     assert(cnt > 25);
249     assert(test);
250     cnt = 0;
251     test = false;
252     foreach(immutable i; 0 .. 100)
253         pickAndCall!(byte)(0, &foo, 1, test);
254     assert(cnt == 0);
255     assert(!test);
256 }
257 
258 /**
259  * Pops an input range while a predicate is true.
260  * Consumes the input argument.
261  *
262  * Params:
263  *      pred = the predicate.
264  *      range = an input range, must be a lvalue.
265  */
266 void popWhile(alias pred, Range)(ref Range range)
267 if (isInputRange!Range && is(typeof(unaryFun!pred)) && isImplicitlyConvertible!
268         (typeof(unaryFun!pred((ElementType!Range).init)), bool))
269 {
270     import std.range.primitives: front, empty, popFront;
271     alias f = unaryFun!pred;
272     while (!range.empty)
273     {
274         if (!f(range.front))
275             break;
276         else
277             range.popFront();
278     }
279 }
280 ///
281 pure @safe unittest
282 {
283     string r0 = "aaaaabcd";
284     r0.popWhile!"a == 'a'";
285     assert(r0 == "bcd");
286 
287     static bool lessTwo(T)(T t)
288     {
289         return t < 2;
290     }
291     int[] r1 = [0,1,2,0,1,2];
292     r1.popWhile!lessTwo;
293     assert(r1 == [2,0,1,2]);
294 
295     static bool posLessFive(T)(T t)
296     {
297         return t < 5 && t > 0;
298     }
299     int[] r3 = [2,3,4,-1];
300     r3.popWhile!posLessFive;
301     assert(r3 == [-1]);
302     int[] r4 = [2,3,4,5];
303     r4.popWhile!posLessFive;
304     assert(r4 == [5]);
305 }
306 
307 /**
308  * Convenience function that calls popWhile() on the input argument
309  * and returns the consumed range to allow function pipelining.
310  * In addition this wrapper accepts rvalues.
311  */
312 auto dropWhile(alias pred, Range)(auto ref Range range)
313 if (isInputRange!Range && is(typeof(unaryFun!pred)) && isImplicitlyConvertible!
314         (typeof(unaryFun!pred((ElementType!Range).init)), bool))
315 {
316     popWhile!(pred, Range)(range);
317     return range;
318 }
319 ///
320 pure @safe unittest
321 {
322     assert("aaaaabcd".dropWhile!"a == 'a'" == "bcd");
323 }
324 
325 /**
326  * Pops back an input range while a predicate is true.
327  * Consumes the input argument.
328  *
329  * Params:
330  *      pred = the predicate.
331  *      range = an input range, must be a lvalue.
332  */
333 void popBackWhile(alias pred, Range)(ref Range range)
334 if (isBidirectionalRange!Range && is(typeof(unaryFun!pred)) && isImplicitlyConvertible!
335         (typeof(unaryFun!pred((ElementType!Range).init)), bool))
336 {
337     import std.range.primitives: back, empty, popBack;
338     alias f = unaryFun!pred;
339     while (!range.empty)
340     {
341         if (!f(range.back))
342             break;
343         else
344             range.popBack;
345     }
346 }
347 ///
348 pure @safe unittest
349 {
350     string r0 = "bcdaaaa";
351     r0.popBackWhile!"a == 'a'";
352     assert(r0 == "bcd");
353 
354     static bool lessTwo(T)(T t)
355     {
356         return t < 2;
357     }
358     int[] r1 = [0,1,2,2,1,0];
359     r1.popBackWhile!lessTwo;
360     assert(r1 == [0,1,2,2]);
361 
362     static bool posLessFive(T)(T t)
363     {
364         return t < 5 && t > 0;
365     }
366     int[] r3 = [-1,2,3,4];
367     r3.popBackWhile!posLessFive;
368     assert(r3 == [-1]);
369     int[] r4 = [5,2,3,4];
370     r4.popBackWhile!posLessFive;
371     assert(r4 == [5]);
372 }
373 
374 /**
375  * Convenience function that calls popBackWhile() on the input argument
376  * and returns the consumed range to allow function pipelining.
377  * In addition this wrapper accepts rvalues.
378  */
379 auto dropBackWhile(alias pred, Range)(auto ref Range range)
380 if (isBidirectionalRange!Range && is(typeof(unaryFun!pred)) && isImplicitlyConvertible!
381         (typeof(unaryFun!pred((ElementType!Range).init)), bool))
382 {
383     popBackWhile!(pred, Range)(range);
384     return range;
385 }
386 ///
387 pure @safe unittest
388 {
389     assert("abcdefgh".dropBackWhile!"a > 'e'" == "abcde");
390 }
391 
392 /**
393  * Returns a lazy input range that alterntively returns the state of one of two
394  * sub-ranges.
395  *
396  * Similar to std.range roundRobin() or chain() except that the resulting range
397  * is considered as empty when one of the sub range is consumed.
398  *
399  * Params:
400  *      flip = the first input range.
401  *      flop = the second input range.
402  */
403 auto flipFlop(R1, R2)(auto ref R1 flip, auto ref R2 flop)
404 if (isInputRange!R1 && isInputRange!R2 && is(ElementType!R1 == ElementType!R2))
405 {
406     import std.range.primitives: front, empty, popFront;
407     struct FlipFlop
408     {
409         private bool _takeFlop;
410 
411         ///
412         bool empty()
413         {
414             return (flip.empty && !_takeFlop) | (_takeFlop && flop.empty);
415         }
416         ///
417         auto front()
418         {
419             final switch (_takeFlop)
420             {
421                 case false: return flip.front;
422                 case true:  return flop.front;
423             }
424         }
425         ///
426         void popFront()
427         {
428             _takeFlop = !_takeFlop;
429             final switch (_takeFlop)
430             {
431                 case false: return flop.popFront();
432                 case true:  return flip.popFront();
433             }
434         }
435     }
436     FlipFlop ff;
437     return ff;
438 }
439 ///
440 pure @safe unittest
441 {
442     import std.array: array;
443     assert(flipFlop([0,2,4],[1,3,5]).array == [0,1,2,3,4,5]);
444     assert(flipFlop([0,2],[1,3,5]).array == [0,1,2,3]);
445     assert(flipFlop([0,2,4],[1,3]).array == [0,1,2,3,4]);
446     int[] re = [];
447     assert(flipFlop([0], re).array == [0]);
448     assert(flipFlop(re, re).array == []);
449     assert(flipFlop(re, [0]).array == []);
450 }
451 
452 /**
453  * Returns a lazy input range that takes from the input while a predicate is
454  * verified and the input is not empty.
455  *
456  * Params:
457  *      pred = the predicate.
458  *      range = an input range, only consumed when passed by reference.
459  */
460 auto takeWhile(alias pred, Range)(auto ref Range range)
461 if (isInputRange!Range && is(typeof(unaryFun!pred)) && isImplicitlyConvertible!
462         (typeof(unaryFun!pred((ElementType!Range).init)), bool))
463 {
464     alias f = unaryFun!pred;
465     import std.range.primitives: front, empty, popFront;
466     struct Taker
467     {
468         ///
469         bool empty()
470         {
471             return range.empty || !f(range.front);
472         }
473         ///
474         void popFront()
475         {
476             range.popFront();
477         }
478         ///
479         auto front()
480         {
481             return range.front;
482         }
483     }
484     Taker result;
485     return result;
486 }
487 ///
488 pure @safe unittest
489 {
490     import std.range: array;
491     import std.ascii: isDigit;
492     auto r = "012A";
493     assert(takeWhile!((a) => isDigit(a))(r).array == "012");
494     assert(r == "A");
495     assert(takeWhile!((a) => isDigit(a))(r).array == "");
496     assert(takeWhile!((a) => isDigit(a))("").array == "");
497 }
498 
499 /**
500  * Returns a lazy input range that takes from the input tail while a
501  * predicate is verified and the input is not empty.
502  *
503  * Params:
504  *      pred = the predicate.
505  *      range = an bidirectional range, only consumed when passed by reference.
506  */
507 auto takeBackWhile(alias pred, Range)(auto ref Range range)
508 if (isBidirectionalRange!Range && is(typeof(unaryFun!pred)) && isImplicitlyConvertible!
509         (typeof(unaryFun!pred((ElementType!Range).init)), bool))
510 {
511     alias f = unaryFun!pred;
512     import std.range.primitives: back, empty, popBack;
513     struct Taker
514     {
515         ///
516         bool empty()
517         {
518             return range.empty || !f(range.back);
519         }
520         ///
521         void popFront()
522         {
523             range.popBack;
524         }
525         ///
526         auto front()
527         {
528             return range.back;
529         }
530     }
531     Taker result;
532     return result;
533 }
534 ///
535 pure @safe unittest
536 {
537     import std.range: array;
538     import std.ascii: isDigit;
539     auto r = "A123";
540     assert(takeBackWhile!((a) => isDigit(a))(r).array == "321");
541     assert(r == "A");
542     assert(takeBackWhile!((a) => isDigit(a))(r).array == "");
543     assert(takeBackWhile!((a) => isDigit(a))("").array == "");
544 }
545 
546 /** Indicates how many elements of a range are different from the default
547  * element value.
548  *
549  * Params:
550  *      range = An input range. The elements must be mutable and initializable.
551  *      Narrow srings are not considered as validate input parameter.
552  *
553  * Returns:
554  *      A number equal to the count of elements that are different from their
555  *      initializer.
556  */
557 size_t mutatedCount(Range)(Range range)
558 if (isInputRange!Range && is(typeof((ElementType!Range).init))
559         && isMutable!(ElementType!Range) && !isNarrowString!Range)
560 {
561     import std.range.primitives: front, empty, popFront;
562 
563     size_t result;
564     const(ElementType!Range) noone = (ElementType!Range).init;
565     while (!range.empty)
566     {
567         result += ubyte(range.front != noone);
568         range.popFront();
569     }
570     return result;
571 }
572 ///
573 unittest
574 {
575     int[] i = [0,0,1];
576     assert(i.mutatedCount == 1);
577     assert(i[0..$-1].mutatedCount == 0);
578 
579     string[] s = ["","a"];
580     assert(s.mutatedCount == 1);
581 
582     dchar[] dc = [dchar.init, 'g'];
583     assert(dc.mutatedCount == 1);
584 
585     class Foo {}
586     Foo[] f = new Foo[](8);
587     assert(f.mutatedCount == 0);
588     f[0] = new Foo;
589     f[1] = new Foo;
590     assert(f.mutatedCount == 2);
591 
592     // w/char.init leads to decoding invalid UTF8 sequence
593     static assert(!is(typeof(mutatedCount!(char[]))));
594     static assert(!is(typeof(mutatedCount!(wchar[]))));
595 
596     static assert(is(typeof(mutatedCount!(dchar[]))));
597 }
598 
599 /**
600  * Allows to pass always a parameter as value even if it would be accepted
601  * as reference.
602  */
603 auto rValue(T)(auto ref T t)
604 {
605     return t;
606 }
607 ///
608 unittest
609 {
610     void foo(T)(ref T t){}
611     uint a;
612     static assert(is(typeof(foo(a))));
613     static assert(!is(typeof(foo(a.rValue))));
614 }
615 
616 /**
617  * Compares two integral values with additional static checkings.
618  *
619  * If the comparison mixes signed and unsigned operands then the function tries
620  * to widen the unsigned operand to perform a valid comparison, otherwise
621  * a DMD-style warning is emitted.
622  *
623  * Params:
624  *      op = The comparison operator, must be either >, < , <= or >=. Equality
625  *          is also allowed even if this is always a transparent operation.
626  *      lhs = The left operand, an integer.
627  *      rhs = The right operand, an integer.
628  *
629  *  Returns:
630  *      A bool, the comparison result.
631  */
632 bool compare(string op, L, R, string fname = __FILE__, int line = __LINE__)
633     (auto ref L lhs, auto ref R rhs)
634 if ((isIntegral!R &&  isIntegral!L) && op == "<" || op == ">" || op == "<=" ||
635         op == ">=" || op == "==" || op == "!=")
636 {
637     alias LT = Unqual!L;
638     alias RT = Unqual!R;
639 
640     // transparent
641     static if (is(LT == RT) || op == "==" || op == "!=")
642     {
643         mixin("return lhs" ~ op ~ "rhs;");
644     }
645     else
646     {
647         enum err = fname ~ "(" ~ line.stringof ~ "): ";
648         enum wer = "warning, signed and unsigned comparison, the unsigned operand has been widened";
649 
650         template Widened(T)
651         {
652             static if (is(T==ubyte))
653                 alias Widened = short;
654             else static if (is(T==ushort))
655                 alias Widened = int;
656             else static if (is(T==uint))
657                 alias Widened = long;
658         }
659 
660         // widen unsigned to bigger signed
661         static if (isSigned!LT && !isSigned!RT  && RT.sizeof < 8)
662         {
663             version(D_Warnings) pragma(msg, err ~ wer);
664             Widened!RT widenedRhs = rhs;
665             mixin("return lhs" ~ op ~ "widenedRhs;");
666         }
667         else static if (isSigned!RT && !isSigned!LT  && LT.sizeof < 8)
668         {
669             version(D_Warnings) pragma(msg, err ~ wer);
670             Widened!LT widenedLhs = lhs;
671             mixin("return widenedLhs" ~ op ~ "rhs;");
672         }
673         // not fixable by widening
674         else
675         {
676             pragma(msg, err ~ "warning, comparing a " ~ L.stringof ~ " with a "
677                 ~ R.stringof ~ " may result into wrong results");
678             mixin("return lhs" ~ op ~ "rhs;");
679         }
680     }
681 }
682 ///
683 pure @safe @nogc nothrow unittest
684 {
685     int a = -1; uint b;
686     assert(a > b); // wrong result
687     assert(compare!">"(a,b) == false); // fixed by operand widening
688     assert(b < a); // wrong result
689     assert(compare!"<"(b,a) == false); // fixed by operand widening
690 
691     long aa = -1; ulong bb;
692     assert(aa > bb); // wrong result
693     assert(compare!">"(aa,bb) == true); // not statically fixable
694     assert(bb < aa); // wrong result
695     assert(compare!"<"(bb,aa) == true); // not statically fixable
696 
697     assert(compare!"!="(bb,aa) == true); // test for equality is always transparent OP
698 
699     immutable long aaa = -1; const ulong bbb;
700     assert(compare!">"(aaa,bbb) == true);
701 }
702 
703 /**
704  * Throws a static exception, suitable for @nogc functions.
705  */
706 @nogc @safe
707 void throwStaticEx(T, string file = __FILE__, size_t line = __LINE__)()
708 {
709     static const e = new T(file, line);
710     throw e;
711 }
712 
713 /// ditto
714 @nogc @safe
715 void throwStaticEx(string message, string file = __FILE__, size_t line = __LINE__)()
716 {
717     static const e = new Exception(message, file, line);
718     throw e;
719 }
720 
721 /**
722  * Sets the context and the function of a delegate.
723  *
724  * Params:
725  *      T = The type of the delegate.
726  *      t = The delegate to set.
727  *      context = The context pointer, e.g a pointer to a struct or a class instance.
728  *      code = The pointer to the static function.
729  */
730 void setDelegate(T, FT)(ref T t, void* context, FT code)
731 if (is(T == delegate) && is(FT == typeof(T.funcptr)))
732 {
733     t.ptr = context;
734     t.funcptr = code;
735 }
736 ///
737 unittest
738 {
739     struct Foo
740     {
741         bool fun(){return true;}
742     }
743     Foo foo;
744     bool delegate() atFun;
745     atFun.setDelegate(&foo, &Foo.fun);
746     assert(atFun());
747 }
748 
749 /**
750  * Sets the context and the function of a new delegate.
751  *
752  * Params:
753  *      T = The type of the delegate.
754  *      t = The delegate to set.
755  *      context = The context pointer, e.g a pointer to a struct or a class instance.
756  *      code = The pointer to the static function.
757  *
758  * Returns:
759  *      A new delegate of type T.
760  */
761 auto getDelegate(FT)(void* context, FT code)
762 if (is(PointerTarget!FT == function))
763 {
764     import std.array: replace;
765     enum type = "alias T = " ~ FT.stringof.replace("function", "delegate") ~ ";";
766     mixin(type);
767     T t;
768     t.ptr = context;
769     t.funcptr = code;
770     return t;
771 }
772 ///
773 unittest
774 {
775     struct Foo
776     {
777         bool fun(){return true;}
778     }
779     Foo foo;
780     bool delegate() atFun = getDelegate(&foo, &Foo.fun);
781     assert(atFun());
782 }
783 
784 /**
785  * The delegate union is a conveniant way to setup non gc delegates that
786  * are compatible with D delegates.
787  */
788 union Delegate(FT)
789 if (is(PointerTarget!FT == function))
790 {
791     /// Defines the delegate layout as defined in the D ABI
792     struct DgMembers
793     {
794         void* ptr;
795         FT funcptr;
796     }
797 
798     //// The delegates members;
799     DgMembers members;
800     alias members this;
801 
802     import std.array: replace;
803     enum type = "alias T = " ~ FT.stringof.replace("function", "delegate") ~ ";";
804     mixin(type);
805 
806     /// Allows to use this union as a true D delegate.
807     T dg;
808 
809     /// Helper to call the delegate without accessing `dg`.
810     auto opCall(A...)(A a)
811     {
812         return dg(a);
813     }
814 }
815 ///
816 unittest
817 {
818     struct Foo
819     {
820         bool fun(){return true;}
821     }
822     Foo foo;
823     Delegate!(typeof(&Foo.fun)) atFun;
824     atFun.ptr = &foo,
825     atFun.funcptr = &Foo.fun,
826     assert(atFun());
827 }
828 
829 /**
830  * Safely cast a value of a type to another, if both have the same size.
831  *
832  * Unlike `bruteCast`, the same location si not shared between the
833  * source and the target and no pointer is used.
834  * This function is inspired by http://www.forwardscattering.org/post/27
835  */
836 template bitCast(T, S)
837 if (T.sizeof == S.sizeof
838         && !is(S == T)
839         && !(is(S== float) & (size_t.sizeof == 4))
840         && !is(S == class)     && !is(T == class)
841         && !is(S == interface) && !is(T == interface))
842 {
843     private union BitCaster
844     {
845         S ss;
846         T tt;
847     }
848 
849     static assert(BitCaster.sizeof == S.sizeof);
850 
851     pragma(inline, true)
852     T bitCast(auto ref S s)
853     {
854         BitCaster bt;
855         bt.ss = s;
856         return bt.tt;
857     }
858 }
859 ///
860 @safe pure nothrow unittest
861 {
862     assert(bitCast!int(1.0f) == 0x3f800000);
863     version(LittleEndian)
864         assert(bitCast!(ubyte[2])(ushort(0x1234)) == [0x34, 0x12]);
865     else
866         assert(bitCast!(ubyte[2])(ushort(0x1234)) == [0x12, 0x34]);
867 }
868 
869 /// ditto
870 template bitCast(T, S)
871 if (T.sizeof == S.sizeof && is(S == float)
872         && !is(T == class) && !is(T == interface))
873 {
874     T bitCast(S[1] source...) pure
875     {
876         // S[1]: prevent the source to be loaded in ST(0)
877         // and any normalization to happen.
878         asm @trusted @nogc pure nothrow
879         {
880             naked;
881             ret;
882         }
883     }
884 }
885 
886 /// Deep iteration mode
887 enum IdMode
888 {
889     depth,
890     breadth
891 }
892 
893 /**
894  * Iterates a tree-like structure that exposes an input range interface and calls
895  * each element with a function.
896  *
897  * Params:
898  *      Fun = The function called for each element. When its return type is bool,
899  *          and if it returns true, the iterations are stopped.
900  *      member = The name of the member that gives the real Range.
901  *      mode = The iteration mode (breadth-first or depth-first).
902  *      range = The root element.
903  *      a = The variadic parameters passed to Fun (after the element).
904  * Returns:
905  *      True if the iterations have stopped, false otherwise.
906  */
907 bool deepIterate(alias Fun, string member = "", IdMode mode = IdMode.breadth,
908     Range, A...)(Range range, auto ref A a)
909 {
910     static if (!member.length)
911     {
912         alias Rng = Range;
913         alias M = void;
914     }
915     else
916     {
917         mixin("alias M = typeof(Range." ~ member ~ ");");
918         static assert(__traits(hasMember, Range, member),
919             "invalid Range member, Range has no member named '" ~ member ~ "'");
920     }
921     enum callable = isCallable!M;
922     static if (callable)
923         alias Rng = ReturnType!M;
924     static assert(isInputRange!Rng && is(ElementType!Rng == Range),
925         "invalid deepIterate Range");
926 
927     static if (is(ReturnType!Fun))
928     {
929         alias R = ReturnType!Fun;
930         enum funIsPred = is(R == bool);
931     }
932     else enum funIsPred = false;
933 
934     bool result;
935 
936     enum callWithFront =
937     q{
938         static if (funIsPred)
939             result = Fun(range, a);
940         else
941             Fun(range, a);
942         if (result)
943             return true;
944     };
945 
946     static if (!__traits(hasMember, range, "front"))
947     {
948         import std.range.primitives: front, empty, popFront;
949     }
950 
951     static if (mode == IdMode.breadth)
952         mixin(callWithFront);
953 
954     static if (!member.length)
955         alias items = range;
956     else static if (callable)
957         mixin("auto items = range." ~ member ~ ";");
958     else
959         mixin("alias items = range." ~ member ~ ";");
960 
961     while (!items.empty)
962     {
963         result = deepIterate!(Fun, member, mode, Range, A)(items.front, a);
964         if (result)
965             break;
966         items.popFront();
967     }
968 
969     static if (mode == IdMode.depth)
970         mixin(callWithFront);
971 
972     return result;
973 }
974 ///
975 unittest
976 {
977     // creates a tree
978     Item root = new Item;
979     root.populate;
980     root[0].populate;
981     root[1].populate;
982 
983     int cnt, a;
984 
985     // count the population
986     deepIterate!((e) => ++cnt)(root);
987     assert(cnt == 7);
988 
989     // previous content is consumed
990     root.populate;
991     root[0].populate;
992     root[1].populate;
993 
994     // the delegate result is used to stop the iteration
995     deepIterate!((Item e, ref int p){++p; --cnt; return cnt == 4;})(root, a);
996     assert(cnt == 4);
997     assert(a == 3);
998 }
999 
1000 version(unittest) private class Item
1001 {
1002     alias children this;
1003     Item[] children;
1004     void populate()
1005     {
1006         children.length = 2;
1007         children[0] = new Item;
1008         children[1] = new Item;
1009         assert(children.length == 2);
1010     }
1011 }
1012 
1013 // unittest
1014 // {
1015 //     import iz.containers: ObjectTreeItem;
1016 //     import iz.memory: construct, destruct;
1017 //     ObjectTreeItem root = construct!ObjectTreeItem;
1018 //     ObjectTreeItem c1 = root.addNewChild!ObjectTreeItem;
1019 //     ObjectTreeItem c2 = root.addNewChild!ObjectTreeItem;
1020 //     ObjectTreeItem c1c1 = c1.addNewChild!ObjectTreeItem;
1021 //     ObjectTreeItem c1c2 = c1.addNewChild!ObjectTreeItem;
1022 //     ObjectTreeItem c2c1 = c2.addNewChild!ObjectTreeItem;
1023 //     ObjectTreeItem c2c2 = c2.addNewChild!ObjectTreeItem;
1024 
1025 //     int cnt, a;
1026 //     deepIterate!((e) => ++cnt, "children")(root);
1027 //     assert(cnt == 7);
1028 
1029 //     root.deleteChildren;
1030 //     destruct(root);
1031 // }
1032 
1033 /**
1034  * Allows to call recursively the function being executed.
1035  *
1036  * Params:
1037  *      a = the parameters expected by the function.
1038  * Examples:
1039  *
1040  * ---
1041  * long factorial(long a)
1042  * {
1043  *     if (a <= 1)
1044  *         return a;
1045  *      else
1046  *          return a * recursion(a-1);
1047  * }
1048  * ---
1049  *
1050  * Returns:
1051  *      The same as the function being executed.
1052  */
1053 auto recursion(string Fun = __FUNCTION__ , A...)(auto ref A a)
1054 {
1055     import std.typecons: tuple;
1056     mixin("return " ~ Fun ~ "(" ~ a.stringof ~ "[0..$]);");
1057 }
1058 
1059 /**
1060  * Used the annotate the member functions that wrap other member functions.
1061  * Each instance must specify aither the type, the instance and the name of the
1062  * function that's wrapped or the name of a context-free function.
1063  * Each string must be colon-separated.
1064  */
1065 struct Wrap{string[] targets;}
1066 ///
1067 unittest
1068 {
1069     struct Foo
1070     {
1071         @Wrap(["Type:instance:name", "freeFunction"])
1072         void foo(){}
1073     }
1074 }
1075 
1076 /**
1077  * Scans the method wrapped by the caller.
1078  *
1079  * Params:
1080  *      f = The caller' s name. Autodetected.
1081  *      returns = The variables that get the result of each wrapped function.
1082  *      They must be references.
1083  *
1084  * Returns:
1085  *      A string that has to be mixed in the caller's body.
1086  */
1087 string applyWrap(string f = __FUNCTION__, R...)(ref R returns)
1088 {
1089     static assert(R.length == 0, "returns are not implemented yet");
1090 
1091     import std.array: array;
1092     import std.algorithm.iteration: splitter;
1093     import std.meta: aliasSeqOf;
1094     import std.range: iota;
1095     import std..string: join;
1096     import std.traits: getUDAs, Parameters, ParameterIdentifierTuple,  ReturnType;
1097 
1098     alias attrbs = getUDAs!(mixin(f), Wrap);
1099     alias params = Parameters!(mixin(f));
1100 
1101     string result;
1102 
1103     foreach(i; aliasSeqOf!(iota(0, attrbs.length)))
1104     {
1105         foreach(j; aliasSeqOf!(iota(0, attrbs[i].targets.length)))
1106         {
1107             enum s = splitter(attrbs[i].targets[j], ":").array;
1108 
1109             if (s.length != 3 && s.length != 1)
1110             {
1111                 assert(0, "Invalid Type:instance:method specifier: \n"
1112                     ~ attrbs[i].targets[j]);
1113             }
1114             static if (s.length == 3)
1115             {
1116                 static assert (__traits(hasMember, mixin(s[0]), s[2]), s[0]  ~
1117                     " has no member named " ~ s[2]);
1118                 enum typeDotMethod = s[0] ~ "." ~ s[2];
1119                 enum instanceDotMethod = s[1] ~ "." ~ s[2];
1120                 alias p = Parameters!(mixin(typeDotMethod));
1121                 alias r = ReturnType!(mixin(typeDotMethod));
1122             }
1123             else
1124             {
1125                 alias p = Parameters!(mixin(s[0]));
1126                 alias r = ReturnType!(mixin(s[0]));
1127             }
1128 
1129             static if (!p.length)
1130             {
1131                 static if (s.length == 3)
1132                     result ~= instanceDotMethod ~ ";";
1133                 else
1134                     result ~= s[0] ~ ";";
1135             }
1136             else static if (is(p == params))
1137             {
1138                 static if (s.length == 3)
1139                 {
1140                     alias n = ParameterIdentifierTuple!(mixin(typeDotMethod));
1141                     result ~= instanceDotMethod ~ "(" ~ [n[0..$]].join(", ") ~ ");";
1142                 }
1143                 else
1144                 {
1145                     alias n = ParameterIdentifierTuple!(mixin(s[0]));
1146                     result ~= s[0] ~ "(" ~ [n[0..$]].join(", ") ~ ");";
1147                 }
1148             }
1149             else static assert(0, "incompatible parameters: \n"
1150                 ~ "got     :" ~ p.stringof ~ "\n"
1151                 ~ "expected:" ~ params.stringof);
1152         }
1153     }
1154     return result;
1155 }
1156 ///
1157 version (none) unittest
1158 {
1159     static bool int42, int8, ffree1, ffree2;
1160 
1161     static struct Inner
1162     {
1163         void foo(int p0, int p1){int42 = true; int8 = true;}
1164         void bar() {ffree1 = true;}
1165     }
1166 
1167     static void freeFunc()
1168     {
1169         ffree2 = true;
1170     }
1171 
1172     static struct Composed
1173     {
1174         Inner inner;
1175 
1176         @Wrap(["Inner:inner:foo", "Inner:inner:bar", "freeFunc"])
1177         void foo(int p0, int p1)
1178         {
1179             mixin(applyWrap());
1180         }
1181     }
1182 
1183     static  Composed c;
1184     c.foo(42,8);
1185     assert(int42 & int8 & ffree1 & ffree2);
1186 }