Skip to content

Streaming data to XML parser #6

@msasikanth

Description

@msasikanth

Hi, I currently use this library in my RSS reader app called Twine. One of the missing things was the ability to stream data to the parser or parse data in chunks rather than loading the entire string into memory. This was causing OOM crashes when there are large strings

Since I receive response as a ByteReadChannel from the Ktor client, I converted it into CharIterator and parsed data in chunks. So far it works well for me in my testing.

I wanted to share my approach, get your thoughts on it, and leave it to anyone looking to do this.

private fun ByteReadChannel.toCharIterator(
  context: CoroutineContext = EmptyCoroutineContext
): CharIterator {
  return object : CharIterator() {

    private val DEFAULT_BUFFER_SIZE = 1024L

    private var currentIndex = 0
    private var currentBuffer = CharArray(0)

    override fun hasNext(): Boolean {
      if (currentIndex < currentBuffer.size) return true
      if (this@toCharIterator.isClosedForRead) return false

      val packet = runBlocking(context) {
        this@toCharIterator.readRemaining(DEFAULT_BUFFER_SIZE)
      }
      currentBuffer = packet.readText().toCharArray()
      packet.release()
      currentIndex = 0
      return currentBuffer.isNotEmpty()
    }

    override fun nextChar(): Char {
      if (!hasNext()) throw NoSuchElementException()
      return currentBuffer[currentIndex++]
    }
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions