1 /** 2 License: 3 Boost Software License - Version 1.0 - August 17th, 2003 4 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 27 Authors: 28 Alexandru Ermicioi 29 **/ 30 module aermicioi.aedi_property_reader.convertor.placeholder; 31 32 import aermicioi.aedi : Wrapper; 33 import aermicioi.aedi_property_reader.convertor.traits : n; 34 import aermicioi.aedi_property_reader.convertor.convertor : Convertor; 35 import std.experimental.allocator; 36 import std.conv; 37 import std.traits : Unqual; 38 import std.typecons : scoped; 39 40 /** 41 Interface for objects that are aware of a type and can provide it. 42 **/ 43 interface TypeAware { 44 45 /** 46 Get the type that is stored in component. 47 48 Returns: 49 TypeInfo stored in component. 50 **/ 51 const(TypeInfo) type() const nothrow @property @nogc pure; 52 } 53 54 /** 55 Interface for objects that are aware of original type from which containing value was created. 56 **/ 57 interface OriginalTypeAware { 58 59 /** 60 Get the type of original component from which contained one was created/converted. 61 62 Returns: 63 TypeInfo of original component 64 **/ 65 const(TypeInfo) original() const @property nothrow @nogc pure; 66 } 67 68 /** 69 Interface for objects that are aware of convertor used to convert to destination type component stored in the implementor. 70 **/ 71 interface ConvertorAware { 72 73 /** 74 Get the convertor used to convert component stored in implementor of this interface. 75 76 Returns: 77 Convertor used to convert component stored by implementor of this interface 78 **/ 79 const(Convertor) convertor() const @property nothrow @nogc pure; 80 } 81 82 /** 83 Interface for objects aware of allocator used in conversion of contained component. 84 **/ 85 interface AllocatorAware { 86 87 /** 88 Get allocator used in conversion of component stored in implementor. 89 90 Returns: 91 Allocator used to convert component stored by implementor of this interface. 92 **/ 93 inout(RCIAllocator) allocator() inout @property nothrow @nogc pure; 94 } 95 96 /** 97 Interface for objects that can hold a value in. 98 **/ 99 interface Placeholder(T) { 100 101 @property { 102 103 /** 104 Get stored value. 105 106 Returns: 107 T value stored in component 108 **/ 109 ref inout(T) value() nothrow @safe inout @nogc; 110 111 /** 112 Store value in component. 113 114 Params: 115 value = value that will be stored in. 116 117 Returns: 118 Reference to stored value. 119 **/ 120 ref T value(ref T value) nothrow @safe; 121 122 /** 123 ditto 124 **/ 125 final ref T value(T value) nothrow @safe { 126 return this.value(value); 127 } 128 129 } 130 } 131 132 /** 133 Interface for components that are able to destroy component contained in them using convertor, allocator, and original type converted from. 134 **/ 135 interface Destroyable { 136 137 /** 138 Destroy contained component using convertor and additional information available. 139 140 Returns: 141 true if it was able to destroy, false otherwise. 142 **/ 143 bool destruct() @safe nothrow; 144 } 145 146 /** 147 Implementation of Placeholder!T. 148 **/ 149 class PlaceholderImpl(T) : Placeholder!T, Wrapper!T, TypeAware, AllocatorAware { 150 151 private { 152 T payload; 153 RCIAllocator allocator_; 154 } 155 156 /** 157 Constructor for placeholder accepting stored value. 158 159 Params: 160 value = value that will be stored in. 161 **/ 162 this(ref T value, RCIAllocator allocator = theAllocator) nothrow { 163 this.payload = value; 164 this.allocator_ = allocator; 165 } 166 167 this(ref const T value, RCIAllocator allocator = theAllocator) nothrow const { 168 this.payload = value; 169 this.allocator_ = allocator; 170 } 171 172 this(ref immutable T value, immutable RCIAllocator allocator) nothrow immutable { 173 this.payload = value; 174 this.allocator_ = allocator; 175 } 176 177 /** 178 ditto 179 **/ 180 this(T value, RCIAllocator allocator = theAllocator) nothrow { 181 this(value, allocator); 182 } 183 184 /** 185 ditto 186 **/ 187 this(const T value, RCIAllocator allocator = theAllocator) nothrow const { 188 this(value, allocator); 189 } 190 191 /** 192 ditto 193 **/ 194 this(immutable T value, immutable RCIAllocator allocator) nothrow immutable { 195 this(value, allocator); 196 } 197 198 @property { 199 /** 200 Get the type of component that is stored in. 201 202 Returns: 203 TypeInfo of stored component. 204 **/ 205 TypeInfo type() const nothrow @nogc pure { 206 return typeid(T); 207 } 208 209 /** 210 Get allocator 211 212 Returns: 213 RCIAllocator 214 **/ 215 inout(RCIAllocator) allocator() @safe nothrow pure inout { 216 return this.allocator_; 217 } 218 219 /** 220 Store value in component. 221 222 Params: 223 value = value that will be stored in. 224 225 Returns: 226 Reference to stored value. 227 **/ 228 ref T value(ref T value) nothrow @safe { 229 static if (!is(T == const) && !is(T == immutable)) { 230 import std.algorithm : move; 231 232 value.move(this.payload); 233 } 234 235 return this.payload; 236 } 237 238 /** 239 Get value 240 241 Returns: 242 ref inout(T) 243 **/ 244 ref inout(T) value() @safe nothrow inout @nogc { 245 return this.payload; 246 } 247 } 248 } 249 250 /** 251 Implementation of Placeholder!T. 252 **/ 253 class OriginalAwarePlaceholderImpl(T) : PlaceholderImpl!T, OriginalTypeAware { 254 255 private { 256 const TypeInfo original_; 257 } 258 259 /** 260 Constructor for placeholder accepting stored value. 261 262 Params: 263 value = value that will be stored in. 264 **/ 265 this(ref T value, const TypeInfo original, RCIAllocator allocator = theAllocator) nothrow 266 in (original !is null, "Placeholder expects original type to be provided, not null.") { 267 super(value, allocator); 268 this.original_ = original; 269 } 270 271 this(ref const T value, const TypeInfo original, RCIAllocator allocator = theAllocator) nothrow const 272 in (original !is null, "Placeholder expects original type to be provided, not null.") { 273 super(value, allocator); 274 this.original_ = original; 275 } 276 277 this(ref immutable T value, immutable TypeInfo original, immutable RCIAllocator allocator) nothrow immutable 278 in (original !is null, "Placeholder expects original type to be provided, not null.") { 279 super(value, allocator); 280 this.original_ = original_; 281 } 282 283 /** 284 ditto 285 **/ 286 this(T value, const TypeInfo original, RCIAllocator allocator = theAllocator) nothrow { 287 this(value, original, allocator); 288 } 289 290 /** 291 ditto 292 **/ 293 this(const T value, const TypeInfo original, RCIAllocator allocator = theAllocator) nothrow const { 294 this(value, original, allocator); 295 } 296 297 /** 298 ditto 299 **/ 300 this(immutable T value, immutable TypeInfo original, immutable RCIAllocator allocator) nothrow immutable { 301 this(value, original, allocator); 302 } 303 304 @property { 305 306 /** 307 Get the type of original component from which contained one was created/converted. 308 309 Returns: 310 TypeInfo of original component 311 **/ 312 const(TypeInfo) original() const nothrow @nogc pure { 313 return this.original_; 314 } 315 } 316 } 317 318 /** 319 Implementation of Placeholder!T. 320 **/ 321 class ConvertorAndOriginalAwarePlaceholderImpl(T) : OriginalAwarePlaceholderImpl!T, ConvertorAware { 322 323 private { 324 const Convertor convertor_; 325 } 326 327 /** 328 Constructor for placeholder accepting stored value. 329 330 Params: 331 value = value that will be stored in. 332 **/ 333 this(ref T value, const TypeInfo original, const Convertor convertor, RCIAllocator allocator = theAllocator) nothrow 334 in (convertor !is null, "Placeholder expects convertor of component to be provided, not null.") { 335 super(value, original, allocator); 336 this.convertor_ = convertor; 337 } 338 339 this(ref const T value, const TypeInfo original, const Convertor convertor, RCIAllocator allocator = theAllocator) nothrow const 340 in (convertor !is null, "Placeholder expects convertor of component to be provided, not null.") { 341 super(value, original, allocator); 342 this.convertor_ = convertor; 343 } 344 345 this(ref immutable T value, immutable TypeInfo original, immutable Convertor convertor, immutable RCIAllocator allocator) nothrow immutable 346 in (convertor !is null, "Placeholder expects convertor of component to be provided, not null.") { 347 super(value, original, allocator); 348 this.convertor_ = convertor_; 349 } 350 351 /** 352 ditto 353 **/ 354 this(T value, const TypeInfo original, const Convertor convertor, RCIAllocator allocator = theAllocator) nothrow { 355 this(value, original, convertor, allocator); 356 } 357 358 /** 359 ditto 360 **/ 361 this(const T value, const TypeInfo original, const Convertor convertor, RCIAllocator allocator = theAllocator) nothrow const { 362 this(value, original, convertor, allocator); 363 } 364 365 /** 366 ditto 367 **/ 368 this(immutable T value, immutable TypeInfo original, immutable Convertor convertor, immutable RCIAllocator allocator) nothrow immutable { 369 this(value, original, convertor, allocator); 370 } 371 372 @property { 373 374 /** 375 Get the type of original component from which contained one was created/converted. 376 377 Returns: 378 TypeInfo of original component 379 **/ 380 const(Convertor) convertor() const nothrow @nogc pure { 381 return this.convertor_; 382 } 383 } 384 } 385 386 /** 387 Wrap up a value in a placeholding object. 388 389 Params: 390 value = value that will be wrapped in placeholding object 391 from = original type from which value was converted 392 convertor = convertor used in converting value out of from 393 allocator = allocator used to allocate placeholding object 394 395 Returns: 396 Placeholder!T with value as content. 397 **/ 398 ConvertorAndOriginalAwarePlaceholderImpl!T pack(T, From)(auto ref T value, const From from, const Convertor convertor, RCIAllocator allocator = theAllocator) @trusted { 399 return allocator.make!(ConvertorAndOriginalAwarePlaceholderImpl!T)(value, from.identify, convertor, allocator); 400 } 401 402 /** 403 ditto 404 **/ 405 OriginalAwarePlaceholderImpl!T pack(T, From)(auto ref T value, const From from, RCIAllocator allocator = theAllocator) @trusted { 406 return allocator.make!(OriginalAwarePlaceholderImpl!T)(value, from.identify, allocator); 407 } 408 409 /** 410 ditto 411 **/ 412 PlaceholderImpl!T pack(T)(auto ref T value, RCIAllocator allocator = theAllocator) @trusted { 413 return allocator.make!(PlaceholderImpl!T)(value, allocator); 414 } 415 416 /** 417 ditto 418 **/ 419 auto packWithStorageClass(alias StorageType, T)(auto ref T value, const TypeInfo from, const Convertor convertor, RCIAllocator allocator = theAllocator) @trusted { 420 421 return pack!(StorageType!T)(cast(StorageType!T) value, from, convertor, allocator); 422 } 423 424 /** 425 ditto 426 **/ 427 auto packWithStorageClass(alias StorageType, T)(auto ref T value, const TypeInfo from, RCIAllocator allocator = theAllocator) @trusted { 428 429 return pack!(StorageType!T)(cast(StorageType!T) value, from, allocator); 430 } 431 432 /** 433 ditto 434 **/ 435 auto packWithStorageClass(alias StorageType, T)(auto ref T value, RCIAllocator allocator = theAllocator) @trusted { 436 437 return pack!(StorageType!T)(cast(StorageType!T) value, allocator); 438 } 439 440 /** 441 Wrap up a value in a placeholding object stored on stack instead of allocator. 442 443 Params: 444 value = value that will be wrapped in placeholding object 445 446 Returns: 447 scoped Placeholder!T with value as content. 448 **/ 449 auto stored(T)(auto ref T value, const TypeInfo from, const Convertor convertor) { 450 import std.typecons : scoped; 451 452 return scoped!(ConvertorAndOriginalAwarePlaceholderImpl!T)(value, from, convertor, RCIAllocator()); 453 } 454 455 /** 456 ditto 457 **/ 458 auto stored(T)(auto ref T value, const TypeInfo from) { 459 import std.typecons : scoped; 460 461 return scoped!(OriginalAwarePlaceholderImpl!T)(value, from, RCIAllocator()); 462 } 463 464 /** 465 ditto 466 **/ 467 auto stored(T)(auto ref T value) { 468 import std.typecons : scoped; 469 470 return scoped!(PlaceholderImpl!T)(value, RCIAllocator()); 471 } 472 473 /** 474 Downcast object to type T, or unwrap it from Placeholder!T. 475 476 Downcast object to type T, or unwrap it from Placeholder!T. 477 If T is rooted in Object, downcast will be performed, otherwise 478 it is assumed that T is stored in Placeholder!T object, and therefore 479 object is downcast to Placeholder!T and then returned. 480 481 Params: 482 object = object from which to unwrap value of type T 483 Returns: 484 T if it is rooted in Object, or Placeholder!T if it is not. 485 **/ 486 auto ref T unwrap(T)(inout(Object) object) @trusted nothrow { 487 static if (is(T : Object) || is(T : const Object) || is(T : immutable Object) || is(T : inout(Object))) { 488 { 489 auto downcasted = cast(T) object; 490 491 if (downcasted !is null) { 492 return downcasted; 493 } 494 } 495 } 496 497 { 498 auto downcasted = cast(Placeholder!T) object; 499 500 if (downcasted !is null) { 501 return downcasted.value; 502 } 503 } 504 505 assert(false, text(object.identify, " does not implement", typeid(T), ". inout(Object) cannot be extracted.")); 506 } 507 508 /** 509 ditto 510 **/ 511 auto ref T unwrap(T : Placeholder!Z, Z)(T placeholder) @trusted nothrow { 512 return placeholder; 513 } 514 515 auto ref T unwrap(T : typeof(null))(inout(Object) object) { 516 if (object is null) { 517 return null; 518 } 519 520 Placeholder!T placeholder = cast(Placeholder!T) object; 521 522 if (placeholder !is null) { 523 return placeholder.value; 524 } 525 526 assert(false, text(object.identify, " is not of ", typeid(null))); 527 } 528 529 /** 530 Downcast object to type T, or destructively unwrap it from Placeholder!T. 531 532 Downcast object to type T, or destructively unwrap it from Placeholder!T. 533 If T is rooted in Object, downcast will be performed, otherwise 534 it is assumed that T is stored in Placeholder!T object, and therefore 535 object is downcast to Placeholder!T it's value extracted and placeholder itself is 536 disposed of. 537 538 Params: 539 object = object from which to unwrap value of type T 540 Returns: 541 T if it is rooted in Object, or Placeholder!T if it is not. 542 **/ 543 T unpack(T)(Object object, RCIAllocator allocator = theAllocator) @trusted { 544 import aermicioi.aedi_property_reader.convertor.traits : n; 545 static if (is(T : Object) || is(T : const Object) || is(T : immutable Object) || is(T : inout(Object))) { 546 { 547 auto downcasted = cast(T) object; 548 549 if (downcasted !is null) { 550 return downcasted; 551 } 552 } 553 } 554 555 { 556 auto downcasted = cast(Placeholder!T) object; 557 558 if (downcasted !is null) { 559 return downcasted.unpack; 560 } 561 } 562 563 assert(false, text(object.identify, " does not implement", typeid(T), ". inout(Object) cannot be extracted.")); 564 } 565 566 T unpack(T : typeof(null))(Object object, RCIAllocator allocator = theAllocator) @trusted { 567 import aermicioi.aedi_property_reader.convertor.traits : n; 568 if (object is null) { 569 return null; 570 } 571 572 { 573 auto downcasted = cast(Placeholder!T) object; 574 575 if (downcasted !is null) { 576 return downcasted.unpack; 577 } 578 } 579 580 assert(false, text(object.identify, " does not implement", typeid(T), ". inout(Object) cannot be extracted.")); 581 } 582 583 /** 584 ditto 585 **/ 586 Z unpack(T : Placeholder!Z, Z)(T placeholder, RCIAllocator allocator = theAllocator) @trusted nothrow { 587 try { 588 scope(exit) allocator.dispose(placeholder); 589 590 return placeholder.value; 591 } catch (Exception e) { 592 throw new Error("Failed to dispose placeholder for a value", e); 593 } 594 } 595 596 /** 597 Identify the type of object. 598 599 Identify the type of object. 600 The object will be downcasted to TypeAware first, in order 601 to test if object is holding information about some type. 602 If so, the type from TypeAware object will be returned, 603 otherwise classinfo of object itself. 604 605 Params: 606 object = component to be identified 607 Returns: 608 TypeInfo of stored type of object implements TypeAware, or classinfo of object itself. 609 **/ 610 const(TypeInfo) identify(T)(T object) @trusted nothrow @nogc 611 if (is(T : Object) || is(T : const Object) || is(T : immutable Object)) { 612 613 if (object is null) { 614 return typeid(null); 615 } 616 617 TypeAware p = cast(TypeAware) object; 618 619 if (p !is null) { 620 return p.type; 621 } 622 623 return object.classinfo; 624 } 625 626 /** 627 ditto 628 **/ 629 const(TypeInfo) identify(T)(auto ref T component) nothrow @nogc @safe 630 if (!(is(T : Object) || is(T : const Object) || is(T : immutable Object))) { 631 import std.stdio; 632 633 return typeid(component); 634 } 635 636 /** 637 ditto 638 **/ 639 T identify(T : TypeInfo)(auto ref T typeinfo) nothrow @nogc @safe { 640 import std.stdio; 641 642 return typeinfo; 643 } 644 645 /** 646 ditto 647 **/ 648 T identify(T : const TypeInfo)(auto ref T typeinfo) nothrow @nogc @safe { 649 import std.stdio; 650 651 return typeinfo; 652 } 653 654 /** 655 ditto 656 **/ 657 T identify(T : immutable TypeInfo)(auto ref T typeinfo) nothrow @nogc @safe { 658 import std.stdio; 659 660 return typeinfo; 661 } 662 663 /** 664 Identify the original type of converted component. 665 666 Identify the original type of converted component. 667 The object will be downcasted to OriginalTypeAware 668 interface and if it succeeded original type will be 669 returned. For non-object components typeid(void) 670 will be returned as no OriginalTypeAware they could implement. 671 672 Params: 673 object = converted component for which original type would need to be identified. 674 Returns: 675 TypeInfo of original type from which current one was converted. 676 **/ 677 const(TypeInfo) original(T)(T object) @trusted nothrow @nogc pure 678 if (is(T : Object) || is(T : const Object) || is(T : immutable Object)) { 679 680 if (object is null) { 681 return typeid(void); 682 } 683 684 OriginalTypeAware p = cast(OriginalTypeAware) object; 685 686 if (p !is null) { 687 return p.original; 688 } 689 690 return object.classinfo; 691 } 692 693 /** 694 ditto 695 **/ 696 TypeInfo original(T)(auto ref T component) nothrow @nogc @safe 697 if (!(is(T : Object) || is(T : const Object) || is(T : immutable Object))) { 698 import std.stdio; 699 700 return typeid(void); 701 } 702 703 /** 704 ditto 705 **/ 706 TypeInfo original(T : TypeInfo)(auto ref T typeinfo) nothrow @nogc @safe { 707 import std.stdio; 708 709 return typeid(void); 710 } 711 712 /** 713 ditto 714 **/ 715 const(TypeInfo) original(T : const TypeInfo)(auto ref T typeinfo) nothrow @nogc @safe { 716 import std.stdio; 717 718 return typeid(void); 719 } 720 721 /** 722 ditto 723 **/ 724 immutable(TypeInfo) original(T : immutable TypeInfo)(auto ref T typeinfo) nothrow @nogc @safe { 725 import std.stdio; 726 727 return typeid(void); 728 } 729 730 /** 731 ditto 732 **/ 733 const(TypeInfo) original(T)(T object, const TypeInfo from) @trusted nothrow @nogc pure { 734 auto result = object.original; 735 736 if (result is typeid(void)) { 737 return from; 738 } 739 740 return result; 741 } 742 743 /** 744 Identify the convertor used to convert component. 745 746 Identify the convertor used to convert component. 747 The object will be downcasted to ConvertorAware 748 interface and if it succeeded convertor used to 749 convert component will be returned. For non-object 750 components null will be returned as no convertor 751 can be extracted from them. 752 753 Params: 754 object = converted component for which used convertor would need to be identified. 755 Returns: 756 Convertor used to convert to contained component. 757 **/ 758 const(Convertor) convertorOf(T)(T object) @trusted nothrow @nogc pure 759 if (is(T : Object) || is(T : const Object) || is(T : immutable Object)) { 760 761 if (object !is null) { 762 ConvertorAware p = cast(ConvertorAware) object; 763 764 if (p !is null) { 765 return p.convertor; 766 } 767 } 768 769 return null; 770 } 771 772 /** 773 ditto 774 **/ 775 Convertor convertorOf(T)(auto ref T component) nothrow @nogc @safe 776 if (!(is(T : Object) || is(T : const Object) || is(T : immutable Object))) { 777 import std.stdio; 778 779 return null; 780 } 781 782 /** 783 ditto 784 **/ 785 Convertor convertorOf(T : Convertor)(auto ref T convertor) nothrow @nogc @safe { 786 import std.stdio; 787 788 return convertor; 789 } 790 791 /** 792 ditto 793 **/ 794 const(Convertor) convertorOf(T : const Convertor)(auto ref T convertor) nothrow @nogc @safe { 795 import std.stdio; 796 797 return convertor; 798 } 799 800 /** 801 ditto 802 **/ 803 immutable(Convertor) convertorOf(T : immutable Convertor)(auto ref T convertor) nothrow @nogc @safe { 804 import std.stdio; 805 806 return convertor; 807 } 808 809 /** 810 Identify the allocator used to convert component. 811 812 Identify the allocator used to convert component. 813 The object will be downcasted to AllocatorAware 814 interface and if it succeeded convertor used to 815 convert component will be returned. For non-object 816 components empty allocator will be returned as no convertor 817 can be extracted from them. 818 819 Params: 820 object = converted component for which used allocator would need to be identified. 821 Returns: 822 RCIAllocator used in conversion process. 823 **/ 824 RCIAllocator allocatorOf(T)(T object) @trusted nothrow @nogc pure 825 if (is(T : Object) || is(T : const Object) || is(T : immutable Object)) { 826 827 if (object !is null) { 828 AllocatorAware p = cast(AllocatorAware) object; 829 830 if (p !is null) { 831 return p.allocator; 832 } 833 } 834 835 return RCIAllocator(null); 836 } 837 838 /** 839 ditto 840 **/ 841 RCIAllocator allocatorOf(T)(auto ref T component) nothrow @nogc @safe 842 if (!(is(T : Object) || is(T : const Object) || is(T : immutable Object))) { 843 import std.stdio; 844 845 return RCIAllocator(null); 846 } 847 848 /** 849 ditto 850 **/ 851 RCIAllocator allocatorOf(T : RCIAllocator)(auto ref T allocator) nothrow @nogc @safe { 852 import std.stdio; 853 854 return allocator; 855 } 856 857 /** 858 ditto 859 **/ 860 const(RCIAllocator) allocatorOf(T : const Convertor)(auto ref T allocator) nothrow @nogc @safe { 861 import std.stdio; 862 863 return allocator; 864 } 865 866 /** 867 ditto 868 **/ 869 immutable(RCIAllocator) allocatorOf(T : immutable Convertor)(auto ref T allocator) nothrow @nogc @safe { 870 import std.stdio; 871 872 return allocator; 873 } 874 875 /** 876 ditto 877 **/ 878 RCIAllocator allocatorOf(T)(T object, RCIAllocator allocator) @trusted nothrow @nogc pure { 879 auto result = object.allocatorOf; 880 881 if (result.isNull) { 882 return allocator; 883 } 884 885 return result; 886 }