MutableDStringN

Stack-allocated mutable dstring of maximum length of capacity.

@safe pure
alias MutableDStringN(uint capacity, bool borrowChecked = false) = FixedArray!(char, capacity, borrowChecked)

Examples

construct from array may throw

enum capacity = 3;
alias T = int;
alias A = FixedArray!(T, capacity);
static assert(!mustAddGCRange!A);

auto a = A([1, 2, 3].s[]);
assert(a[] == [1, 2, 3].s);

unsafe construct from array

enum capacity = 3;
alias T = int;
alias A = FixedArray!(T, capacity);
static assert(!mustAddGCRange!A);

auto a = A.fromValuesUnsafe([1, 2, 3].s);
assert(a[] == [1, 2, 3].s);

construct from scalars is nothrow

enum capacity = 3;
alias T = int;
alias A = FixedArray!(T, capacity);
static assert(!mustAddGCRange!A);

auto a = A(1, 2, 3);
assert(a[] == [1, 2, 3].s);

static assert(!__traits(compiles, { auto _ = A(1, 2, 3, 4); }));

scope checked string

enum capacity = 15;
foreach (StrN; AliasSeq!(StringN// , WStringN, DStringN
             ))
{
    alias String15 = StrN!(capacity);

    typeof(String15.init[0])[] xs;
    assert(xs.length == 0);
    auto x = String15("alphas");

    assert(x[0] == 'a');
    assert(x[$ - 1] == 's');

    assert(x[0 .. 2] == "al");
    assert(x[] == "alphas");

    const y = String15("åäö_åäöå"); // fits in 15 chars
    assert(y.length == capacity);
}

scope checked string

enum capacity = 15;
foreach (Str; AliasSeq!(StringN!capacity,
                        WStringN!capacity,
                        DStringN!capacity))
{
    static assert(!mustAddGCRange!Str);
    static if (isDIP1000)
    {
        static assert(!__traits(compiles, {
                    auto f() @safe pure
                    {
                        auto x = Str("alphas");
                        auto y = x[];
                        return y;   // errors with -dip1000
                    }
                }));
    }
}
1 import std.exception : assertNotThrown;
2 
3 alias T = char;
4 enum capacity = 3;
5 
6 alias A = FixedArray!(T, capacity, true);
7 static assert(!mustAddGCRange!A);
8 static assert(A.sizeof == T.sizeof*capacity + 1);
9 
10 import std.range.primitives : isOutputRange;
11 static assert(isOutputRange!(A, T));
12 
13 auto ab = A("ab");
14 assert(!ab.empty);
15 assert(ab[0] == 'a');
16 assert(ab.front == 'a');
17 assert(ab.back == 'b');
18 assert(ab.length == 2);
19 assert(ab[] == "ab");
20 assert(ab[0 .. 1] == "a");
21 assertNotThrown(ab.insertBack('_'));
22 assert(ab[] == "ab_");
23 ab.popBack();
24 assert(ab[] == "ab");
25 assert(ab.toString == "ab");
26 
27 ab.popBackN(2);
28 assert(ab.empty);
29 assertNotThrown(ab.insertBack('a', 'b'));
30 
31 const abc = A("abc");
32 assert(!abc.empty);
33 assert(abc.front == 'a');
34 assert(abc.back == 'c');
35 assert(abc.length == 3);
36 assert(abc[] == "abc");
37 assert(ab[0 .. 2] == "ab");
38 assert(abc.full);
39 static assert(!__traits(compiles, { const abcd = A('a', 'b', 'c', 'd'); })); // too many elements
40 
41 assert(ab[] == "ab");
42 ab.popFront();
43 assert(ab[] == "b");
44 
45 const xy = A("xy");
46 assert(!xy.empty);
47 assert(xy[0] == 'x');
48 assert(xy.front == 'x');
49 assert(xy.back == 'y');
50 assert(xy.length == 2);
51 assert(xy[] == "xy");
52 assert(xy[0 .. 1] == "x");
53 
54 const xyz = A("xyz");
55 assert(!xyz.empty);
56 assert(xyz.front == 'x');
57 assert(xyz.back == 'z');
58 assert(xyz.length == 3);
59 assert(xyz[] == "xyz");
60 assert(xyz.full);
61 static assert(!__traits(compiles, { const xyzw = A('x', 'y', 'z', 'w'); })); // too many elements
static void testAsSomeString(T)()
{
    enum capacity = 15;
    alias A = FixedArray!(immutable(T), capacity);
    static assert(!mustAddGCRange!A);
    auto a = A("abc");
    assert(a[] == "abc");

    import std.conv : to;
    const x = "a".to!(T[]);
}

foreach (T; AliasSeq!(char// , wchar, dchar
             ))
{
    testAsSomeString!T();
}

equality

enum capacity = 15;
alias S = FixedArray!(int, capacity);
static assert(!mustAddGCRange!S);

assert(S([1, 2, 3].s[]) ==
       S([1, 2, 3].s[]));
assert(S([1, 2, 3].s[]) ==
       [1, 2, 3]);

insertBackMaybe is nothrow @nogc.

alias S = FixedArray!(int, 2);
S s;
assert(s.insertBackMaybe(42));
assert(s.insertBackMaybe(43));
assert(!s.insertBackMaybe(0));
assert(s.length == 2);

equality

enum capacity = 15;
alias S = FixedArray!(int, capacity);

assert(S.fromValuesUnsafe([1, 2, 3].s) ==
       S.fromValuesUnsafe([1, 2, 3].s));

const ax = [1, 2, 3].s;
assert(S.fromValuesUnsafe([1, 2, 3].s) == ax);
assert(S.fromValuesUnsafe([1, 2, 3].s) == ax[]);

const cx = [1, 2, 3].s;
assert(S.fromValuesUnsafe([1, 2, 3].s) == cx);
assert(S.fromValuesUnsafe([1, 2, 3].s) == cx[]);

immutable ix = [1, 2, 3].s;
assert(S.fromValuesUnsafe([1, 2, 3].s) == ix);
assert(S.fromValuesUnsafe([1, 2, 3].s) == ix[]);

assignment from const to immutable element type

enum capacity = 15;
alias String15 = StringN!(capacity);
static assert(!mustAddGCRange!String15);

const char[4] _ = ['a', 'b', 'c', 'd'];
auto x = String15(_[]);
assert(x.length == 4);
assert(x[] == "abcd");

borrow checking

enum capacity = 15;
alias String15 = StringN!(capacity, true);
static assert(String15.readBorrowCountMax == 7);
static assert(!mustAddGCRange!String15);

auto x = String15("alpha");

assert(x[] == "alpha");

{
    auto xw1 = x[];
    assert(x.isWriteBorrowed);
    assert(x.isBorrowed);
}

auto xr1 = (cast(const)x)[];
assert(x.readBorrowCount == 1);

auto xr2 = (cast(const)x)[];
assert(x.readBorrowCount == 2);

auto xr3 = (cast(const)x)[];
assert(x.readBorrowCount == 3);

auto xr4 = (cast(const)x)[];
assert(x.readBorrowCount == 4);

auto xr5 = (cast(const)x)[];
assert(x.readBorrowCount == 5);

auto xr6 = (cast(const)x)[];
assert(x.readBorrowCount == 6);

auto xr7 = (cast(const)x)[];
assert(x.readBorrowCount == 7);

assertThrown!AssertError((cast(const)x)[]);

Meta