Advertisement
Guest User

Untitled

a guest
Feb 15th, 2013
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. This module is based on code in the std.typecons module in the standard library of the D programming language. The authors of std.typecons deserve credit and thanks, and are listed at the top of the source code for the module, which is available here:
  3.  
  4. https://github.com/D-Programming-Language/phobos/blob/master/std/typecons.d
  5.  
  6. Copyright (c) 2013, w0rp <moebiuspersona@gmail.com>
  7. All rights reserved.
  8.  
  9. Redistribution and use in source and binary forms, with or without
  10. modification, are permitted provided that the following conditions are met:
  11.  
  12. 1. Redistributions of source code must retain the above copyright notice, this
  13.    list of conditions and the following disclaimer.
  14. 2. Redistributions in binary form must reproduce the above copyright notice,
  15.    this list of conditions and the following disclaimer in the documentation
  16.    and/or other materials provided with the distribution.
  17.  
  18. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  22. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29.  
  30. module option;
  31.  
  32. import std.exception;
  33. import std.typecons;
  34. import std.stdio;
  35.  
  36. struct Option(T) if(is(T == class)) {
  37.     private T _value;
  38.  
  39.     this(T value) {
  40.         _value = value;
  41.     }
  42.  
  43.     this(Nullable!T value) {
  44.         if (!value.isNull)
  45.         {
  46.             _value = value;
  47.         }
  48.     }
  49.  
  50.     @property @safe const pure nothrow
  51.     bool isNull() {
  52.         return _value is null;
  53.     }
  54.  
  55.     @safe pure nothrow
  56.     void opAssign(T value) {
  57.         _value = value;
  58.     }
  59.  
  60.     @safe pure
  61.     void opAssign(Nullable!T value) {
  62.         if (!value.isNull)
  63.         {
  64.             _value = value;
  65.         }
  66.     }
  67.  
  68.     @safe pure nothrow nullify() {
  69.         _value = null;
  70.     }
  71.  
  72.     @property @safe pure nothrow inout(T) get() inout {
  73.         enum message = "Called `get' on null Option!" ~ T.stringof ~ ".";
  74.         assert(_value !is null, message);
  75.         return _value;
  76.     }
  77.  
  78.     alias get this;
  79. }
  80.  
  81. struct Option(T) if(!is(T == class)) {
  82.     private T _value;
  83.     private bool _isNull = true;
  84.  
  85.     this(T value) {
  86.         _value = value;
  87.         _isNull = false;
  88.     }
  89.  
  90.     // The defaults work here.
  91.     this(typeof(null) value) {}
  92.  
  93.     this(Nullable!T value) {
  94.         if (!value.isNull) {
  95.             _value = value;
  96.             _isNull = false;
  97.         }
  98.     }
  99.  
  100.     @property @safe const pure nothrow
  101.     bool isNull() {
  102.         return _isNull;
  103.     }
  104.  
  105.     @safe pure nothrow
  106.     void opAssign(T value) {
  107.         _value = value;
  108.         _isNull = false;
  109.     }
  110.  
  111.     @safe pure nothrow
  112.     void opAssign(typeof(null) value) {
  113.         nullify();
  114.     }
  115.  
  116.     @safe pure
  117.     void opAssign(Nullable!T value) {
  118.         if (!value.isNull) {
  119.             _value = value;
  120.             _isNull = false;
  121.         }
  122.     }
  123.  
  124.     @safe pure nothrow nullify() {
  125.         _value = T.init;
  126.         _isNull = true;
  127.     }
  128.  
  129.     @property @safe pure nothrow
  130.     inout(T) get() inout {
  131.         enum message = "Called `get' on null Option!" ~ T.stringof ~ ".";
  132.         assert(!_isNull, message);
  133.         return _value;
  134.     }
  135.  
  136.     alias get this;
  137. }
  138.  
  139. // Test that Option works for classes.
  140. unittest {
  141.     class MyClass { }
  142.  
  143.     Option!MyClass test = null;
  144.     assert(test.isNull);
  145.     assertThrown!Throwable(test.get);
  146. }
  147.  
  148. unittest {
  149.     class MyClass { }
  150.  
  151.     Option!MyClass test = new MyClass();
  152.     test = null;
  153.  
  154.     assert(test.isNull);
  155.     assertThrown!Throwable(test.get);
  156. }
  157.  
  158. unittest {
  159.     class MyClass { }
  160.  
  161.     Option!MyClass test = new MyClass();
  162.     assert(!test.isNull);
  163.     assertNotThrown!Throwable(test.get);
  164. }
  165.  
  166. unittest {
  167.     class MyClass { }
  168.  
  169.     Option!MyClass test;
  170.     test = new MyClass();
  171.     assert(!test.isNull);
  172.     assertNotThrown!Throwable(test.get);
  173. }
  174.  
  175. // Test that option works for primitives.
  176. unittest {
  177.     Option!int test;
  178.     assert(test.isNull);
  179.     assertThrown!Throwable(test.get);
  180. }
  181.  
  182. unittest {
  183.     Option!int test = 3;
  184.     test.nullify();
  185.     assert(test.isNull);
  186.     assertThrown!Throwable(test.get);
  187. }
  188.  
  189. unittest {
  190.     Option!int test = 4;
  191.     assert(!test.isNull);
  192.     assertNotThrown!Throwable(test.get);
  193. }
  194.  
  195. unittest {
  196.     Option!int test;
  197.     test = 4;
  198.     assert(!test.isNull);
  199.     assertNotThrown!Throwable(test.get);
  200. }
  201.  
  202. // Test the hook for assigning null to primitives.
  203.  
  204. unittest {
  205.     Option!int test = null;
  206. }
  207.  
  208. unittest {
  209.     Option!int test;
  210.     test = null;
  211. }
  212.  
  213. // Test that option supports Nullable for classes.
  214. unittest {
  215.     class MyClass { }
  216.  
  217.     Nullable!MyClass nullableInstance;
  218.     Option!MyClass optInstance = nullableInstance;
  219.  
  220.     assert(optInstance.isNull);
  221.     assertThrown!Throwable(optInstance.get);
  222. }
  223.  
  224. unittest {
  225.     class MyClass { }
  226.  
  227.     MyClass instance = new MyClass();
  228.  
  229.     Nullable!MyClass nullableInstance = instance;
  230.     Option!MyClass optInstance = nullableInstance;
  231.  
  232.     assert(!optInstance.isNull);
  233.     assertNotThrown!Throwable(optInstance.get);
  234.     assert(optInstance == instance);
  235. }
  236.  
  237. // Test that option supports Nullable for primitives.
  238. unittest {
  239.     Nullable!int nullableInt;
  240.     Option!int optInt = nullableInt;
  241.  
  242.     assert(optInt.isNull);
  243.     assertThrown!Throwable(optInt.get);
  244. }
  245.  
  246. unittest {
  247.     Nullable!int nullableInt = 3;
  248.     Option!int optInt = nullableInt;
  249.  
  250.     assert(!optInt.isNull);
  251.     assertNotThrown!Throwable(optInt.get);
  252.     assert(optInt == 3);
  253. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement