WIP ROOT json serialization

This commit is contained in:
Alexander Nozik 2021-08-20 20:25:19 +03:00
parent a748282d63
commit 5d2c853cbe
11 changed files with 144 additions and 42 deletions

View File

@ -37,8 +37,7 @@ apiValidation {
} }
afterEvaluate { //workaround for https://youtrack.jetbrains.com/issue/KT-48273
extensions.configure<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension> { rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin::class.java) {
versions.webpackDevServer.version = "4.0.0" rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().versions.webpackDevServer.version = "4.0.0"
}
} }

View File

@ -1,25 +0,0 @@
package ru.mipt.npm.root
import kotlin.properties.PropertyDelegateProvider
import kotlin.reflect.KType
import kotlin.reflect.typeOf
public interface RootValueProvider {
/**
* Provide a member cast or reinterpreted to given type.
* Returns null if member with given name/type could not be resolved.
*/
public fun <T : Any> provideOrNull(name: String, type: KType): T?
}
public interface RootModel {
public val provider: RootValueProvider
}
public inline fun <reified T : Any> RootValueProvider.provide(name: String): T =
provideOrNull(name, typeOf<T>()) ?: error("A member with type ${T::class} and name $name could not be resolved")
public inline fun <reified T : Any> RootModel.member(name: String? = null): PropertyDelegateProvider<Any?, Lazy<T>> =
PropertyDelegateProvider { _, property ->
lazy { provider.provide(name ?: property.name) }
}

View File

@ -1,15 +1,19 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("TGeoMatrix")
public sealed class TGeoMatrix : TNamed() public sealed class TGeoMatrix : TNamed()
@Serializable @Serializable
@SerialName("TGeoIdentity")
public class TGeoIdentity : TGeoMatrix() public class TGeoIdentity : TGeoMatrix()
@Serializable @Serializable
@SerialName("TGeoHMatrix")
public class TGeoHMatrix( public class TGeoHMatrix(
public val fTranslation: DoubleArray, public val fTranslation: DoubleArray,
public val fRotationMatrix: DoubleArray, public val fRotationMatrix: DoubleArray,
@ -17,16 +21,19 @@ public class TGeoHMatrix(
) : TGeoMatrix() ) : TGeoMatrix()
@Serializable @Serializable
@SerialName("TGeoTranslation")
public class TGeoTranslation( public class TGeoTranslation(
public val fTranslation: DoubleArray public val fTranslation: DoubleArray
) : TGeoMatrix() ) : TGeoMatrix()
@Serializable @Serializable
@SerialName("TGeoRotation")
public class TGeoRotation( public class TGeoRotation(
public val fRotationMatrix: DoubleArray public val fRotationMatrix: DoubleArray
): TGeoMatrix() ): TGeoMatrix()
@Serializable @Serializable
@SerialName("TGeoCombiTrans")
public class TGeoCombiTrans( public class TGeoCombiTrans(
public val fTranslation: DoubleArray, public val fTranslation: DoubleArray,
public val fRotation: TGeoRotation? = null, public val fRotation: TGeoRotation? = null,

View File

@ -1,11 +1,18 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
@Serializable @Serializable
@SerialName("TGeoManager")
public class TGeoManager : TNamed() { public class TGeoManager : TNamed() {
public val fMatrices: TObjArray = TObjArray.empty public val fMatrices: TObjArray = TObjArray.empty
@ -22,17 +29,29 @@ public class TGeoManager : TNamed() {
public fun decodeFromJson(jsonObject: JsonObject): TGeoManager = TODO() public fun decodeFromJson(jsonObject: JsonObject): TGeoManager = TODO()
public fun decodeFromString(string: String): TGeoManager = public fun decodeFromString(string: String): TGeoManager =
RootJsonSerialFormat().decodeFromString(serializer(), string) Root().decodeFromString(serializer(), string)
} }
} }
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
private class RootJsonSerialFormat : StringFormat { private class RootJsonSerializer<T>(private val tSerializer: KSerializer<T>) : KSerializer<T> {
override val serializersModule: SerializersModule get() = json.serializersModule
private val refCache: HashMap<UInt, TObject> = HashMap() private val refCache: HashMap<UInt, TObject> = HashMap()
override val descriptor: SerialDescriptor get() = tSerializer.descriptor
override fun deserialize(decoder: Decoder): T {
val input = decoder as JsonDecoder
val element = input.decodeJsonElement()
return input.json.decodeFromJsonElement(tSerializer, transformDeserialize(element))
}
override fun serialize(encoder: Encoder, value: T) {
tSerializer.serialize(encoder, value)
}
override fun <T> decodeFromString(deserializer: DeserializationStrategy<T>, string: String): T { override fun <T> decodeFromString(deserializer: DeserializationStrategy<T>, string: String): T {
val match = refRegex.matchEntire(string) val match = refRegex.matchEntire(string)
return if (match != null) { return if (match != null) {
@ -41,7 +60,7 @@ private class RootJsonSerialFormat : StringFormat {
val refValue = refCache[ref] ?: error("Reference $ref unresolved") val refValue = refCache[ref] ?: error("Reference $ref unresolved")
refValue as T //TODO research means to make it safe refValue as T //TODO research means to make it safe
} else { } else {
val res = json.decodeFromString(deserializer, string) val res = rootJson.decodeFromString(deserializer, string)
val uid = (res as? TObject)?.fUniqueID val uid = (res as? TObject)?.fUniqueID
if (uid != null && refCache[uid] == null) { if (uid != null && refCache[uid] == null) {
refCache[uid] = res refCache[uid] = res
@ -50,17 +69,70 @@ private class RootJsonSerialFormat : StringFormat {
} }
} }
override fun <T> encodeToString(serializer: SerializationStrategy<T>, value: T): String = override fun <T> encodeToString(serializer: SerializationStrategy<T>, value: T): String =
json.encodeToString(serializer, value) rootJson.encodeToString(serializer, value)
companion object { companion object {
val refRegex = """\{\s*"${"\\$"}ref"\s*:\s*(\d*)}""".toRegex() val refRegex = """\{\s*"${"\\$"}ref"\s*:\s*(\d*)}""".toRegex()
val json: Json = Json { val rootSerializersModule = SerializersModule {
encodeDefaults = true polymorphic(TGeoShape::class) {
ignoreUnknownKeys = true subclass(TGeoBBox.serializer())
classDiscriminator = "_typename" subclass(TGeoCompositeShape.serializer())
subclass(TGeoXtru.serializer())
subclass(TGeoTube.serializer())
subclass(TGeoTubeSeg.serializer())
subclass(TGeoShapeAssembly.serializer())
}
polymorphic(TGeoMatrix::class) {
subclass(TGeoIdentity.serializer())
subclass(TGeoHMatrix.serializer())
subclass(TGeoTranslation.serializer())
subclass(TGeoRotation.serializer())
subclass(TGeoCombiTrans.serializer())
}
polymorphic(TObject::class) {
subclass(TGeoBBox.serializer())
subclass(TGeoCompositeShape.serializer())
subclass(TGeoXtru.serializer())
subclass(TGeoTube.serializer())
subclass(TGeoTubeSeg.serializer())
subclass(TGeoShapeAssembly.serializer())
subclass(TGeoIdentity.serializer())
subclass(TGeoHMatrix.serializer())
subclass(TGeoTranslation.serializer())
subclass(TGeoRotation.serializer())
subclass(TGeoCombiTrans.serializer())
subclass(TGeoMaterial.serializer())
subclass(TGeoMixture.serializer())
subclass(TGeoMedium.serializer())
subclass(TGeoNode.serializer())
subclass(TGeoNodeMatrix.serializer())
subclass(TGeoVolume.serializer())
subclass(TGeoVolumeAssembly.serializer())
}
polymorphic(TGeoNode::class, TGeoNode.serializer()) {
subclass(TGeoNodeMatrix.serializer())
}
polymorphic(TGeoVolume::class, TGeoVolume.serializer()) {
subclass(TGeoVolumeAssembly.serializer())
} }
} }
val rootJson: Json = Json {
encodeDefaults = true
ignoreUnknownKeys = true
classDiscriminator = "_typename"
serializersModule = rootSerializersModule
}
}
} }

View File

@ -1,9 +1,12 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("TGeoMaterial")
public open class TGeoMaterial: TNamed() public open class TGeoMaterial: TNamed()
@Serializable @Serializable
@SerialName("TGeoMixture")
public class TGeoMixture: TGeoMaterial() public class TGeoMixture: TGeoMaterial()

View File

@ -1,8 +1,10 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("TGeoMedium")
public class TGeoMedium( public class TGeoMedium(
public val fId : Int, public val fId : Int,
public val fMaterial: TGeoMaterial, public val fMaterial: TGeoMaterial,

View File

@ -1,9 +1,11 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
public class TGeoNode : TNamed() { @SerialName("TGeoNode")
public open class TGeoNode : TNamed() {
//val fGeoAtt: UInt //val fGeoAtt: UInt
public val fVolume: TGeoVolume? = null public val fVolume: TGeoVolume? = null
public val fMother: TGeoVolume? = null public val fMother: TGeoVolume? = null
@ -12,6 +14,8 @@ public class TGeoNode : TNamed() {
public val fOverlaps: IntArray = intArrayOf() public val fOverlaps: IntArray = intArrayOf()
} }
public class TGeoNodeMatrix : TGeoMatrix() { @Serializable
@SerialName("TGeoNodeMatrix")
public class TGeoNodeMatrix : TGeoNode() {
public val fMatrix: TGeoMatrix? = null public val fMatrix: TGeoMatrix? = null
} }

View File

@ -1,14 +1,17 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
public abstract class TGeoShape : TNamed() { @SerialName("TGeoShape")
public sealed class TGeoShape : TNamed() {
public val fShapeBits: UInt = 0u public val fShapeBits: UInt = 0u
public val fShapeId: Int = 0 public val fShapeId: Int = 0
} }
@Serializable @Serializable
@SerialName("TGeoBBox")
public open class TGeoBBox : TGeoShape() { public open class TGeoBBox : TGeoShape() {
public val fDX: Double = 0.0 public val fDX: Double = 0.0
public val fDY: Double = 0.0 public val fDY: Double = 0.0
@ -17,6 +20,7 @@ public open class TGeoBBox : TGeoShape() {
} }
@Serializable @Serializable
@SerialName("TGeoBoolNode")
public sealed class TGeoBoolNode : TObject() { public sealed class TGeoBoolNode : TObject() {
public abstract val fLeft: TGeoShape public abstract val fLeft: TGeoShape
public abstract val fLeftMat: TGeoMatrix public abstract val fLeftMat: TGeoMatrix
@ -25,6 +29,7 @@ public sealed class TGeoBoolNode : TObject() {
} }
@Serializable @Serializable
@SerialName("TGeoUnion")
public class TGeoUnion( public class TGeoUnion(
override val fLeft: TGeoShape, override val fLeft: TGeoShape,
override val fLeftMat: TGeoMatrix, override val fLeftMat: TGeoMatrix,
@ -33,6 +38,7 @@ public class TGeoUnion(
) : TGeoBoolNode() ) : TGeoBoolNode()
@Serializable @Serializable
@SerialName("TGeoSubtraction")
public class TGeoSubtraction( public class TGeoSubtraction(
override val fLeft: TGeoShape, override val fLeft: TGeoShape,
override val fLeftMat: TGeoMatrix, override val fLeftMat: TGeoMatrix,
@ -41,6 +47,7 @@ public class TGeoSubtraction(
) : TGeoBoolNode() ) : TGeoBoolNode()
@Serializable @Serializable
@SerialName("TGeoIntersection")
public class TGeoIntersection( public class TGeoIntersection(
override val fLeft: TGeoShape, override val fLeft: TGeoShape,
override val fLeftMat: TGeoMatrix, override val fLeftMat: TGeoMatrix,
@ -50,9 +57,11 @@ public class TGeoIntersection(
@Serializable @Serializable
@SerialName("TGeoCompositeShape")
public class TGeoCompositeShape(public val fNode: TGeoBoolNode) : TGeoBBox() public class TGeoCompositeShape(public val fNode: TGeoBoolNode) : TGeoBBox()
@Serializable @Serializable
@SerialName("TGeoXtru")
public class TGeoXtru( public class TGeoXtru(
public val fNvert: Int, public val fNvert: Int,
public val fNz: Int, public val fNz: Int,
@ -67,14 +76,33 @@ public class TGeoXtru(
@Serializable @Serializable
public class TGeoTube( @SerialName("TGeoTube")
public open class TGeoTube(
public val fRmin: Double, public val fRmin: Double,
public val fRmax: Double, public val fRmax: Double,
public val fDz: Double, public val fDz: Double,
) : TGeoBBox() ) : TGeoBBox()
@Serializable @Serializable
@SerialName("TGeoTubeSeg")
public class TGeoTubeSeg(
public val fRmin: Double,
public val fRmax: Double,
public val fDz: Double,
public val fPhi1: Double,
public val fPhi2: Double,
public val fS1: Double,
public val fC1: Double,
public val fS2: Double,
public val fC2: Double,
public val fSm: Double,
public val fCm: Double,
public val fCdfi: Double,
) : TGeoBBox()
@Serializable
@SerialName("TGeoShapeAssembly")
public class TGeoShapeAssembly( public class TGeoShapeAssembly(
public val fVolume: TGeoVolumeAssembly, public val fVolume: TGeoVolumeAssembly,
public val fBBoxOK: Boolean = true public val fBBoxOK: Boolean = true
): TGeoBBox() ) : TGeoBBox()

View File

@ -1,8 +1,10 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("TGeoVolume")
public open class TGeoVolume : TNamed(){ public open class TGeoVolume : TNamed(){
// "fGeoAtt" : 3084, // "fGeoAtt" : 3084,
// "fLineColor" : 3, // "fLineColor" : 3,
@ -19,4 +21,5 @@ public open class TGeoVolume : TNamed(){
} }
@Serializable @Serializable
@SerialName("TGeoVolumeAssembly")
public class TGeoVolumeAssembly : TGeoVolume() public class TGeoVolumeAssembly : TGeoVolume()

View File

@ -1,5 +1,6 @@
package ru.mipt.npm.root package ru.mipt.npm.root
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@ -15,6 +16,7 @@ public abstract class TNamed : TObject() {
} }
@Serializable @Serializable
@SerialName("TObjArray")
public class TObjArray(public val arr: List<TObject>){ public class TObjArray(public val arr: List<TObject>){
public companion object{ public companion object{
public val empty = TObjArray(emptyList()) public val empty = TObjArray(emptyList())

View File

@ -0,0 +1,7 @@
package ru.mipt.npm.root
fun main() {
val string = TGeoManager::class.java.getResourceAsStream("/BM@N.root.json")!!
.readAllBytes().decodeToString()
val geo = TGeoManager.decodeFromString(string)
}