Mark Vogel
08/23/2023, 5:30 PMinline fun <T1, T2, R> BsonReader.read(
prop1: KProperty<T1>, read1: BsonReader.(BsonType) -> T1,
prop2: KProperty<T2>, read2: BsonReader.(BsonType) -> T2,
create: (T1, T2) -> R
): R {
readStartDocument()
val name1 = prop1.encodedName
val name2 = prop2.encodedName
var val1: T1
var val2: T2
var readVal1 = false
var readVal2 = false
var type = readBsonType()
while (type != BsonType.END_OF_DOCUMENT) {
when (val name = readName()) {
name1 -> { val1 = read1(type); readVal1 = true }
name2 -> { val2 = read2(type); readVal2 = true }
"_id" -> readObjectId()
else -> error("unknown field name: $name")
}
type = readBsonType()
}
readEndDocument()
require(readVal1) { "no value for $name1" }
require(readVal2) { "no value for $name2" }
return create(val1, val2) // Error: variable must be initialized
}
At the end of the function I know that the variable was initialized, but the compiler can't pick that up.
I can't make the variable nullable otherwise I will have to do a null assertion and the point is to allow the generics to be nullable at the source
Does anyone know of a way to assert that the val1
and val2
are initialized to the compiler?
The only thing I've been able to think of is trying to pass the variables into Java code, but it seems really clunky to try that if that'd even workAdam S
08/23/2023, 6:32 PMread()
and early-return the value. If it reaches END_OF_DOCUMENT, then throw an exception - "property $propName was not found". This way, you handle the three cases:
1. the property is found and the value is not null,
2. the property is found and the value is null,
3. the property isn't found (throw an exception)Adam S
08/23/2023, 6:38 PMMark Vogel
08/23/2023, 8:41 PMval2
before val1
and just throw an exceptionMark Vogel
08/23/2023, 10:47 PMMark Vogel
08/23/2023, 10:47 PMAdam S
08/24/2023, 9:15 AMI could possible read all of the valuesAhh yeah, that could work. I assumed that it would be too heavy to load the whole document into memory, but actually that's not true. Also, you could only retain values for the specified keys.
Mark Vogel
08/24/2023, 6:37 PMinline fun <T1, T2, R> BsonReader.read(
prop1: KProperty<T1>, read1: BsonReader.(BsonType) -> T1,
prop2: KProperty<T2>, read2: BsonReader.(BsonType) -> T2,
create: (T1, T2) -> R
): R {
readStartDocument()
val name1 = prop1.encodedName
val name2 = prop2.encodedName
val values = BsonValues<T1, T2>()
var type = readBsonType()
while (type != BsonType.END_OF_DOCUMENT) {
when (val name = readName()) {
name1 -> values.val1 = read1(type)
name2 -> values.val2 = read2(type)
"_id" -> readObjectId()
else -> error("unknown field name: $name")
}
type = readBsonType()
}
readEndDocument()
require(values.is1Set) { "no value for $name1" }
require(values.is2Set) { "no value for $name2" }
return create(values.val1, values.val2)
}
Sucks to go against the Kotlin system, but it's the only way to maintain full functionality that I could see