Created
April 24, 2019 12:29
-
-
Save rikkimax/9deba78f68d5b8becac104fec5f72321 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import wg.util.allocator; | |
import std.traits : isPointer, isBasicType; | |
struct Optional(T) if (isBasicType!T || is(T == struct) || is(T == union)) { | |
@disable this(this); | |
this(Allocator* allocator) { | |
this.allocator = allocator; | |
} | |
~this() { | |
if (!this.isNull) { | |
this._value.destroy(); | |
this.allocator.deallocate((cast(void*)_value)[0 .. T.sizeof]); | |
} | |
} | |
bool isNull() { | |
return _value is null; | |
} | |
scope ref T get() { | |
if (this.isNull) { | |
_value = cast(T*)allocator.allocate(T.sizeof); | |
*_value = T.init; | |
static if (__traits(compiles, {auto v = new T(new Allocator);})) { | |
_value.__ctor(this.allocator()); | |
} else static if (__traits(hasMember, T, "__ctor")) { | |
_value.__ctor(); | |
} | |
} | |
return *_value; | |
} | |
alias get this; | |
static if (__traits(compiles, { T value1, value2; value2 = value1; })) { | |
void opAssign(T value) { | |
this.get() = value; | |
} | |
} | |
private { | |
Allocator* allocator; | |
T* _value; | |
} | |
} | |
struct Optional(T) if (isPointer!T || is(T == class)) { | |
@disable this(this); | |
this(Allocator* allocator) { | |
this.allocator = allocator; | |
} | |
~this() { | |
if (!this.isNull) { | |
this._value.destroy(); | |
static if (is(T == class)) { | |
this.allocator.deallocate((cast(void*)_value)[0 .. __traits(classInstanceSize, T)]); | |
} else { | |
this.allocator.deallocate((cast(void*)_value)[0 .. T.sizeof]); | |
} | |
} | |
} | |
bool isNull() { | |
return _value is null; | |
} | |
scope ref auto get() { | |
if (this.isNull) { | |
_value = cast(T)allocator.allocate(this.Size).ptr; | |
static if (is(T == class)) { | |
import std.conv : emplace; | |
static if (__traits(compiles, {auto v = new T(new Allocator);})) { | |
emplace(_value, this.allocator); | |
} else { | |
emplace(_value); | |
} | |
} else { | |
*_value = U.init; | |
} | |
} | |
static if (is(T == class)) { | |
return _value; | |
} else { | |
return *_value; | |
} | |
} | |
alias get this; | |
static if (is(T == class)) { | |
@disable void opAssign(T); | |
} else { | |
void opAssign(U value) { | |
this.get() = value; | |
} | |
} | |
private { | |
static if (is(T == class)) { | |
enum Size = __traits(classInstanceSize, T); | |
} else { | |
alias U = typeof(*T.init); | |
enum Size = U.sizeof; | |
} | |
Allocator* allocator; | |
T _value; | |
} | |
} | |
struct Optional(T:const(U)[], U) if (__traits(compiles, { U value1, value2; value2 = value1; })) { | |
@disable this(this); | |
this(Allocator* allocator) { | |
this.allocator = allocator; | |
} | |
~this() { | |
if (!isNull) { | |
void[] temp = cast(void[])_value; | |
_value.destroy(); | |
this.allocator.deallocate(temp); | |
} | |
} | |
bool isNull() { | |
return _value.ptr is null || _value.length == 0; | |
} | |
scope T get() { | |
return _value; | |
} | |
alias get this; | |
void opAssign(T value) { | |
this._value = cast(T)((cast(U*)allocator.allocate(U.sizeof * value.length))[0 .. value.length]); | |
(cast(U[])this._value)[] = value[]; | |
} | |
private { | |
Allocator* allocator; | |
T _value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment