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