/**
This module is a submodule of $(MREF std, range).

The main $(MREF std, range) module provides template-based tools for working with
ranges, but sometimes an object-based interface for ranges is needed, such as
when runtime polymorphism is required. For this purpose, this submodule
provides a number of object and $(D interface) definitions that can be used to
wrap around _range objects created by the $(MREF std, range) templates.

$(SCRIPT inhibitQuickIndex = 1;)
$(BOOKTABLE ,
    $(TR $(TD $(LREF InputRange))
        $(TD Wrapper for input ranges.
    ))
    $(TR $(TD $(LREF InputAssignable))
        $(TD Wrapper for input ranges with assignable elements.
    ))
    $(TR $(TD $(LREF ForwardRange))
        $(TD Wrapper for forward ranges.
    ))
    $(TR $(TD $(LREF ForwardAssignable))
        $(TD Wrapper for forward ranges with assignable elements.
    ))
    $(TR $(TD $(LREF BidirectionalRange))
        $(TD Wrapper for bidirectional ranges.
    ))
    $(TR $(TD $(LREF BidirectionalAssignable))
        $(TD Wrapper for bidirectional ranges with assignable elements.
    ))
    $(TR $(TD $(LREF RandomAccessFinite))
        $(TD Wrapper for finite random-access ranges.
    ))
    $(TR $(TD $(LREF RandomAccessAssignable))
        $(TD Wrapper for finite random-access ranges with assignable elements.
    ))
    $(TR $(TD $(LREF RandomAccessInfinite))
        $(TD Wrapper for infinite random-access ranges.
    ))
    $(TR $(TD $(LREF OutputRange))
        $(TD Wrapper for output ranges.
    ))
    $(TR $(TD $(LREF OutputRangeObject))
        $(TD Class that implements the $(D OutputRange) interface and wraps the
        $(D put) methods in virtual functions.
    $(TR $(TD $(LREF outputRangeObject))
        Convenience function for creating an $(D OutputRangeObject) with a base
        range of type R that accepts types E.
    ))
    $(TR $(TD $(LREF InputRangeObject))
        $(TD Class that implements the $(D InputRange) interface and wraps the
        input _range methods in virtual functions.
    ))
    $(TR $(TD $(LREF inputRangeObject))
        $(TD Convenience function for creating an $(D InputRangeObject)
        of the proper type.
    ))
    $(TR $(TD $(LREF MostDerivedInputRange))
        $(TD Returns the interface type that best matches the range.)
    ))
)


Source: $(PHOBOSSRC std/range/_interfaces.d)

License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).

Authors: $(HTTP erdani.com, Andrei Alexandrescu), David Simcha,
and Jonathan M Davis. Credit for some of the ideas in building this module goes
to $(HTTP fantascienza.net/leonardo/so/, Leonardo Maffi).
*/
module std.range.interfaces;

import std.meta;
import std.range.primitives;
import std.traits;

/**These interfaces are intended to provide virtual function-based wrappers
 * around input ranges with element type E.  This is useful where a well-defined
 * binary interface is required, such as when a DLL function or virtual function
 * needs to accept a generic range as a parameter. Note that
 * $(REF_ALTTEXT isInputRange, isInputRange, std, range, primitives)
 * and friends check for conformance to structural interfaces
 * not for implementation of these $(D interface) types.
 *
 * Limitations:
 *
 * These interfaces are not capable of forwarding $(D ref) access to elements.
 *
 * Infiniteness of the wrapped range is not propagated.
 *
 * Length is not propagated in the case of non-random access ranges.
 *
 * See_Also:
 * $(LREF inputRangeObject)
 */
interface InputRange(E) {
    ///
    @property E front();

    ///
    E moveFront();

    ///
    void popFront();

    ///
    @property bool empty();

    /* Measurements of the benefits of using opApply instead of range primitives
     * for foreach, using timings for iterating over an iota(100_000_000) range
     * with an empty loop body, using the same hardware in each case:
     *
     * Bare Iota struct, range primitives:  278 milliseconds
     * InputRangeObject, opApply:           436 milliseconds  (1.57x penalty)
     * InputRangeObject, range primitives:  877 milliseconds  (3.15x penalty)
     */

    /**$(D foreach) iteration uses opApply, since one delegate call per loop
     * iteration is faster than three virtual function calls.
     */
    int opApply(scope int delegate(E));

    /// Ditto
    int opApply(scope int delegate(size_t, E));

}

///
@safe unittest
{
    import std.algorithm.iteration : map;
    import std.range : iota;

    void useRange(InputRange!int range) {
        // Function body.
    }

    // Create a range type.
    auto squares = map!"a * a"(iota(10));

    // Wrap it in an interface.
    auto squaresWrapped = inputRangeObject(squares);

    // Use it.
    useRange(squaresWrapped);
}

/**Interface for a forward range of type $(D E).*/
interface ForwardRange(E) : InputRange!E {
    ///
    @property ForwardRange!E save();
}

/**Interface for a bidirectional range of type $(D E).*/
interface BidirectionalRange(E) : ForwardRange!(E) {
    ///
    @property BidirectionalRange!E save();

    ///
    @property E back();

    ///
    E moveBack();

    ///
    void popBack();
}

/**Interface for a finite random access range of type $(D E).*/
interface RandomAccessFinite(E) : BidirectionalRange!(E) {
    ///
    @property RandomAccessFinite!E save();

    ///
    E opIndex(size_t);

    ///
    E moveAt(size_t);

    ///
    @property size_t length();

    ///
    alias opDollar = length;

    // Can't support slicing until issues with requiring slicing for all
    // finite random access ranges are fully resolved.
    version (none)
    {
        ///
        RandomAccessFinite!E opSlice(size_t, size_t);
    }
}

/**Interface for an infinite random access range of type $(D E).*/
interface RandomAccessInfinite(E) : ForwardRange!E {
    ///
    E moveAt(size_t);

    ///
    @property RandomAccessInfinite!E save();

    ///
    E opIndex(size_t);
}

/**Adds assignable elements to InputRange.*/
interface InputAssignable(E) : InputRange!E {
    ///
    @property void front(E newVal);

    alias front = InputRange!E.front; // overload base interface method
}

@safe unittest
{
    static assert(isInputRange!(InputAssignable!int));
}

/**Adds assignable elements to ForwardRange.*/
interface ForwardAssignable(E) : InputAssignable!E, ForwardRange!E {
    ///
    @property ForwardAssignable!E save();
}

/**Adds assignable elements to BidirectionalRange.*/
interface BidirectionalAssignable(E) : ForwardAssignable!E, BidirectionalRange!E {
    ///
    @property BidirectionalAssignable!E save();

    ///
    @property void back(E newVal);
}

/**Adds assignable elements to RandomAccessFinite.*/
interface RandomFiniteAssignable(E) : RandomAccessFinite!E, BidirectionalAssignable!E {
    ///
    @property RandomFiniteAssignable!E save();

    ///
    void opIndexAssign(E val, size_t index);
}

/**Interface for an output range of type $(D E).  Usage is similar to the
 * $(D InputRange) interface and descendants.*/
interface OutputRange(E) {
    ///
    void put(E);
}

@safe unittest
{
    // 6973
    static assert(isOutputRange!(OutputRange!int, int));
}


// CTFE function that generates mixin code for one put() method for each
// type E.
private string putMethods(E...)()
{
    import std.conv : to;

    string ret;

    foreach (ti, Unused; E)
    {
        ret ~= "void put(E[" ~ to!string(ti) ~ "] e) { .put(_range, e); }";
    }

    return ret;
}

/**Implements the $(D OutputRange) interface for all types E and wraps the
 * $(D put) method for each type $(D E) in a virtual function.
 */
class OutputRangeObject(R, E...) : staticMap!(OutputRange, E) {
    // @BUG 4689:  There should be constraints on this template class, but
    // DMD won't let me put them in.
    private R _range;

    ///
    this(R range) {
        this._range = range;
    }

    mixin(putMethods!E());
}


/**Returns the interface type that best matches $(D R).*/
template MostDerivedInputRange(R)
if (isInputRange!(Unqual!R))
{
    private alias E = ElementType!R;

    static if (isRandomAccessRange!R)
    {
        static if (isInfinite!R)
        {
            alias MostDerivedInputRange = RandomAccessInfinite!E;
        }
        else static if (hasAssignableElements!R)
        {
            alias MostDerivedInputRange = RandomFiniteAssignable!E;
        }
        else
        {
            alias MostDerivedInputRange = RandomAccessFinite!E;
        }
    }
    else static if (isBidirectionalRange!R)
    {
        static if (hasAssignableElements!R)
        {
            alias MostDerivedInputRange = BidirectionalAssignable!E;
        }
        else
        {
            alias MostDerivedInputRange = BidirectionalRange!E;
        }
    }
    else static if (isForwardRange!R)
    {
        static if (hasAssignableElements!R)
        {
            alias MostDerivedInputRange = ForwardAssignable!E;
        }
        else
        {
            alias MostDerivedInputRange = ForwardRange!E;
        }
    }
    else
    {
        static if (hasAssignableElements!R)
        {
            alias MostDerivedInputRange = InputAssignable!E;
        }
        else
        {
            alias MostDerivedInputRange = InputRange!E;
        }
    }
}

/**Implements the most derived interface that $(D R) works with and wraps
 * all relevant range primitives in virtual functions.  If $(D R) is already
 * derived from the $(D InputRange) interface, aliases itself away.
 */
