1 module darray; 2 3 import std.array : back; 4 5 import exceptionhandling; 6 7 struct DArraySlice(FSA,T) { 8 FSA* fsa; 9 short low; 10 short high; 11 12 pragma(inline, true) 13 this(FSA* fsa, short low, short high) { 14 this.fsa = fsa; 15 this.low = low; 16 this.high = high; 17 } 18 19 pragma(inline, true) 20 @property bool empty() const pure @safe nothrow @nogc { 21 return this.low >= this.high; 22 } 23 24 pragma(inline, true) 25 @property size_t length() pure @safe nothrow @nogc { 26 return cast(size_t)(this.high - this.low); 27 } 28 29 pragma(inline, true) 30 @property ref T front() @nogc { 31 return (*this.fsa)[cast(size_t)this.low]; 32 } 33 34 pragma(inline, true) 35 @property ref const(T) front() const @nogc { 36 return (*this.fsa)[cast(size_t)this.low]; 37 } 38 39 pragma(inline, true) 40 @property ref T back() @nogc { 41 return (*this.fsa)[cast(size_t)(this.high - 1)]; 42 } 43 44 pragma(inline, true) 45 @property ref const(T) back() const @nogc { 46 return (*this.fsa)[cast(size_t)(this.high - 1)]; 47 } 48 49 pragma(inline, true) 50 void insertBack(S)(auto ref S s) { 51 (*this.fsa).insertBack(s); 52 } 53 54 /// Ditto 55 alias put = insertBack; 56 57 pragma(inline, true) 58 ref T opIndex(const size_t idx) @nogc { 59 return (*this.fsa)[this.low + idx]; 60 } 61 62 pragma(inline, true) 63 void popFront() pure @safe nothrow @nogc { 64 ++this.low; 65 } 66 67 pragma(inline, true) 68 void popBack() pure @safe nothrow @nogc { 69 --this.high; 70 } 71 72 pragma(inline, true) 73 @property typeof(this) save() pure @safe nothrow @nogc { 74 return this; 75 } 76 77 pragma(inline, true) 78 @property const(typeof(this)) save() const pure @safe nothrow @nogc { 79 return this; 80 } 81 82 pragma(inline, true) 83 typeof(this) opIndex() pure @safe nothrow @nogc { 84 return this; 85 } 86 87 pragma(inline, true) 88 typeof(this) opIndex(size_t l, size_t h) pure @safe nothrow @nogc { 89 return this.opSlice(l, h); 90 } 91 92 pragma(inline, true) 93 typeof(this) opSlice(size_t l, size_t h) pure @safe nothrow @nogc { 94 assert(l <= h); 95 return typeof(this)(this.fsa, 96 cast(short)(this.low + l), 97 cast(short)(this.low + h) 98 ); 99 } 100 } 101 102 struct DArray(T) { 103 import std.traits; 104 105 T[] data; 106 long base; 107 long len; 108 109 private void buildCapacity() { 110 if(this.len + 1 >= this.data.length) { 111 this.data.length = (this.data.length + 10) * 2; 112 } 113 } 114 115 pragma(inline, true) 116 this(Args...)(Args args) { 117 foreach(it; args) { 118 static if(isAssignable!(T,typeof(it))) { 119 this.insertBack(it); 120 } 121 } 122 } 123 124 pragma(inline, true) 125 size_t capacity() const @nogc @safe pure nothrow { 126 return this.data.length; 127 } 128 129 /** This function inserts an `S` element at the back if there is space. 130 Otherwise the behaviour is undefined. 131 */ 132 pragma(inline, true) 133 void insertBack(S)(auto ref S t) @trusted if(is(Unqual!(S) == T)) { 134 this.buildCapacity(); 135 136 this.data[ 137 cast(size_t)((this.base + this.len) % 138 this.data.length) 139 ] = t; 140 ++this.len; 141 } 142 143 /// Ditto 144 pragma(inline, true) 145 void insertBack(S)(auto ref S s) @trusted if(!is(Unqual!(S) == T)) { 146 this.buildCapacity(); 147 this.data[ 148 cast(size_t)((this.base + this.len) % 149 this.len) 150 ] = s; 151 } 152 153 /// Ditto 154 pragma(inline, true) 155 void insertBack(S)(auto ref S defaultValue, size_t num) { 156 for(size_t i = 0; i < num; ++i) { 157 this.insertBack(defaultValue); 158 } 159 } 160 /** This function inserts an `S` element at the front if there is space. 161 Otherwise the behaviour is undefined. 162 */ 163 pragma(inline, true) 164 void insertFront(S)(auto ref S t) @trusted if(is(Unqual!(S) == T)) { 165 this.buildCapacity(); 166 --this.base; 167 if(this.base < 0) { 168 this.base = 169 cast(typeof(this.base))(this.data.length - 1); 170 } 171 172 this.data[cast(size_t)this.base] = t; 173 ++this.len; 174 } 175 176 /** This function removes an element form the back of the array. 177 */ 178 pragma(inline, true) 179 void removeBack() { 180 assert(!this.empty); 181 182 --this.len; 183 } 184 185 /** This function removes an element form the front of the array. 186 */ 187 pragma(inline, true) 188 void removeFront() { 189 assert(!this.empty); 190 191 //this.begin = (this.begin + T.sizeof) % (Size * T.sizeof); 192 ++this.base; 193 if(this.base >= this.data.length) { 194 this.base = 0; 195 } 196 --this.len; 197 } 198 199 /** This function removes all elements from the array. 200 */ 201 pragma(inline, true) 202 void removeAll() { 203 while(!this.empty) { 204 this.removeBack(); 205 } 206 } 207 208 pragma(inline, true) 209 void remove(ulong idx) { 210 import std.stdio; 211 if(idx == 0) { 212 this.removeFront(); 213 } else if(idx == this.length - 1) { 214 this.removeBack(); 215 } else { 216 for(long i = idx + 1; i < this.length; ++i) { 217 this[cast(size_t)(i - 1)] = this[cast(size_t)i]; 218 } 219 this.removeBack(); 220 } 221 } 222 223 /** Access the last or the first element of the array. 224 */ 225 pragma(inline, true) 226 @property ref T back() @trusted @nogc { 227 debug ensure(!this.empty); 228 return this.data[ 229 cast(size_t)(this.base + this.len - 1) % this.data.length 230 ]; 231 } 232 233 pragma(inline, true) 234 @property ref const(T) back() const @trusted @nogc { 235 debug ensure(!this.empty); 236 return this.data[ 237 cast(size_t)(this.base + this.len - 1) % this.data.length 238 ]; 239 } 240 241 /// Ditto 242 pragma(inline, true) 243 @property ref T front() @trusted @nogc { 244 debug ensure(!this.empty); 245 return this.data[cast(size_t)this.base]; 246 } 247 248 pragma(inline, true) 249 @property ref const(T) front() const @trusted @nogc { 250 debug ensure(!this.empty); 251 return this.data[cast(size_t)this.base]; 252 } 253 254 /** Use an index to access the array. 255 */ 256 pragma(inline, true) 257 ref T opIndex(const size_t idx) @trusted @nogc { 258 debug ensure(idx < this.length); 259 return this.data[cast(size_t)((this.base + idx) % this.data.length)]; 260 } 261 262 /// Ditto 263 pragma(inline, true) 264 ref const(T) opIndex(const size_t idx) @trusted const @nogc { 265 debug ensure(idx < this.length); 266 return this.data[cast(size_t)((this.base + idx) % this.data.length)]; 267 } 268 269 270 pragma(inline, true) 271 DArraySlice!(typeof(this),T) opSlice() pure @nogc @safe nothrow { 272 return DArraySlice!(typeof(this),T)(&this, cast(short)0, 273 cast(short)this.length 274 ); 275 } 276 277 pragma(inline, true) 278 DArraySlice!(typeof(this),T) opSlice(const size_t low, 279 const size_t high) 280 pure @nogc @safe nothrow 281 { 282 return DArraySlice!(typeof(this),T)(&this, cast(short)low, 283 cast(short)high 284 ); 285 } 286 287 pragma(inline, true) 288 auto opSlice() pure @nogc @safe nothrow const { 289 return DArraySlice!(typeof(this),const(T)) 290 (&this, cast(short)0, cast(short)this.length); 291 } 292 293 pragma(inline, true) 294 auto opSlice(const size_t low, const size_t high) pure @nogc @safe nothrow const 295 { 296 return DArraySlice!(typeof(this),const(T)) 297 (&this, cast(short)low, cast(short)high); 298 } 299 300 /// Gives the length of the array. 301 pragma(inline, true) 302 @property size_t length() const pure @nogc nothrow { 303 return this.len; 304 } 305 306 /// Ditto 307 pragma(inline, true) 308 @property bool empty() const pure @nogc nothrow { 309 return this.len == 0; 310 } 311 312 } 313 314 version(unittest) { 315 import std.stdio; 316 } 317 318 @safe unittest { 319 DArray!(int) fsa; 320 fsa.insertFront(1337); 321 assert(fsa.length == 1); 322 assert(fsa[0] == 1337); 323 assert(fsa.front == 1337); 324 assert(fsa.back == 1337); 325 326 fsa.removeBack(); 327 assert(fsa.length == 0); 328 assert(fsa.empty); 329 fsa.insertFront(1336); 330 331 assert(fsa.length == 1); 332 assert(fsa[0] == 1336); 333 assert(fsa.front == 1336); 334 assert(fsa.back == 1336); 335 } 336 337 @safe unittest { 338 DArray!(int) fsa; 339 for(int i = 0; i < 32; ++i) { 340 fsa.insertFront(i); 341 assert(fsa.length == 1); 342 assert(!fsa.empty); 343 assert(fsa.front == i); 344 assert(fsa.back == i); 345 fsa.removeFront(); 346 assert(fsa.length == 0); 347 assert(fsa.empty); 348 } 349 } 350 351 @safe unittest { 352 DArray!(int) fsa; 353 for(int i = 0; i < 32; ++i) { 354 fsa.insertFront(i); 355 assert(fsa.length == 1); 356 assert(!fsa.empty); 357 assert(fsa.front == i); 358 assert(fsa.back == i); 359 fsa.removeBack(); 360 assert(fsa.length == 0); 361 assert(fsa.empty); 362 } 363 } 364 365 @safe unittest { 366 DArray!(int) fsa; 367 for(int i = 0; i < 32; ++i) { 368 fsa.insertBack(i); 369 assert(fsa.length == 1); 370 assert(!fsa.empty); 371 assert(fsa.front == i); 372 assert(fsa.back == i); 373 fsa.removeFront(); 374 assert(fsa.length == 0); 375 assert(fsa.empty); 376 } 377 } 378 379 /// 380 @safe unittest { 381 DArray!(int) fsa; 382 fsa.insertBack(1337); 383 assert(fsa.length == 1); 384 assert(fsa[0] == 1337); 385 386 fsa.insertBack(99, 5); 387 388 foreach(it; fsa[1 .. fsa.length]) { 389 assert(it == 99); 390 } 391 } 392 393 @safe unittest { 394 DArray!(int) fsa; 395 fsa.insertBack(1337); 396 assert(fsa.length == 1); 397 assert(fsa[0] == 1337); 398 399 fsa.removeBack(); 400 assert(fsa.length == 0); 401 assert(fsa.empty); 402 } 403 404 @safe unittest { 405 DArray!(int) fsa; 406 fsa.insertBack(1337); 407 fsa.insertBack(1338); 408 assert(fsa.length == 2); 409 assert(fsa[0] == 1337); 410 assert(fsa[1] == 1338); 411 412 fsa.removeAll(); 413 assert(fsa.length == 0); 414 assert(fsa.empty); 415 } 416 417 unittest { 418 DArray!(int) fsa; 419 foreach(i; 0..10) { 420 fsa.insertBack(i); 421 } 422 fsa.remove(1); 423 foreach(idx, i; [0,2,3,4,5,6,7,8,9]) { 424 assert(fsa[idx] == i); 425 } 426 fsa.remove(0); 427 foreach(idx, i; [2,3,4,5,6,7,8,9]) { 428 assert(fsa[idx] == i); 429 } 430 fsa.remove(7); 431 foreach(idx, i; [2,3,4,5,6,7,8]) { 432 assert(fsa[idx] == i); 433 } 434 fsa.remove(5); 435 foreach(idx, i; [2,3,4,5,6,8]) { 436 assert(fsa[idx] == i); 437 } 438 fsa.remove(1); 439 foreach(idx, i; [2,4,5,6,8]) { 440 assert(fsa[idx] == i); 441 } 442 fsa.remove(0); 443 foreach(idx, i; [4,5,6,8]) { 444 assert(fsa[idx] == i); 445 } 446 fsa.remove(0); 447 foreach(idx, i; [5,6,8]) { 448 assert(fsa[idx] == i); 449 } 450 } 451 452 453 /// 454 @safe unittest { 455 DArray!(int) fsa; 456 assertEqual(fsa.capacity, 0); 457 fsa.insertBack(1337); 458 fsa.insertBack(1338); 459 assert(fsa.capacity > 0); 460 assert(fsa.length == 2); 461 462 assert(fsa.front == 1337); 463 assert(fsa.back == 1338); 464 465 void f(ref const(DArray!int) d) { 466 assert(d.front == 1337); 467 assert(d.back == 1338); 468 } 469 470 f(fsa); 471 } 472 473 474 /// 475 @safe unittest { 476 DArray!(int) fsa; 477 fsa.insertBack(1337); 478 fsa.insertBack(1338); 479 assert(fsa.length == 2); 480 481 assert(fsa[0] == 1337); 482 assert(fsa[1] == 1338); 483 484 void f(ref const(DArray!int) d) { 485 assert(d[0] == 1337); 486 assert(d[1] == 1338); 487 } 488 489 f(fsa); 490 } 491 /// 492 @safe unittest { 493 DArray!(int) fsa; 494 assert(fsa.empty); 495 assert(fsa.length == 0); 496 497 fsa.insertBack(1337); 498 fsa.insertBack(1338); 499 500 assert(fsa.length == 2); 501 assert(!fsa.empty); 502 } 503 504 unittest { 505 DArray!int d; 506 assertEqual(d.length, 0); 507 assert(d.empty); 508 509 for(int i = 0; i < 20; ++i) { 510 d.insertBack(i); 511 assertEqual(d.length, i+1); 512 } 513 assertEqual(d.length, 20); 514 515 DArray!int d2 = d; 516 assertEqual(d.length, 20); 517 assertEqual(d2.length, 20); 518 519 d2.insertBack(21); 520 assertEqual(d.length, 20); 521 assertEqual(d2.length, 21); 522 } 523 524 unittest { 525 import exceptionhandling; 526 import std.stdio; 527 528 DArray!(int) fsa; 529 assert(fsa.empty); 530 cast(void)assertEqual(fsa.length, 0); 531 532 fsa.insertBack(1); 533 assert(!fsa.empty); 534 cast(void)assertEqual(fsa.length, 1); 535 cast(void)assertEqual(fsa.front, 1); 536 cast(void)assertEqual(fsa.back, 1); 537 538 fsa.insertBack(2); 539 assert(!fsa.empty); 540 cast(void)assertEqual(fsa.length, 2); 541 cast(void)assertEqual(fsa.front, 1); 542 cast(void)assertEqual(fsa.back, 2); 543 544 fsa.removeFront(); 545 assert(!fsa.empty); 546 cast(void)assertEqual(fsa.length, 1); 547 cast(void)assertEqual(fsa.front, 2); 548 cast(void)assertEqual(fsa.back, 2); 549 550 fsa.removeBack(); 551 //writefln("%s %s", fsa.begin, fsa.end); 552 assert(fsa.empty); 553 cast(void)assertEqual(fsa.length, 0); 554 } 555 556 unittest { 557 import std.format; 558 559 DArray!(char) fsa; 560 formattedWrite(fsa[], "%s %s %s", "Hello", "World", 42); 561 //assert(cast(string)fsa == "Hello World 42", cast(string)fsa); 562 } 563 564 unittest { 565 import exceptionhandling; 566 567 DArray!(int) fsa; 568 auto a = [0,1,2,4,32,64,1024,2048,65000]; 569 foreach(idx, it; a) { 570 fsa.insertBack(it); 571 assertEqual(fsa.length, idx + 1); 572 assertEqual(fsa.back, it); 573 for(int i = 0; i < idx; ++i) { 574 assertEqual(fsa[i], a[i]); 575 } 576 } 577 } 578 579 unittest { 580 import exceptionhandling; 581 import std.traits; 582 import std.meta; 583 import std.range; 584 import std.stdio; 585 import std.conv : to; 586 foreach(Type; AliasSeq!(byte,int,long)) { 587 DArray!(Type) fsa2; 588 static assert(isInputRange!(typeof(fsa2[]))); 589 static assert(isForwardRange!(typeof(fsa2[]))); 590 static assert(isBidirectionalRange!(typeof(fsa2[]))); 591 foreach(idx, it; [[0], [0,1,2,3,4], [2,3,6,5,6,21,9,36,61,62]]) { 592 DArray!(Type) fsa; 593 foreach(jdx, jt; it) { 594 fsa.insertBack(to!Type(jt)); 595 //writefln("%s idx %d jdx %d length %d", Type.stringof, idx, jdx, fsa.length); 596 cast(void)assertEqual(fsa.length, jdx + 1); 597 foreach(kdx, kt; it[0 .. jdx]) { 598 assertEqual(fsa[kdx], kt); 599 } 600 601 { 602 auto forward = fsa[]; 603 auto forward2 = forward; 604 cast(void)assertEqual(forward.length, jdx + 1); 605 for(size_t i = 0; i < forward.length; ++i) { 606 cast(void)assertEqual(forward[i], it[i]); 607 cast(void)assertEqual(forward2.front, it[i]); 608 forward2.popFront(); 609 } 610 assert(forward2.empty); 611 612 auto backward = fsa[]; 613 auto backward2 = backward.save; 614 cast(void)assertEqual(backward.length, jdx + 1); 615 for(size_t i = 0; i < backward.length; ++i) { 616 cast(void)assertEqual(backward[backward.length - i - 1], 617 it[jdx - i] 618 ); 619 620 cast(void)assertEqual(backward2.back, 621 it[0 .. jdx + 1 - i].back 622 ); 623 backward2.popBack(); 624 } 625 assert(backward2.empty); 626 auto forward3 = fsa[].save; 627 auto forward4 = fsa[0 .. jdx + 1]; 628 629 while(!forward3.empty && !forward4.empty) { 630 cast(void)assertEqual(forward3.front, forward4.front); 631 cast(void)assertEqual(forward3.back, forward4.back); 632 forward3.popFront(); 633 forward4.popFront(); 634 } 635 assert(forward3.empty); 636 assert(forward4.empty); 637 } 638 639 { 640 const(DArray!(Type))* constFsa; 641 constFsa = &fsa; 642 auto forward = (*constFsa)[]; 643 auto forward2 = forward.save; 644 cast(void)assertEqual(forward.length, jdx + 1); 645 for(size_t i = 0; i < forward.length; ++i) { 646 cast(void)assertEqual(cast(int)forward[i], it[i]); 647 cast(void)assertEqual(cast(int)forward2.front, it[i]); 648 forward2.popFront(); 649 } 650 assert(forward2.empty); 651 652 auto backward = (*constFsa)[]; 653 auto backward2 = backward.save; 654 cast(void)assertEqual(backward.length, jdx + 1); 655 for(size_t i = 0; i < backward.length; ++i) { 656 cast(void)assertEqual(backward[backward.length - i - 1], 657 it[jdx - i] 658 ); 659 660 cast(void)assertEqual(backward2.back, 661 it[0 .. jdx + 1 - i].back 662 ); 663 backward2.popBack(); 664 } 665 assert(backward2.empty); 666 auto forward3 = (*constFsa)[]; 667 auto forward4 = (*constFsa)[0 .. jdx + 1]; 668 669 while(!forward3.empty && !forward4.empty) { 670 cast(void)assertEqual(forward3.front, forward4.front); 671 cast(void)assertEqual(forward3.back, forward4.back); 672 forward3.popFront(); 673 forward4.popFront(); 674 } 675 assert(forward3.empty); 676 assert(forward4.empty); 677 } 678 } 679 } 680 } 681 } 682 683 // Test case Issue #2 684 unittest { 685 import exceptionhandling; 686 687 DArray!(int) fsa; 688 fsa.insertBack(0); 689 assert(fsa.length == 1); 690 fsa.insertBack(1); 691 692 assertEqual(fsa[0], 0); 693 assertEqual(fsa[1], 1); 694 assertEqual(fsa.front, 0); 695 assertEqual(fsa.back, 1); 696 } 697 698 unittest { 699 import std.stdio; 700 import core.memory; 701 enum size = 128; 702 DArray!(int)[size] arrays; 703 foreach (i; 0..size) { 704 foreach (j; 0..size) { 705 assert(arrays[i].length == j); 706 arrays[i].insertBack(i * 1000 + j); 707 } 708 } 709 bool[int] o; 710 foreach (i; 0..size) { 711 foreach (j; 0..size) { 712 assert(arrays[i][j] !in o); 713 o[arrays[i][j]] = true; 714 } 715 } 716 assert(size * size == o.length); 717 } 718 719 // issue #1 won't fix not sure why 720 unittest { 721 import std.stdio; 722 import core.memory; 723 enum size = 256; 724 DArray!(Object) arrays; 725 foreach (i; 0..size) { 726 auto o = new Object(); 727 assert(arrays.length == i); 728 foreach(it; arrays[]) { 729 assert(it !is null); 730 assert(it.toHash()); 731 } 732 arrays.insertBack(o); 733 assert(arrays.back is o); 734 assert(!arrays.empty); 735 assert(arrays.length == i + 1); 736 } 737 738 assert(arrays.length == size); 739 for(int i = 0; i < size; ++i) { 740 assert(arrays[i] !is null); 741 assert(arrays[i].toHash()); 742 } 743 bool[Object] o; 744 foreach (i; 0..size) { 745 assert(arrays[i] !is null); 746 assert(arrays[i] !in o); 747 o[arrays[i]] = true; 748 749 } 750 assert(size == o.length); 751 } 752 753 unittest { 754 import exceptionhandling; 755 DArray!(int) fsa; 756 fsa.insertFront(1337); 757 assert(!fsa.empty); 758 assertEqual(fsa.length, 1); 759 assertEqual(fsa.back, 1337); 760 assertEqual(fsa.front, 1337); 761 } 762 763 // Test case Issue #2 764 unittest { 765 enum size = 256; 766 DArray!(Object)[size] arrays; 767 foreach (i; 0..size) { 768 foreach (j; 0..size) { 769 arrays[i].insertBack(new Object); 770 } 771 } 772 bool[Object] o; 773 foreach (i; 0..size) { 774 foreach (j; 0..size) { 775 o[arrays[i][j]] = true; 776 } 777 } 778 assert(o.length == size * size); 779 } 780 781 unittest { 782 import std.range.primitives : hasAssignableElements, hasSlicing, isRandomAccessRange; 783 DArray!(int) fsa; 784 auto s = fsa[]; 785 static assert(hasSlicing!(typeof(s))); 786 static assert(isRandomAccessRange!(typeof(s))); 787 static assert(hasAssignableElements!(typeof(s))); 788 } 789 790 unittest { 791 import exceptionhandling; 792 793 DArray!(int) fsa; 794 for(int i = 0; i < 32; ++i) { 795 fsa.insertBack(i); 796 } 797 798 auto s = fsa[]; 799 for(int i = 0; i < 32; ++i) { 800 assert(s[i] == i); 801 } 802 s = s[0 .. 33]; 803 for(int i = 0; i < 32; ++i) { 804 assert(s[i] == i); 805 } 806 807 auto t = s.save; 808 s.popFront(); 809 for(int i = 0; i < 32; ++i) { 810 assert(t[i] == i); 811 } 812 813 auto r = t[10, 20]; 814 for(int i = 10; i < 20; ++i) { 815 assertEqual(r[i-10], fsa[i]); 816 } 817 818 foreach(ref it; r) { 819 it = 0; 820 } 821 822 for(int i = 10; i < 20; ++i) { 823 assertEqual(r[i-10], 0); 824 } 825 } 826 827 unittest { 828 DArray!(int) fsaM; 829 for(int i = 0; i < 32; ++i) { 830 fsaM.insertBack(i); 831 } 832 833 const(DArray!(int)) fsa = fsaM; 834 835 auto s = fsa[]; 836 for(int i = 0; i < 32; ++i) { 837 assert(s[i] == i); 838 } 839 s = s[0 .. 33]; 840 for(int i = 0; i < 32; ++i) { 841 assert(s[i] == i); 842 } 843 844 auto t = s.save; 845 s.popFront(); 846 for(int i = 0; i < 32; ++i) { 847 assert(t[i] == i); 848 } 849 } 850 851 unittest { 852 import std.random : Random, uniform; 853 import std.format : format; 854 struct Data { 855 ulong a, b, c, d, e; 856 } 857 858 auto rnd = Random(1337); 859 DArray!(Data) a; 860 for(size_t i = 0; i < 4096; ++i) { 861 Data d; 862 d.a = i; 863 d.b = i; 864 d.c = i; 865 d.d = i; 866 d.e = i; 867 868 a.insertBack(d); 869 870 int c = uniform(4,10, rnd); 871 while(a.length > c) { 872 a.removeFront(); 873 } 874 assert(!a.empty); 875 assert(a.length <= c, format("%d < %d", a.length, c)); 876 877 auto r = a[]; 878 assert(r.back.a == i); 879 assert(r.front.a <= i); 880 881 foreach(it; r[]) { 882 assert(it.a <= i); 883 } 884 885 auto cr = (*(cast(const(typeof(a))*)(&a))); 886 assert(cr.back.a == i); 887 assert(cr.front.a <= i); 888 889 auto crr = cr[]; 890 assert(crr.front.a <= i); 891 assert(crr.back.a <= i); 892 foreach(it; crr.save) { 893 assert(it.a <= i); 894 } 895 } 896 }