From 0a121d9d19fd689a1d8d37ce75a51934942039a0 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 13 Nov 2018 08:29:51 +0100 Subject: [PATCH] Disable length when taking from a lengthless range Fix #79. --- source/tanya/algorithm/iteration.d | 23 ++++++++++-- source/tanya/meta/trait.d | 2 + source/tanya/test/range.d | 59 ++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 source/tanya/test/range.d diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d index 8a3686b..a66e980 100644 --- a/source/tanya/algorithm/iteration.d +++ b/source/tanya/algorithm/iteration.d @@ -23,6 +23,7 @@ module tanya.algorithm.iteration; import tanya.algorithm.comparison; import tanya.algorithm.mutation; import tanya.range; +version (unittest) import tanya.test.range; private struct Take(R, bool exactly) { @@ -73,13 +74,16 @@ private struct Take(R, bool exactly) } else { - return length == 0 || this.source.empty; + return this.length_ == 0 || this.source.empty; } } - @property size_t length() + static if (exactly || hasLength!R) { - return this.length_; + @property size_t length() + { + return this.length_; + } } static if (hasAssignableElements!R) @@ -315,6 +319,19 @@ if (isInputRange!R) assert(t.empty); } +// length is unknown when taking from a range without length +@nogc nothrow pure @safe unittest +{ + @Empty + static struct R + { + mixin InputRange; + } + auto actual = take(R(), 100); + + static assert(!hasLength!(typeof(actual))); +} + /** * Takes exactly $(D_PARAM n) elements from $(D_PARAM range). * diff --git a/source/tanya/meta/trait.d b/source/tanya/meta/trait.d index 81b2127..5ecb234 100644 --- a/source/tanya/meta/trait.d +++ b/source/tanya/meta/trait.d @@ -1493,6 +1493,8 @@ if (F.length == 1) } /** + * Determines whether $(D_PARAM T) defines a symbol $(D_PARAM member). + * * Params: * T = Aggregate type. * member = Symbol name. diff --git a/source/tanya/test/range.d b/source/tanya/test/range.d new file mode 100644 index 0000000..92a8c05 --- /dev/null +++ b/source/tanya/test/range.d @@ -0,0 +1,59 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Range generators for tests. + + * Copyright: Eugene Wissner 2018. + * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, + * Mozilla Public License, v. 2.0). + * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) + * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/test/range.d, + * tanya/test/range.d) + */ +module tanya.test.range; + +package(tanya) struct Empty +{ +} + +package(tanya) template InputRange() +{ + import tanya.meta.metafunction : AliasSeq; + + private alias attributes = AliasSeq!(__traits(getAttributes, typeof(this))); + + static foreach (attribute; attributes) + { + static if (is(attribute == Empty)) + { + @property bool empty() const @nogc nothrow pure @safe + { + return true; + } + } + } + + void popFront() @nogc nothrow pure @safe + { + static foreach (attribute; attributes) + { + static if (is(attribute == Empty)) + { + assert(false); + } + } + } + + int front() @nogc nothrow pure @safe + { + static foreach (attribute; attributes) + { + static if (is(attribute == Empty)) + { + assert(false); + } + } + } +}