template InputRangeObject(R)
if (isInputRange!(Unqual!R))
{
    static if (is(R : InputRange!(ElementType!R)))
    {
        alias InputRangeObject = R;
    }
    else static if (!is(Unqual!R == R))
    {
        alias InputRangeObject = InputRangeObject!(Unqual!R);
    }
    else
    {

        ///
        class InputRangeObject : MostDerivedInputRange!(R) {
            private R _range;
            private alias E = ElementType!R;

            this(R range) {
                this._range = range;
            }

            @property E front() { return _range.front; }

            E moveFront() {
                return _range.moveFront();
            }

            void popFront() { _range.popFront(); }
            @property bool empty() { return _range.empty; }

            static if (isForwardRange!R)
            {
                @property typeof(this) save() {
                    return new typeof(this)(_range.save);
                }
            }

            static if (hasAssignableElements!R)
            {
                @property void front(E newVal) {
                    _range.front = newVal;
                }
            }

            static if (isBidirectionalRange!R)
            {
                @property E back() { return _range.back; }

                E moveBack() {
                    return _range.moveBack();
                }

                void popBack() { return _range.popBack(); }

                static if (hasAssignableElements!R)
                {
                    @property void back(E newVal) {
                        _range.back = newVal;
                    }
                }
            }

            static if (isRandomAccessRange!R)
            {
                E opIndex(size_t index) {
                    return _range[index];
                }

                E moveAt(size_t index) {
                    return _range.moveAt(index);
                }

                static if (hasAssignableElements!R)
                {
                    void opIndexAssign(E val, size_t index) {
                        _range[index] = val;
                    }
                }

                static if (!isInfinite!R)
                {
                    @property size_t length() {
                        return _range.length;
                    }

                    alias opDollar = length;

                    // Can't support slicing until all the issues with
                    // requiring slicing support for finite random access
                    // ranges are resolved.
                    version (none)
                    {
                        typeof(this) opSlice(size_t lower, size_t upper) {
                            return new typeof(this)(_range[lower .. upper]);
                        }
                    }
                }
            }

            // Optimization:  One delegate call is faster than three virtual
            // function calls.  Use opApply for foreach syntax.
            int opApply(scope int delegate(E) dg) {
                int res;

                for (auto r = _range; !r.empty; r.popFront())
                {
                    res = dg(r.front);
                    if (res) break;
                }

                return res;
            }

            int opApply(scope int delegate(size_t, E) dg) {
                int res;

                size_t i = 0;
                for (auto r = _range; !r.empty; r.popFront())
                {
                    res = dg(i, r.front);
                    if (res) break;
                    i++;
                }

                return res;
            }
        }
    }
}

/**Convenience function for creating an $(D InputRangeObject) of the proper type.
 * See $(LREF InputRange) for an example.
 */
InputRangeObject!R inputRangeObject(R)(R range)
if (isInputRange!R)
{
    static if (is(R : InputRange!(ElementType!R)))
    {
        return range;
    }
    else
    {
        return new InputRangeObject!R(range);
    }
}

/**Convenience function for creating an $(D OutputRangeObject) with a base range
 * of type $(D R) that accepts types $(D E).
*/
template outputRangeObject(E...) {

    ///
    OutputRangeObject!(R, E) outputRangeObject(R)(R range) {
        return new OutputRangeObject!(R, E)(range);
    }
}

///
@safe unittest
{
     import std.array;
     auto app = appender!(uint[])();
     auto appWrapped = outputRangeObject!(uint, uint[])(app);
     static assert(is(typeof(appWrapped) : OutputRange!(uint[])));
     static assert(is(typeof(appWrapped) : OutputRange!(uint)));
}

@system unittest
{
    import std.algorithm.comparison : equal;
    import std.array;
    import std.internal.test.dummyrange;

    static void testEquality(R)(iInputRange r1, R r2) {
        assert(equal(r1, r2));
    }

    auto arr = [1,2,3,4];
    RandomFiniteAssignable!int arrWrapped = inputRangeObject(arr);
    static assert(isRandomAccessRange!(typeof(arrWrapped)));
    //    static assert(hasSlicing!(typeof(arrWrapped)));
    static assert(hasLength!(typeof(arrWrapped)));
    arrWrapped[0] = 0;
    assert(arr[0] == 0);
    assert(arr.moveFront() == 0);
    assert(arr.moveBack() == 4);
    assert(arr.moveAt(1) == 2);

    foreach (elem; arrWrapped) {}
    foreach (i, elem; arrWrapped) {}

    assert(inputRangeObject(arrWrapped) is arrWrapped);

    foreach (DummyType; AllDummyRanges)
    {
        auto d = DummyType.init;
        static assert(propagatesRangeType!(DummyType,
                        typeof(inputRangeObject(d))));
        static assert(propagatesRangeType!(DummyType,
                        MostDerivedInputRange!DummyType));
        InputRange!uint wrapped = inputRangeObject(d);
        assert(equal(wrapped, d));
    }

    // Test output range stuff.
    auto app = appender!(uint[])();
    auto appWrapped = outputRangeObject!(uint, uint[])(app);
    static assert(is(typeof(appWrapped) : OutputRange!(uint[])));
    static assert(is(typeof(appWrapped) : OutputRange!(uint)));

    appWrapped.put(1);
    appWrapped.put([2, 3]);
    assert(app.data.length == 3);
    assert(equal(app.data, [1,2,3]));
}
