1 // Written in D programming language
2 /**
3 *   Module handles functions and templates that we lazied to factor out to separate module.
4 *
5 *   Function categories:
6 *   <ul>
7 *   <li> JSON de/serialization based on annotations </li>
8 *   <li> Exception handling functions </li>
9 *   <li> Cheat casting functions </li>
10 *   <li> String processing functions (the only one $(B fromStringz))</li>
11 *   <li> Introspecting templates that cannot be found in Phobos </li> 
12 *   <li> Functional styled utilities for optional values and lazy ranges</li> 
13 *   </ul>
14 *
15 *   Copyright: © 2014 DSoftOut
16 *   License: Subject to the terms of the MIT license, as written in the included LICENSE file.
17 *   Authors: Zaramzan <shamyan.roman@gmail.com>, 
18 *            NCrashed <ncrashed@gmail.com>
19 */
20 module util;
21 
22 import std.algorithm;
23 import std.exception;
24 import std.string;
25 import std.conv;
26 import std.container;
27 import std.traits;
28 import std.typecons;
29 import std.typetuple;
30 import std.range;
31 import std.path;
32 import vibe.data.json;
33 
34 enum APPNAME = "pgator";
35 
36 mixin template t_field(T, alias fieldName)
37 {
38 	mixin("private "~T.stringof~" m_"~fieldName~";");
39 	
40 	mixin("private bool f_"~fieldName~";");
41 	
42 	mixin(T.stringof~" "~fieldName~"() @property { return m_"~fieldName~";}");
43 	
44 	mixin("private void "~fieldName~"("~T.stringof~" f) @property { m_"~fieldName~"= f; f_"~fieldName~"=true;}");
45 }
46 
47 //For deserializeFromJson
48 enum required;
49 
50 //For deserializeFromJson
51 enum possible;
52 
53 
54 /**
55 * Deserializes from Json to type T<br>
56 *
57 * Supported only structs yet
58 *
59 * Example:
60 * ----
61 * struct S
62 * {
63 *    @required
64 *	int a; //get value from Json. Throws RequiredFieldException
65 *
66 *    @possible
67 *	int b; //tries to get value from Json
68 *
69 *	int c; //will be ignored
70 * }
71 *
72 * auto s = deserializeFromJson!S(json);
73 * ------
74 *
75 * Authors: Zaramzan <shamyan.roman@gmail.com>
76 */
77 T deserializeFromJson(T)(Json src) if(is(T == struct))
78 {
79 	T ret;
80 		
81 	if (src.type != Json.Type.object)
82 	{
83 		throw new RequiredJsonObject("Required json object");
84 	}
85 	
86 	void processStruct(string mem, bool isMemberOptional, Ret)(out Ret retMem, Json srcMem)
87 	{
88 		static if (is(Ret == Json))
89 		{
90 			retMem = srcMem;
91 		}
92 		else
93 		{
94 			if (srcMem.type == Json.Type.object)
95 			{	
96 				retMem = deserializeFromJson!Ret(srcMem);
97 			}
98 			else
99 			{
100 				// issue #96, is struct has default constructor 
101 				// and marked with @possible and received null
102 				static if(isMemberOptional && __traits(compiles, Ret() ))
103 				{
104 					if(srcMem.type == Json.Type.null_)
105 					{
106 						retMem = Ret();
107 					} else
108 					{
109 						throw new RequiredFieldException(text("Field ", mem, " must be object in json: ", src));
110 					}
111 				} else
112 				{
113 					throw new RequiredFieldException(text("Field ", mem, " must be object in json: ", src)); 
114 				}
115 			}
116 		}
117 	}
118 	
119 	void processArray(string mem, bool isMemberOptional, Ret)(out Ret retMem, Json srcMem)
120 	{
121 		if (srcMem.type == Json.Type.array)
122 		{
123 			alias ElementType!Ret ElemType;
124 			
125 			ElemType[] arr = new ElemType[0];
126 			
127 			foreach(json; srcMem)
128 			{
129 				static if (is(ElemType == struct))
130 				{
131 					arr ~= deserializeFromJson!ElemType(json);
132 				}
133 				else
134 				{
135 				    static if(__traits(compiles, {ElemType t = null;}))
136 				    {
137 				        if(json.type == Json.Type.null_)
138 				        {
139 				            arr ~= null;
140 				            continue;
141 				        }
142 				    } 
143 				    arr ~= json.to!ElemType;
144 				}
145 			}
146 			
147 			retMem = arr;
148 		} 
149 		else
150 		{
151 			// array could be a null for @possible. issue #96
152 			static if(isMemberOptional)
153 			{
154 				if(srcMem.type == Json.Type.null_)
155 				{
156 					retMem = null;
157 				} else
158 				{
159 					throw new RequiredFieldException(text("Field ", mem, " must be array in json: ", src));
160 				}
161 			} else
162 			{
163 				throw new RequiredFieldException(text("Field ", mem, " must be array in json: ", src));
164 			}
165 		}	
166 	}
167 	
168 	foreach(mem; __traits(allMembers, T))
169 	{	
170 		alias getMemberType!(T, mem) MemberType;
171 		enum isMemberRequired = isRequired!(mem, T);
172 		enum isMemberOptional = isOptional!(mem, T);
173 		
174 		enum srcMem = "src."~mem;
175 		enum retMem = "ret."~mem;
176 		
177 		static if (isMemberRequired || isMemberOptional)
178 		{
179 			if (mixin(srcMem).type != Json.Type.undefined)
180 			{
181 				static if(is(MemberType == struct))
182 				{
183 					processStruct!(mem, isMemberOptional)(mixin(retMem), mixin(srcMem));
184 				} 
185 				else static if(isArray!MemberType && !isSomeString!MemberType)
186 				{
187 					processArray!(mem, isMemberOptional)(mixin(retMem), mixin(srcMem));
188 				}
189 				else
190 				{
191 					mixin(retMem) = mixin(srcMem).to!MemberType();
192 				}
193 			}
194 			else static if (isMemberRequired)
195 			{
196 				throw new RequiredFieldException(text("Field ", mem, " required in json: ", src));
197 			}
198 		}
199 		
200 	}
201 	
202 	return ret;
203 }
204 unittest // issue #96
205 {
206 	struct A
207 	{
208 		@possible
209 		ubyte[] a;
210 	}
211 	
212 	auto a = A(null);
213 	assert(deserializeFromJson!A(serializeToJson(a)) == a);
214 	
215 	struct B
216 	{
217 		@possible
218 		A a;
219 	}
220 	
221 	auto b = B(A(null));
222 	assert(deserializeFromJson!B(serializeToJson(b)) == b);
223 }
224 
225 /**
226 * Serializes struct with $(B @required) attributes fields to Json  <br>
227 * 
228 * Example
229 * ------
230 * struct S
231 * {
232 *    @required
233 *	int a = 1; //will be used
234 *
235 *    @possible
236 *	int b = 2; //will be ignored
237 *
238 *	int c; //will be ignored
239 * }
240 *
241 * writeln(serializeRequiredToJson(S())); // { "a":1 }
242 * ------
243 */
244 Json serializeRequiredToJson(T)(T val)
245 {
246 	static assert (is(T == struct), "Need struct type, not "~T.stringof);
247 	
248 	Json ret = Json.emptyObject;
249 	
250 	foreach(mem; __traits(allMembers, T))
251 	{
252 		static if (isRequired!(mem, T))
253 		{
254 			alias getMemberType!(T, mem) MemType;
255 			
256 			alias vibe.data.json.serializeToJson vibeSer;
257 			
258 			static if (is(MemType == struct))
259 			{
260 				ret[mem] = serializeRequiredToJson!MemType(mixin("val."~mem));
261 			}
262 			else static if (isArray!MemType)
263 			{
264 				alias ElementType!MemType EType;
265 				static if (is(EType == struct))
266 				{
267 					auto j1 = Json.emptyArray;
268 				
269 					foreach(elem; mixin("val."~mem))
270 					{
271 						j1 ~= serializeRequiredToJson(elem);
272 					}
273 					
274 					ret[mem] = j1;
275 				}
276 				else
277 				{
278 					ret[mem] = vibeSer(mixin("val."~mem));
279 				}
280 			}
281 			else
282 			{
283 				ret[mem] = vibeSer(mixin("val."~mem));
284 			}
285 		}
286 	}
287 	
288 	return ret;
289 }
290 
291 private bool isRequired(alias mem, T)()
292 {
293 	foreach(attr;__traits(getAttributes, mixin("T."~mem)))
294 	{
295 		static if (is(attr == required))
296 		{
297 			return true;
298 		}
299 	}
300 	
301 	return false;
302 }
303 
304 private bool isOptional(alias mem, T)()
305 {
306 	foreach(attr;__traits(getAttributes, mixin("T."~mem)))
307 	{
308 		static if (is(attr == possible))
309 		{
310 			return true;
311 		}
312 	}
313 	
314 	return false;
315 }
316 
317 class RequiredFieldException:Exception
318 {
319 	this(in string msg)
320 	{
321 		super(msg);
322 	}
323 }
324 
325 class RequiredJsonObject:Exception
326 {
327 	this(in string msg)
328 	{
329 		super(msg);
330 	}
331 }
332 
333 /**
334 * Tries to call function. On exception throws Ex, otherwise return func() result
335 *
336 * Authors: Zaramzan <shamyan.roman@gmail.com>
337 */
338 template tryEx(Ex, alias func)
339 {
340 	static assert(isSomeFunction!func, "func must be some function");
341 	static assert(is(Ex:Exception), "Ex must be Exception");
342 	
343 	auto wrapper(TP...)(TP params)
344 	{	
345 		try
346 		{
347 			return func(params);
348 		}
349 		catch(Exception ex)
350 		{
351 			throw new Ex(ex.msg, ex.file, ex.line);
352 		}
353 	}
354 
355 	alias wrapper tryEx;
356 }
357 
358 /**
359 * Tries to evaluate par. On exception throws Ex, otherwise return par
360 *
361 * Authors: Zaramzan <shamyan.roman@gmail.com>
362 */
363 T tryEx(Ex, T)(lazy T par)
364 {
365 	static assert(is(Ex:Exception), "Ex must be Exception");
366 	
367 	try
368 	{
369 		return par;
370 	}
371 	catch(Exception ex)
372 	{
373 		throw new Ex(ex.msg, ex.file, ex.line);
374 	}
375 }
376 
377 /**
378 * cast to shared type T
379 *
380 * Warning:
381 *	Don't use this, if you want send object to another thread. It just dirty hack.
382 */
383 template toShared(T)
384 {
385 	private alias Unqual!T P;
386 	
387 	shared(P) toShared(T par)
388 	{
389 		return cast(shared P) cast(P) par;
390 	}
391 }
392 
393 /// cast to unqual type T
394 template toUnqual(T)
395 {
396 	private alias Unqual!T P;
397 	
398 	P toUnqual(T par)
399 	{
400 		return cast(P) par;
401 	}
402 }
403 
404 version(unittest)
405 {
406 	bool thrower()
407 	{
408 		throw new Exception("Exception");
409 	}
410 	
411 	class TestException: Exception
412 	{
413 		@safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
414 		{
415 			super(msg, file, line, next); 
416 		}
417 	}
418 }
419 
420 unittest
421 {
422 	import std.exception;
423 	
424 	assertThrown!TestException(tryEx!TestException(thrower()));
425 }
426 
427 static if (__VERSION__ < 2066) { // from phobos 2.066-b1
428 	import std.c.string;
429 	
430 	/++
431 	    Returns a D-style array of $(D char) given a zero-terminated C-style string.
432 	    The returned array will retain the same type qualifiers as the input.
433 	
434 	    $(RED Important Note:) The returned array is a slice of the original buffer.
435 	    The original data is not changed and not copied.
436 	+/
437 	
438 	inout(char)[] fromStringz(inout(char)* cString) @system pure {
439 	    return cString ? cString[0 .. strlen(cString)] : null;
440 	}
441 	
442 	///
443 	@system pure unittest
444 	{
445 	    assert(fromStringz(null) == null);
446 	    assert(fromStringz("foo") == "foo");
447 	}
448 } else {
449 	public import std.string: fromStringz;
450 }
451 
452 /// getMemberType
453 /**
454 *   Retrieves member type with $(D name) of class $(D Class). If member is agregate 
455 *   type declaration or simply doesn't exist, retrieves no type. You can check it with
456 *   $(D is) operator.
457 *
458 *   Example:
459 *   -----------
460 *   class A 
461 *   {
462 *       int aField;
463 *       string b;
464 *       bool c;
465 *       
466 *       class B {}
467 *       struct C {}
468 *       union D {}
469 *       interface E {}
470 *   }
471 *
472 *   static assert(is(getMemberType!(A, "aField") == int));
473 *   static assert(is(getMemberType!(A, "b") == string));
474 *   static assert(is(getMemberType!(A, "c") == bool));
475 *
476 *   static assert(!is(getMemberType!(A, "B")));
477 *   static assert(!is(getMemberType!(A, "C")));
478 *   static assert(!is(getMemberType!(A, "D")));
479 *   static assert(!is(getMemberType!(A, "E")));
480 *   -----------
481 */
482 template getMemberType(Class, string name)
483 {
484     static if(hasMember!(Class, name))
485         alias typeof(__traits(getMember, Class, name)) getMemberType;
486 }
487 
488 unittest
489 {
490     class A 
491     {
492         int a;
493         string b;
494         bool c;
495 
496         class B {}
497         struct C {}
498         union D {}
499         interface E {}
500     }
501 
502     static assert(is(getMemberType!(A, "a") == int));
503     static assert(is(getMemberType!(A, "b") == string));
504     static assert(is(getMemberType!(A, "c") == bool));
505 
506     static assert(!is(getMemberType!(A, "B")));
507     static assert(!is(getMemberType!(A, "C")));
508     static assert(!is(getMemberType!(A, "D")));
509     static assert(!is(getMemberType!(A, "E")));
510 }
511 
512 /// FieldNameTuple
513 /**
514 *   Retrieves names of all class/struct/union $(D Class) fields excluding technical ones like this, Monitor.
515 *
516 *   Example:
517 *   ---------
518 *   class A 
519 *   {
520 *       int aField;
521 *
522 *       void func1() {}
523 *       static void func2() {}
524 *
525 *       string b;
526 *
527 *       final func3() {}
528 *       abstract void func4();
529 *
530 *       bool c;
531 *   }
532 *
533 *   static assert(FieldNameTuple!A == ["aField","b","c"]);
534 *   ---------
535 */
536 template FieldNameTuple(Class)
537 {
538     template removeFuncs(funcs...)
539     {
540         static if(funcs.length > 0)
541         {
542             // if member is class/struct/interface declaration second part getMemberType returns no type
543             static if( is(getMemberType!(Class, funcs[0]) == function) ||
544                 !is(getMemberType!(Class, funcs[0])) ||
545                 funcs[0] == "this" || funcs[0] == "Monitor" || funcs[0] == "__ctor" ||
546                 funcs[0] == "opEquals" || funcs[0] == "opCmp" || funcs[0] == "opAssign")
547             {
548                 enum removeFuncs = removeFuncs!(funcs[1..$]);
549             }
550             else
551                 enum removeFuncs = [funcs[0]]~removeFuncs!(funcs[1..$]);
552         }
553         else
554             enum removeFuncs = [];
555     }
556 
557     enum temp = removeFuncs!(__traits(allMembers, Class));
558     static if(temp.length > 0)
559         enum FieldNameTuple = temp[0..$-1];
560     else
561         enum FieldNameTuple = [];
562 }
563 
564 // ddoc example
565 unittest
566 {
567     class A 
568     {
569         int a;
570 
571         void func1() {}
572         static void func2() {}
573 
574         string b;
575 
576         final func3() {}
577         abstract void func4();
578 
579         bool c;
580     }
581 
582     static assert(FieldNameTuple!A == ["a","b","c"]);
583 }
584 unittest
585 {
586     class P 
587     {
588         void foo() {}
589 
590         real p;
591     }
592 
593     class A : P
594     {
595         int aField;
596 
597         void func1() {}
598         static void func2() {}
599 
600         string b;
601 
602         final void func3() {}
603         abstract void func4();
604 
605         bool c;
606 
607         void function(int,int) da;
608         void delegate(int, int) db;
609 
610         class B {} 
611         B mB;
612 
613         struct C {}
614         C mC;
615 
616         interface D {}
617     }
618 
619     static assert(FieldNameTuple!A == ["aField","b","c","da","db","mB","mC","p"]);
620     static assert(is(getMemberType!(A, "aField") == int));
621     static assert(is(getMemberType!(A, "b") == string));
622     static assert(is(getMemberType!(A, "c") == bool));
623 
624     struct S1
625     {
626         int a;
627         bool b;
628 
629         void foo() {}
630 
631         real c;
632     }
633 
634     static assert(FieldNameTuple!S1 == ["a","b","c"]);
635 
636     union S2
637     {
638         size_t index;
639         void*   pointer;
640     }
641 
642     static assert(FieldNameTuple!S2 == ["index", "pointer"]);
643 
644     class S3
645     {
646 
647     }
648     static assert(FieldNameTuple!S3 == []);
649 
650     // Properties detected as field. To fix.
651     struct S4
652     {
653         @property S4 dup()
654         {
655             return S4();
656         }
657     }
658     static assert(FieldNameTuple!S4 == ["dup"]);
659 }
660 
661 /// Removes one element from the list
662 /**
663 *   NEVER use while iterating the $(B list).
664 */
665 void removeOne(T)(ref DList!T list, T elem)
666 {
667    auto toRemove = list[].find(elem).take(1);
668    list.linearRemove(toRemove);
669 }
670 
671 /**
672 *   Struct-wrapper to handle result of computations,
673 *   that can fail.
674 *
675 *   Example:
676 *   ---------
677 *   class A {}
678 *   
679 *   auto a = new A();
680 *   auto ma = Maybe!A(a);
681 *   auto mb = Maybe!A(null);
682 *   
683 *   assert(!ma.isNothing);
684 *   assert(mb.isNothing);
685 *   
686 *   assert(ma.get == a);
687 *   assertThrown!Error(mb.get);
688 *   
689 *   bool ncase = false, jcase = false;
690 *   ma.map(() {ncase = true;}, (v) {jcase = true;});
691 *   assert(jcase && !ncase);
692 *   
693 *   ncase = jcase = false;
694 *   mb.map(() {ncase = true;}, (v) {jcase = true;});
695 *   assert(!jcase && ncase);
696 *   ---------
697 */
698 struct Maybe(T)
699     if(is(T == class) || is(T == interface) 
700         || isPointer!T || isArray!T) 
701 {
702     private T value;
703     
704     /// Alias to stored type
705     alias T StoredType;
706     
707     /**
708     *   Constructing Maybe from $(B value).
709     *   If pointer is $(B null) methods: $(B isNothing) returns true and 
710     *   $(B get) throws Error.
711     */
712     this(T value) pure
713     {
714         this.value = value;
715     }
716     
717     /**
718     *   Constructing empty Maybe.
719     *   If Maybe is created with the method, it is considred empty
720     *   and $(B isNothing) returns false.
721     */
722     static Maybe!T nothing()
723     {
724         return Maybe!T(null);
725     } 
726     
727     /// Returns true if stored value is null
728     bool isNothing() const
729     {
730         return value is null;
731     }
732     
733     /**
734     *   Unwrap value from Maybe.
735     *   If stored value is $(B null), Error is thrown.
736     */
737     T get()
738     {
739         assert(value !is null, "Stored reference is null!");
740         return value;
741     }
742     
743     /**
744     *   Unwrap value from Maybe.
745     *   If stored value is $(B null), Error is thrown.
746     */
747     const(T) get() const
748     {
749         assert(value !is null, "Stored reference is null!");
750         return value;
751     }
752     
753     /**
754     *   If struct holds $(B null), then $(B nothingCase) result
755     *   is returned. If struct holds not $(B null) value, then
756     *   $(justCase) result is returned. $(B justCase) is fed
757     *   with unwrapped value.
758     */
759     U map(U)(U delegate() nothingCase, U delegate(T) justCase)
760     {
761         return isNothing ? nothingCase() : justCase(value);
762     }
763     
764     /**
765     *   If struct holds $(B null), then $(B nothingCase) result
766     *   is returned. If struct holds not $(B null) value, then
767     *   $(justCase) result is returned. $(B justCase) is fed
768     *   with unwrapped value.
769     */
770     U map(U)(U delegate() nothingCase, U delegate(const T) justCase) const
771     {
772         return isNothing ? nothingCase() : justCase(value);
773     }
774 }
775 
776 unittest
777 {
778     class A {}
779     
780     auto a = new A();
781     auto ma = Maybe!A(a);
782     auto mb = Maybe!A(null);
783     
784     assert(!ma.isNothing);
785     assert(mb.isNothing);
786     
787     assert(ma.get == a);
788     assertThrown!Error(mb.get);
789     
790     bool ncase = false, jcase = false;
791     ma.map(() {ncase = true;}, (v) {jcase = true;});
792     assert(jcase && !ncase);
793     
794     ncase = jcase = false;
795     mb.map(() {ncase = true;}, (v) {jcase = true;});
796     assert(!jcase && ncase);
797 }
798 
799 /**
800 *   Struct-wrapper to handle result of computations,
801 *   that can fail.
802 *
803 *   Example:
804 *   ---------
805 *   struct A {}
806 *   
807 *   auto ma = Maybe!A(A());
808 *   auto mb = Maybe!A.nothing;
809 *   
810 *   assert(!ma.isNothing);
811 *   assert(mb.isNothing);
812 *   
813 *   assert(ma.get == A());
814 *   assertThrown!Error(mb.get);
815 *   
816 *   bool ncase = false, jcase = false;
817 *   ma.map(() {ncase = true;}, (v) {jcase = true;});
818 *   assert(jcase && !ncase);
819 *   
820 *   ncase = jcase = false;
821 *   mb.map(() {ncase = true;}, (v) {jcase = true;});
822 *   assert(!jcase && ncase);
823 *   ---------
824 */
825 struct Maybe(T)
826     if(is(T == struct) || isAssociativeArray!T || isBasicType!T) 
827 {
828     private bool empty;
829     private T value;
830     
831     /// Alias to stored type
832     alias T StoredType;
833     
834     /**
835     *   Constructing empty Maybe.
836     *   If Maybe is created with the method, it is considred empty
837     *   and $(B isNothing) returns false.
838     */
839     static Maybe!T nothing()
840     {
841         Maybe!T ret;
842         ret.empty = true;
843         return ret;
844     } 
845     
846     /**
847     *   Constructing Maybe from $(B value).
848     *   If Maybe is created with the constructor, it is considered non empty
849     *   and $(B isNothing) returns false.
850     */
851     this(T value) pure
852     {
853         this.value = value;
854         empty = false;
855     }
856     
857     /// Returns true if stored value is null
858     bool isNothing() const
859     {
860         return empty;
861     }
862     
863     /**
864     *   Unwrap value from Maybe.
865     *   If the Maybe is empty, Error is thrown.
866     */
867     T get()
868     {
869         assert(!empty, "Stored value is null!");
870         return value;
871     }
872     
873     /**
874     *   Unwrap value from Maybe.
875     *   If the Maybe is empty, Error is thrown.
876     */
877     const(T) get() const
878     {
879         assert(!empty, "Stored value is null!");
880         return value;
881     }
882     
883     /**
884     *   If struct holds $(B null), then $(B nothingCase) result
885     *   is returned. If struct holds not $(B null) value, then
886     *   $(justCase) result is returned. $(B justCase) is fed
887     *   with unwrapped value.
888     */
889     U map(U)(U delegate() nothingCase, U delegate(T) justCase)
890     {
891         return isNothing ? nothingCase() : justCase(value);
892     }
893     
894     /**
895     *   If struct holds $(B null), then $(B nothingCase) result
896     *   is returned. If struct holds not $(B null) value, then
897     *   $(justCase) result is returned. $(B justCase) is fed
898     *   with unwrapped value.
899     */
900     U map(U)(U delegate() nothingCase, U delegate(const T) justCase) const
901     {
902         return isNothing ? nothingCase() : justCase(value);
903     }
904 }
905 
906 unittest
907 {
908     struct A {}
909     
910     auto ma = Maybe!A(A());
911     auto mb = Maybe!A.nothing;
912     
913     assert(!ma.isNothing);
914     assert(mb.isNothing);
915     
916     assert(ma.get == A());
917     assertThrown!Error(mb.get);
918     
919     bool ncase = false, jcase = false;
920     ma.map(() {ncase = true;}, (v) {jcase = true;});
921     assert(jcase && !ncase);
922     
923     ncase = jcase = false;
924     mb.map(() {ncase = true;}, (v) {jcase = true;});
925     assert(!jcase && ncase);
926 }
927 
928 /**
929 *   Transforms delegate into lazy range. Generation is stopped, when
930 *   $(B genfunc) returns $(B Maybe!T.nothing).
931 *
932 *   Example:
933 *   --------
934 *   assert( (() => Maybe!int(1)).generator.take(10).equal(1.repeat.take(10)) );
935 *   assert( (() => Maybe!int.nothing).generator.empty);
936 *   assert( (() 
937 *           {
938 *               static size_t i = 0;
939 *               return i++ < 10 ? Maybe!int(1) : Maybe!int.nothing;
940 *           }
941 *           ).generator.equal(1.repeat.take(10)));
942 *   
943 *   class A {}
944 *   auto a = new A();
945 *   
946 *   assert( (() => Maybe!A(a)).generator.take(10).equal(a.repeat.take(10)) );
947 *   assert( (() => Maybe!A.nothing).generator.empty);
948 *   assert( (() 
949 *           {
950 *               static size_t i = 0;
951 *               return i++ < 10 ? Maybe!A(a) : Maybe!A.nothing;
952 *           }
953 *           ).generator.equal(a.repeat.take(10)));
954 *   --------
955 */
956 auto generator(T)(Maybe!T delegate() genfunc)
957 {
958     struct Sequencer
959     {
960         private Maybe!T currvalue;
961         
962         T front()
963         {
964             assert(!currvalue.isNothing, "Generator range is empty!");
965             return currvalue.get;
966         }
967         
968         bool empty()
969         {
970             return currvalue.isNothing;
971         }
972         
973         void popFront()
974         {
975             currvalue = genfunc();
976         }
977     }
978     static assert(isInputRange!Sequencer);
979     
980     auto s = Sequencer();
981     s.popFront;
982     return s;
983 }
984 unittest
985 {
986     assert( (() => Maybe!int(1)).generator.take(10).equal(1.repeat.take(10)) );
987     assert( (() => Maybe!int.nothing).generator.empty);
988     assert( (() 
989             {
990                 static size_t i = 0;
991                 return i++ < 10 ? Maybe!int(1) : Maybe!int.nothing;
992             }
993             ).generator.equal(1.repeat.take(10)));
994     
995     class A {}
996     auto a = new A();
997     
998     assert( (() => Maybe!A(a)).generator.take(10).equal(a.repeat.take(10)) );
999     assert( (() => Maybe!A.nothing).generator.empty);
1000     assert( (() 
1001             {
1002                 static size_t i = 0;
1003                 return i++ < 10 ? Maybe!A(a) : Maybe!A.nothing;
1004             }
1005             ).generator.equal(a.repeat.take(10)));
1006 }
1007 
1008 private template TypesOf(T...)
1009 {
1010     static if(T.length == 1)
1011         alias TypesOf = typeof(T[0]);
1012     else
1013         alias TypesOf = TypeTuple!(typeof(T[0]), TypesOf!(T[1..$]));
1014 }
1015 
1016 /**
1017 *   Allows to fast retreiving results from functions that returns a tuple.
1018 */
1019 @property void tie(T...)(Tuple!(TypesOf!T) t)
1020 {
1021     foreach(i, ref var; T)
1022     {
1023         T[i] = t[i];
1024     }
1025 }
1026 /// Example
1027 unittest
1028 {
1029     Tuple!(int, string) foo()
1030     {
1031         return tuple(1, "a");
1032     }
1033     
1034     int x;
1035     string y;
1036     
1037     tie!(x,y) = foo();
1038     assert(x == 1 && y == "a");
1039 }