Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// *slurping noises*
- interface StringVacuum :
- OutputRange!string, OutputRange!wstring, OutputRange!dstring,
- OutputRange!char, OutputRange!wchar, OutputRange!dchar
- {
- void put(string plainText);
- void put(wstring plainText);
- void put(dstring plainText);
- void put(char oneChar);
- void put(wchar oneChar);
- void put(dchar oneChar);
- }
- /// Woof.
- struct DogType
- {
- string[4] whatAmI = ["I","am","a","dog"];
- /// The `stringize` method allows a type to convert itself to a string
- /// without forcing the caller to endure less-than-deterministic behavior
- /// such as GC allocations.
- ///
- /// How /actually/ @nogc this method /really is/ completely depends on
- /// the StringVacuum implementation that the caller supplies.
- ///
- /// Regardless, this type's author has already done their own due-diligence,
- /// and it is thus /possible/ to write an @nogc program that uses
- /// the DogType and requires the ability to convert DogTypes to strings.
- ///
- @nogc nothrow void stringize(return scope StringVacuum writer)
- {
- size_t i = 0;
- if ( i < whatAmI.length )
- writer.send(this.whatAmI[i++]);
- for(; i < whatAmI.length; i++ )
- {
- writer.send(" ");
- writer.send(this.whatAmI[i++];
- }
- }
- /+
- // The above is analagous to this:
- @property nothrow string toString() const
- {
- return whatAmI[0] ~" "~ whatAmI[1] ~" "~ whatAmI[2] ~" "~ whatAmI[3];
- }
- +/
- /+
- // But I'd really like to be able to derive .toString from .stringizer
- // by mixin template:
- mixin toString!(typeof(this));
- +/
- }
- /// A suboptimal-yet-convenient StringVacuum implementation that collects
- /// text from a type's `stringize` method and places it all into one
- /// GC-allocated string.
- class StringizationConcatenator : StringVacuum
- {
- private:
- import std.array;
- Appender!string contents_;
- public:
- @property pure const @nogc nothrow
- string contents() { return contents_.data; }
- this()
- {
- contents_ = appender!string();
- }
- void send(string plainText) { contents_.put(plainText); }
- void send(wstring plainText) { contents_.put(plainText); }
- void send(dstring plainText) { contents_.put(plainText); }
- void send(char oneChar) { contents_.put(oneChar); }
- void send(wchar oneChar) { contents_.put(oneChar); }
- void send(dchar oneChar) { contents_.put(oneChar); }
- }
- /// This template allows a type that implements the `stringize` method to
- /// get a `toString` method for free.
- ///
- /// After all, `stringize` is just a generalized version of `toString`.
- ///
- mixin template toString(T)
- {
- private import std.traits : FA = FunctionAttribute;
- // Generate a .toString method with SOME, but not ALL, of the function attributes
- // that the type's `stringize` method has.
- //
- // For example:
- // If T's `stringize` is nothrow, then this implies that the derived `toString` is nothrow.
- // If T's `stringize` is @nogc, then the derived `toString` is still NOT @nogc,
- // because StringizationConcatenator GC-allocates.
- //
- // (Also I'm pretty sure this won't compile, albeit I haven't tested it.
- // The below code is intended to express intent, not be a valid implementation.)
- //
- @property
- ...
- mixin(stringizeFunctionAttributes!(
- // This is a template that I haven't implemented yet. Does what the name suggests.
- getStringizeMethod!T,
- // Tentative list of attributes that get forwarded. Anything not here is not forwarded, ex: @nogc.
- FA.pure_ | FA.nothrow_ | FA.trusted | FA.safe | FA.system |
- FA.const_ | FA.shared_ | FA.live
- ))
- ...
- string toString()
- {
- // Body of our boilerplate toString method.
- scope vacuum = new StringizationConcatentator();
- this.stringize(vacuum);
- return vacuum.result;
- }
- }
- /// Creates a string of function attribute(s)
- /// that are found on the given `func`.
- /// Only attributes present in the `selectedAttrs`
- /// argument will be present in the resulting string;
- /// all others will be discarded.
- ///
- template stringizeFunctionAttributes(alias func, FunctionAttribute selectedAttrs)
- if (func.length == 1 && isCallable!func)
- {
- import std.array : join;
- import std.traits : functionAttributes, FunctionAttribute;
- alias FA = FunctionAttribute;
- FA attrs = functionAttributes!func & selectedAttrs;
- enum stringizeFunctionAttributes = [""
- , (attrs & FA.pure_ ? "pure" : "")
- , (attrs & FA.nothrow_ ? "nothrow" : "")
- , (attrs & FA.ref_ ? "ref" : "")
- , (attrs & FA.property ? "@property" : "")
- , (attrs & FA.trusted ? "@trusted" : "")
- , (attrs & FA.safe ? "@safe" : "")
- , (attrs & FA.nogc ? "@nogc" : "")
- , (attrs & FA.system ? "@system" : "")
- , (attrs & FA.const_ ? "const" : "")
- , (attrs & FA.immutable_ ? "immutable" : "")
- , (attrs & FA.inout_ ? "inout" : "")
- , (attrs & FA.shared_ ? "shared" : "")
- , (attrs & FA.return_ ? "return" : "")
- , (attrs & FA.scope_ ? "scope" : "")
- , (attrs & FA.live ? "@live" : "")
- ].join(" ");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement