All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.apollographql.apollo.mockserver.multipart.kt Maven / Gradle / Ivy

package com.apollographql.apollo.mockserver

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.mapNotNull
import okio.Buffer
import okio.ByteString


private sealed interface Item
private class BytesItem(val bytes: ByteString): Item
private class DelayItem(val delayMillis: Long): Item

internal class MultipartBodyImpl(private val boundary: String, private val partsContentType: String) : MultipartBody {
  private var isFirst = true

  private val channel = Channel(Channel.UNLIMITED)

  internal fun consumeAsFlow(): Flow {
    return channel.consumeAsFlow().mapNotNull {
      when (it) {
        is DelayItem -> {
          delay(it.delayMillis)
          null
        }
        is BytesItem -> it.bytes
      }
    }.asChunked()
  }

  override fun enqueuePart(bytes: ByteString, isLast: Boolean) {

    val b = Buffer().apply {
      if (isFirst) {
        writeUtf8("--$boundary\r\n")
        isFirst = false
      }
      val endBoundary = if (isLast) "--$boundary--" else "--$boundary"

      writeUtf8("Content-Length: ${bytes.size}\r\n")
      writeUtf8("Content-Type: $partsContentType\r\n")
      writeUtf8("\r\n")
      write(bytes)
      writeUtf8("\r\n$endBoundary\r\n")
    }.readByteString()

    channel.trySend(BytesItem(b))
    if (isLast) {
      channel.close()
    }
  }

  override fun enqueueDelay(delayMillis: Long) {
    channel.trySend(DelayItem(delayMillis))
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy