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

Add extensions to improve out-of-box experiences #1458

Closed
Omico opened this issue Mar 18, 2024 · 4 comments
Closed

Add extensions to improve out-of-box experiences #1458

Omico opened this issue Mar 18, 2024 · 4 comments

Comments

@Omico
Copy link

Omico commented Mar 18, 2024

Hi, I am just wondering if we could add something like the below to improve out-of-box experiences.

For example (incomplete)

@Throws(IOException::class)
public inline fun Path.exists(): Boolean = FileSystem.SYSTEM.exists(this)

@Throws(IOException::class)
public inline fun Path.notExists(): Boolean = FileSystem.SYSTEM.exists(this).not()

public inline val Path.metadata: FileMetadata
    @Throws(IOException::class)
    get() = FileSystem.SYSTEM.metadata(this)

public inline val Path.isRegularFile: Boolean
    @Throws(IOException::class)
    get() = metadata.isRegularFile

public inline val Path.isDirectory: Boolean
    @Throws(IOException::class)
    get() = metadata.isDirectory

@Throws(IOException::class)
public inline fun Path.createDirectory(mustCreate: Boolean = false): Unit =
    FileSystem.SYSTEM.createDirectory(this, mustCreate)

@Throws(IOException::class)
public inline fun Path.createDirectories(mustCreate: Boolean = false): Unit =
    FileSystem.SYSTEM.createDirectories(this, mustCreate)

@Throws(IOException::class)
public inline fun Path.delete(mustExist: Boolean = false): Unit = FileSystem.SYSTEM.delete(this, mustExist)

@Throws(IOException::class)
public inline fun Path.list(): List<Path> = FileSystem.SYSTEM.list(this)

@Throws(IOException::class)
public fun Path.listOrNull(): List<Path>? = FileSystem.SYSTEM.listOrNull(this)

@Throws(IOException::class)
public fun Path.listRecursively(followSymlinks: Boolean = false): Sequence<Path> =
    FileSystem.SYSTEM.listRecursively(this, followSymlinks)

@Throws(IOException::class)
public inline fun <T> Path.read(readerAction: BufferedSource.() -> T): T = FileSystem.SYSTEM.read(this, readerAction)

@Throws(IOException::class)
public inline fun Path.readUtf8(): String = read(BufferedSource::readUtf8)

@Throws(IOException::class)
public inline fun <T> Path.write(mustCreate: Boolean = false, writerAction: BufferedSink.() -> T): T =
    FileSystem.SYSTEM.write(this, mustCreate, writerAction)

@Throws(IOException::class)
public inline fun Path.writeUtf8(content: String, mustCreate: Boolean = false): BufferedSink =
    write(mustCreate) { writeUtf8(content) }
@JakeWharton
Copy link
Member

JakeWharton commented Mar 18, 2024

The ones for file system (they're all for file system)

These fundamentally undermine a principle of the design which is that code is agnostic to the actual FileSystem with which it's interacting. More concretely, using these extensions (in a library, say) breaks my ability to use the contents of a zip without extracting. Or files in an Android app's asset directory. Or files that live on a remote machine like AWS S3 bucket.

With Kotlin's upcoming context parameter language feature, it's possible that the FileSystem context could become implicitly propagated rather than implicitly. Until then, accepting a FileSystem anywhere you accept a Path is the correct design pattern.

@JakeWharton JakeWharton closed this as not planned Won't fix, can't repro, duplicate, stale Mar 18, 2024
@JakeWharton
Copy link
Member

You can use extensions like these in your project so long as you're not a library. If you're a library, and you accept a Path from a user, you really must also accept a FileSystem or you break a bunch of use cases.

If you are in an application that only uses the system FileSystem then these are relatively safe.

@Omico
Copy link
Author

Omico commented Mar 18, 2024

If you are in an application that only uses the system FileSystem then these are relatively safe.

Yes, that's why I call it "out-of-box experiences." Because I only want to call the system FileSystem, it would be best if Okio could provide some extensions for JVM (including Android) and native platforms.

What I am asking is, indeed, for the upper layer. We can achieve this by placing it in different source sets, instead let users write again and again.

@JakeWharton
Copy link
Member

I think we're stuck waiting for context parameters where we don't need to choose between convenient-but-inflexible and verbose-but-flexible. We explicitly do not want to make it easier to implicitly introduce a static dependency on the system file system that makes code harder to test and less flexible in the library case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants