import kotlin.reflect.KProperty inline fun BsonReader.read( prop1: KProperty, prop2: KProperty, noinline read1: BsonReader.(BsonType) -> T1, noinline read2: BsonReader.(BsonType) -> T2, create: (T1, T2) -> R ): R { readStartDocument() val name1 = prop1.encodedName val name2 = prop2.encodedName val val1: T1 = readProperty(name1, read1) val val2: T2 = readProperty(name2, read2) readEndDocument() return create(val1, val2) } tailrec fun BsonReader.readProperty( propName: String, read: BsonReader.(BsonType) -> T ): T { val type = readBsonType() if (type == BsonType.END_OF_DOCUMENT) error("could not find $propName in document") return when (val currentName = readName()) { propName -> read(type) "_id" -> { readObjectId() readProperty(propName, read) } else -> error("unknown field name: $currentName") } } //region dummy implementations val KProperty.encodedName get() = "" interface BsonReader enum class BsonType { END_OF_DOCUMENT } fun readBsonType(): BsonType {} fun readStartDocument(): BsonType {} fun readName(): String {} fun readObjectId(): String {} fun readEndDocument(): String {} //endregion