kotlinx-io-core

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

The module provides core multiplatform IO primitives and integrates it with platform-specific APIs.

kotlinx-io core aims to provide a concise but powerful API along with efficient implementation.

The main interfaces for the IO interaction are kotlinx.io.Source and kotlinx.io.Sink providing buffered read and write operations for integer types, byte arrays, and other sources and sinks. There are also extension functions bringing support for strings and other types. Implementations of these interfaces are built on top of kotlinx.io.Buffer, kotlinx.io.RawSource, and kotlinx.io.RawSink.

A central part of the library, kotlinx.io.Buffer, is a container optimized to reduce memory allocations and to avoid data copying when possible.

kotlinx.io.RawSource and kotlinx.io.RawSink are interfaces aimed for integration with anything that can provide or receive data: network interfaces, files, etc. The module provides integration with some platform-specific IO APIs, but if something not yet supported by the library needs to be integrated, then these interfaces are exactly what should be implemented for that.

Example below shows how to manually serialize an object to BSON and then back to an object using kotlinx.io. Please note that the example aimed to show kotlinx-io API in action, rather than to provide a robust BSON-serialization.

data class Message(val timestamp: Long, val text: String) {
companion object
}

fun Message.toBson(sink: Sink) {
val buffer = Buffer()
with (buffer) {
writeByte(0x9) // UTC-timestamp field
writeString("timestamp") // field name
writeByte(0)
writeLongLe(timestamp) // field value
writeByte(0x2) // string field
writeString("text") // field name
writeByte(0)
writeIntLe(text.utf8Size().toInt() + 1) // field value: length followed by the string
writeString(text)
writeByte(0)
writeByte(0) // end of BSON document
}

// Write document length and then its body
sink.writeIntLe(buffer.size.toInt() + 4)
buffer.transferTo(sink)
sink.flush()
}

fun Message.Companion.fromBson(source: Source): Message {
source.require(4) // check if the source contains length
val length = source.readIntLe() - 4L
source.require(length) // check if the source contains the whole message

fun readFieldName(source: Source): String {
val delimiterOffset = source.indexOf(0) // find offset of the 0-byte terminating the name
check(delimiterOffset >= 0) // indexOf return -1 if value not found
val fieldName = source.readString(delimiterOffset) // read the string until terminator
source.skip(1) // skip the terminator
return fieldName
}

// for simplicity, let's assume that the order of fields matches serialization order
var tag = source.readByte().toInt() // read the field type
check(tag == 0x9 && readFieldName(source) == "timestamp")
val timestamp = source.readLongLe() // read long value
tag = source.readByte().toInt()
check(tag == 0x2 && readFieldName(source) == "text")
val textLen = source.readIntLe() - 1L // read string length (it includes the terminator)
val text = source.readString(textLen) // read value
source.skip(1) // skip terminator
source.skip(1) // skip end of the document
return Message(timestamp, text)
}

Packages

Link copied to clipboard
apple
common
js
native

Core IO primitives.

Link copied to clipboard
apple
common
native
nativeNonApple
nodeFilesystemShared