Created
November 11, 2021 11:58
-
-
Save realdadfish/ba3fc9ec49210a08dcd2c2700fd22a9f to your computer and use it in GitHub Desktop.
A trial to mimic "Type-driven design in Rust" (https://www.youtube.com/watch?v=bnnacleqg6k) with Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS") | |
interface ExactSizeIterator<T> : Iterator<T> { | |
val length: UInt | |
} | |
fun <T> Collection<T>.exactSizeIterator() = object : ExactSizeIterator<T> { | |
private val inner = iterator() | |
override val length: UInt = size.toUInt() | |
override fun hasNext(): Boolean = inner.hasNext() | |
override fun next(): T = inner.next() | |
} | |
sealed class Bounding { | |
object Unbounded : Bounding() | |
data class Bounded(val bound: UInt, val brackets: Pair<Char, Char>) : Bounding() | |
fun display(current: UInt) { | |
print("\\u001b[2K") | |
when (this) { | |
Unbounded -> print("*") | |
is Bounded -> { | |
print(brackets.first) | |
print("*".repeat(current.toInt())) | |
print(" ".repeat((bound - current).toInt())) | |
print(brackets.second) | |
} | |
} | |
} | |
} | |
class ProgressIter<I, T : Iterator<I>, B : Bounding>(internal val iterator: T, internal val bounding: B) : | |
Iterator<I> { | |
private var current: UInt = 1u | |
override fun hasNext(): Boolean = iterator.hasNext() | |
override fun next(): I { | |
bounding.display(current++) | |
return iterator.next() | |
} | |
} | |
fun <I> Sequence<I>.progressIterator(): ProgressIter<I, out Iterator<I>, Bounding.Unbounded> = | |
ProgressIter(iterator(), Bounding.Unbounded) | |
fun <I> Iterable<I>.progressIterator(): ProgressIter<I, out Iterator<I>, Bounding.Unbounded> = | |
when (this) { | |
is Collection<I> -> ProgressIter(exactSizeIterator(), Bounding.Unbounded) | |
else -> ProgressIter(iterator(), Bounding.Unbounded) | |
} | |
fun <I> ProgressIter<I, out Iterator<I>, Bounding.Unbounded>.withBound(): ProgressIter<I, ExactSizeIterator<I>, Bounding.Bounded> = | |
when (iterator) { | |
is ExactSizeIterator<I> -> ProgressIter(iterator, Bounding.Bounded(iterator.length, Pair('[', ']'))) | |
else -> error("no ExactSizeIterator") | |
} | |
fun <I> ProgressIter<I, ExactSizeIterator<I>, Bounding.Bounded>.withBrackets(brackets: Pair<Char, Char>): ProgressIter<I, ExactSizeIterator<I>, Bounding.Bounded> = | |
ProgressIter(iterator, bounding.copy(brackets = brackets)) | |
fun main() { | |
//val seq = generateSequence(1, Int::inc) | |
val seq = listOf(1, 2, 3, 4) | |
fun work(item: Int) { | |
Thread.sleep(1000) | |
} | |
for (i in seq.progressIterator().withBound().withBrackets(Pair('<', '>'))) { | |
work(i) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment