Unverified Commit 4c5ade59 authored by Harry Barber's avatar Harry Barber Committed by GitHub
Browse files

Add a join method for `Iterable<Writable>`, `Sequence<Writable>`, and `Array<Writable>` (#1716)

* Add join to Iterable, Sequence, and Array

* Change writable(w: String) to writeInline

* Add .join tests

* Improve documentation

* Address feedback

* Simplify rustTypeParameters
parent e0083877
Loading
Loading
Loading
Loading
+59 −24
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ typealias Writable = RustWriter.() -> Unit
 */
fun writable(w: Writable): Writable = w

fun writable(w: String): Writable = writable { rust(w) }
fun writable(w: String): Writable = writable { writeInline(w) }

fun Writable.isEmpty(): Boolean {
    val writer = RustWriter.root()
@@ -26,6 +26,46 @@ fun Writable.isEmpty(): Boolean {
    return writer.toString() == RustWriter.root().toString()
}

/**
 * Helper allowing a `Iterable<Writable>` to be joined together using a `String` separator.
 */
fun Iterable<Writable>.join(separator: String) = join(writable(separator))

/**
 * Helper allowing a `Iterable<Writable>` to be joined together using a `Writable` separator.
 */
fun Iterable<Writable>.join(separator: Writable): Writable {
    val iter = this.iterator()
    return writable {
        iter.forEach { value ->
            value()
            if (iter.hasNext()) {
                separator()
            }
        }
    }
}

/**
 * Helper allowing a `Sequence<Writable>` to be joined together using a `String` separator.
 */
fun Sequence<Writable>.join(separator: String) = asIterable().join(separator)

/**
 * Helper allowing a `Sequence<Writable>` to be joined together using a `Writable` separator.
 */
fun Sequence<Writable>.join(separator: Writable) = asIterable().join(separator)

/**
 * Helper allowing a `Array<Writable>` to be joined together using a `String` separator.
 */
fun Array<Writable>.join(separator: String) = asIterable().join(separator)

/**
 * Helper allowing a `Array<Writable>` to be joined together using a `Writable` separator.
 */
fun Array<Writable>.join(separator: Writable) = asIterable().join(separator)

/**
 * Combine multiple writable types into a Rust generic type parameter list
 *
@@ -51,11 +91,9 @@ fun rustTypeParameters(
    vararg typeParameters: Any,
): Writable = writable {
    if (typeParameters.isNotEmpty()) {
        rustInlineTemplate("<")

        val iterator: Iterator<Any> = typeParameters.iterator()
        while (iterator.hasNext()) {
            when (val typeParameter = iterator.next()) {
        val items = typeParameters.map { typeParameter ->
            writable {
                when (typeParameter) {
                    is Symbol, is RuntimeType, is RustType -> rustInlineTemplate("#{it}", "it" to typeParameter)
                    is String -> rustInlineTemplate(typeParameter)
                    is GenericsGenerator -> rustInlineTemplate(
@@ -72,12 +110,9 @@ fun rustTypeParameters(
                        }
                    }
                }

            if (iterator.hasNext()) {
                rustInlineTemplate(", ")
            }
        }

        rustInlineTemplate(">")
        rustInlineTemplate("<#{Items:W}>", "Items" to items.join(", "))
    }
}
+33 −0
Original line number Diff line number Diff line
@@ -75,4 +75,37 @@ internal class RustTypeParametersTest {

        writer.toString() shouldContain "'<()>'"
    }

    @Test
    fun `join iterable`() {
        val writer = RustWriter.forModule("model")
        val itemsA = listOf(writable("a"), writable("b"), writable("c")).join(", ")
        val itemsB = listOf(writable("d"), writable("e"), writable("f")).join(writable(", "))
        writer.rustTemplate("vec![#{ItemsA:W}, #{ItemsB:W}]", "ItemsA" to itemsA, "ItemsB" to itemsB)
        writer.toString() shouldContain "vec![a, b, c, d, e, f]"
    }

    @Test
    fun `join array`() {
        val writer = RustWriter.forModule("model")
        arrayOf(writable("A"), writable("B"), writable("C")).join("-")(writer)
        arrayOf(writable("D"), writable("E"), writable("F")).join(writable("+"))(writer)
        writer.toString() shouldContain "A-B-CD+E+F"
    }

    @Test
    fun `join sequence`() {
        val writer = RustWriter.forModule("model")
        sequence {
            yield(writable("A"))
            yield(writable("B"))
            yield(writable("C"))
        }.join("-")(writer)
        sequence {
            yield(writable("D"))
            yield(writable("E"))
            yield(writable("F"))
        }.join(writable("+"))(writer)
        writer.toString() shouldContain "A-B-CD+E+F"
    }
}