Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiplatform file resources (e.g read text/binary file) #637

Open
avdyushin opened this issue Jan 26, 2023 · 0 comments
Open

Multiplatform file resources (e.g read text/binary file) #637

avdyushin opened this issue Jan 26, 2023 · 0 comments
Labels
1.x.x expected somewhere in a future release proposal

Comments

@avdyushin
Copy link
Contributor

Is your feature request related to a problem? Please describe.
Very often (especially in unit tests) we need a big data samples to use (now it's in code as byte arrays).
It's good to have access to them from common code (including common tests).

As a first version we can do read-only mode.

Not sure if it belongs resources module or brand new separate one.

Describe the solution you'd like

Some ideas over interface:


sealed class FilePath(val path: String) 

expect class FileResource(
    path: FilePath
) {
    fun open()
    fun nextLine(): String?
    fun nextByte(): Byte?
    fun close()
}

private fun FileResource.lineSequence() = Sequence {
    iterator {
        while (true) {
            nextLine()?.let { yield(it) } ?: break
        }
    }
}

fun <T> FileResource.useLines(block: (Sequence<String>) -> T): T {
    open()
    return block(lineSequence()).also { close() }
}

Where FilePath will wrap/maintain path for platform(Android,iOS,Native) and location (commonMain/resources, commonTest/resource, etc)

Do I can easily use it like this:

FileResource(path).useLines { string ->
   // use next string from file
}

Similar way can be implemented to access single Byte (by having byte iterator)

JVM

And Android as well:

actual class FileResource actual constructor(path: FilePath) {

    private val file = File(path.path)
    private lateinit var iterator: Iterator<String>

    actual fun open() {
        iterator = file.readLines().iterator()
    }

    actual fun nextLine(): String? {
        if (!iterator.hasNext()) return null
        return iterator.next()
    }

    actual fun close() {
    }
}

Native

Probably can be used in darwinMain:

actual class FileResource actual constructor(private val path: FilePath) {

    private var file: CPointer<FILE>? = null

    actual fun open() {
        file = fopen(__filename = path.path, __mode = "r")
        ?: throw NullPointerException("Can't open file at path: <${path.path}>")
    }

    actual fun nextLine() = memScoped {
        val buffer: CPointer<ByteVar> = allocArray(MAX_BUFFER_SIZE)
        fgets(buffer, MAX_BUFFER_SIZE, file)?.toKString()?.trimEnd() // remove newline
    }

    actual fun close() {
        fclose(file)
    }
}

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

@avdyushin avdyushin added 1.x.x expected somewhere in a future release proposal labels Jan 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1.x.x expected somewhere in a future release proposal
Projects
None yet
Development

No branches or pull requests

1 participant