WIP root unref
This commit is contained in:
parent
1b2d61008f
commit
64e084dc53
@ -1,29 +1,19 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.JsonElement
|
|
||||||
import kotlinx.serialization.json.decodeFromJsonElement
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoManager")
|
@SerialName("TGeoManager")
|
||||||
public class TGeoManager : TNamed() {
|
public class TGeoManager : TNamed() {
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public val fMatrices: TObjArray = TObjArray.empty
|
public val fMatrices: TObjArray = TObjArray.empty
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public val fShapes: TObjArray = TObjArray.empty
|
public val fShapes: TObjArray = TObjArray.empty
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public val fVolumes: TObjArray = TObjArray.empty
|
public val fVolumes: TObjArray = TObjArray.empty
|
||||||
|
|
||||||
|
|
||||||
public companion object {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load Json encoded TGeoManager
|
|
||||||
*/
|
|
||||||
public fun decodeFromJson(jsonElement: JsonElement): TGeoManager =
|
|
||||||
rootJson().decodeFromJsonElement(jsonElement)
|
|
||||||
|
|
||||||
public fun decodeFromString(string: String): TGeoManager =
|
|
||||||
rootJson().decodeFromString(serializer(), string)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@ -30,11 +31,12 @@ public class TGeoTranslation(
|
|||||||
@SerialName("TGeoRotation")
|
@SerialName("TGeoRotation")
|
||||||
public class TGeoRotation(
|
public class TGeoRotation(
|
||||||
public val fRotationMatrix: DoubleArray
|
public val fRotationMatrix: DoubleArray
|
||||||
): TGeoMatrix()
|
) : TGeoMatrix()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoCombiTrans")
|
@SerialName("TGeoCombiTrans")
|
||||||
public class TGeoCombiTrans(
|
public class TGeoCombiTrans(
|
||||||
public val fTranslation: DoubleArray,
|
public val fTranslation: DoubleArray,
|
||||||
|
@Contextual
|
||||||
public val fRotation: TGeoRotation? = null,
|
public val fRotation: TGeoRotation? = null,
|
||||||
): TGeoMatrix()
|
) : TGeoMatrix()
|
@ -1,12 +1,14 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoMedium")
|
@SerialName("TGeoMedium")
|
||||||
public class TGeoMedium(
|
public class TGeoMedium(
|
||||||
public val fId : Int,
|
public val fId: Int,
|
||||||
|
@Contextual
|
||||||
public val fMaterial: TGeoMaterial,
|
public val fMaterial: TGeoMaterial,
|
||||||
public val fParams: DoubleArray
|
public val fParams: DoubleArray
|
||||||
): TNamed()
|
) : TNamed()
|
@ -1,5 +1,6 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@ -7,7 +8,10 @@ import kotlinx.serialization.Serializable
|
|||||||
@SerialName("TGeoNode")
|
@SerialName("TGeoNode")
|
||||||
public open class TGeoNode : TNamed() {
|
public open class TGeoNode : TNamed() {
|
||||||
//val fGeoAtt: UInt
|
//val fGeoAtt: UInt
|
||||||
|
@Contextual
|
||||||
public val fVolume: TGeoVolume? = null
|
public val fVolume: TGeoVolume? = null
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public val fMother: TGeoVolume? = null
|
public val fMother: TGeoVolume? = null
|
||||||
public val fNumber: Int = 0
|
public val fNumber: Int = 0
|
||||||
public val fNovlp: Int = 0
|
public val fNovlp: Int = 0
|
||||||
@ -17,5 +21,6 @@ public open class TGeoNode : TNamed() {
|
|||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoNodeMatrix")
|
@SerialName("TGeoNodeMatrix")
|
||||||
public class TGeoNodeMatrix : TGeoNode() {
|
public class TGeoNodeMatrix : TGeoNode() {
|
||||||
|
@Contextual
|
||||||
public val fMatrix: TGeoMatrix? = null
|
public val fMatrix: TGeoMatrix? = null
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@ -22,36 +23,55 @@ public open class TGeoBBox : TGeoShape() {
|
|||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoBoolNode")
|
@SerialName("TGeoBoolNode")
|
||||||
public sealed class TGeoBoolNode : TObject() {
|
public sealed class TGeoBoolNode : TObject() {
|
||||||
|
@Contextual
|
||||||
public abstract val fLeft: TGeoShape
|
public abstract val fLeft: TGeoShape
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public abstract val fLeftMat: TGeoMatrix
|
public abstract val fLeftMat: TGeoMatrix
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public abstract val fRight: TGeoShape
|
public abstract val fRight: TGeoShape
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public abstract val fRightMat: TGeoMatrix
|
public abstract val fRightMat: TGeoMatrix
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoUnion")
|
@SerialName("TGeoUnion")
|
||||||
public class TGeoUnion(
|
public class TGeoUnion(
|
||||||
|
@Contextual
|
||||||
override val fLeft: TGeoShape,
|
override val fLeft: TGeoShape,
|
||||||
|
@Contextual
|
||||||
override val fLeftMat: TGeoMatrix,
|
override val fLeftMat: TGeoMatrix,
|
||||||
|
@Contextual
|
||||||
override val fRight: TGeoShape,
|
override val fRight: TGeoShape,
|
||||||
|
@Contextual
|
||||||
override val fRightMat: TGeoMatrix
|
override val fRightMat: TGeoMatrix
|
||||||
) : TGeoBoolNode()
|
) : TGeoBoolNode()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoSubtraction")
|
@SerialName("TGeoSubtraction")
|
||||||
public class TGeoSubtraction(
|
public class TGeoSubtraction(
|
||||||
|
@Contextual
|
||||||
override val fLeft: TGeoShape,
|
override val fLeft: TGeoShape,
|
||||||
|
@Contextual
|
||||||
override val fLeftMat: TGeoMatrix,
|
override val fLeftMat: TGeoMatrix,
|
||||||
|
@Contextual
|
||||||
override val fRight: TGeoShape,
|
override val fRight: TGeoShape,
|
||||||
|
@Contextual
|
||||||
override val fRightMat: TGeoMatrix
|
override val fRightMat: TGeoMatrix
|
||||||
) : TGeoBoolNode()
|
) : TGeoBoolNode()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoIntersection")
|
@SerialName("TGeoIntersection")
|
||||||
public class TGeoIntersection(
|
public class TGeoIntersection(
|
||||||
|
@Contextual
|
||||||
override val fLeft: TGeoShape,
|
override val fLeft: TGeoShape,
|
||||||
|
@Contextual
|
||||||
override val fLeftMat: TGeoMatrix,
|
override val fLeftMat: TGeoMatrix,
|
||||||
|
@Contextual
|
||||||
override val fRight: TGeoShape,
|
override val fRight: TGeoShape,
|
||||||
|
@Contextual
|
||||||
override val fRightMat: TGeoMatrix
|
override val fRightMat: TGeoMatrix
|
||||||
) : TGeoBoolNode()
|
) : TGeoBoolNode()
|
||||||
|
|
||||||
@ -103,6 +123,7 @@ public class TGeoTubeSeg(
|
|||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoShapeAssembly")
|
@SerialName("TGeoShapeAssembly")
|
||||||
public class TGeoShapeAssembly(
|
public class TGeoShapeAssembly(
|
||||||
|
@Contextual
|
||||||
public val fVolume: TGeoVolumeAssembly,
|
public val fVolume: TGeoVolumeAssembly,
|
||||||
public val fBBoxOK: Boolean = true
|
public val fBBoxOK: Boolean = true
|
||||||
) : TGeoBBox()
|
) : TGeoBBox()
|
@ -1,20 +1,30 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoVolume")
|
@SerialName("TGeoVolume")
|
||||||
public open class TGeoVolume : TNamed(){
|
public open class TGeoVolume : TNamed() {
|
||||||
// "fGeoAtt" : 3084,
|
// "fGeoAtt" : 3084,
|
||||||
// "fLineColor" : 3,
|
// "fLineColor" : 3,
|
||||||
// "fLineStyle" : 1,
|
// "fLineStyle" : 1,
|
||||||
// "fLineWidth" : 1,
|
// "fLineWidth" : 1,
|
||||||
// "fFillColor" : 19,
|
// "fFillColor" : 19,
|
||||||
// "fFillStyle" : 1001,
|
// "fFillStyle" : 1001,
|
||||||
|
@Contextual
|
||||||
public lateinit var fNodes: TObjArray
|
public lateinit var fNodes: TObjArray
|
||||||
|
internal set
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public lateinit var fShape: TGeoShape
|
public lateinit var fShape: TGeoShape
|
||||||
|
internal set
|
||||||
|
|
||||||
|
@Contextual
|
||||||
public lateinit var fMedium: TGeoMedium
|
public lateinit var fMedium: TGeoMedium
|
||||||
|
internal set
|
||||||
|
|
||||||
public val fNumber: Int = 1
|
public val fNumber: Int = 1
|
||||||
public val fNtotal: Int = 1
|
public val fNtotal: Int = 1
|
||||||
public val fRefCount: Int = 1
|
public val fRefCount: Int = 1
|
||||||
|
@ -10,15 +10,23 @@ public abstract class TObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
public abstract class TNamed : TObject() {
|
public open class TNamed : TObject() {
|
||||||
public val fName: String = ""
|
public val fName: String = ""
|
||||||
public val fTitle: String = ""
|
public val fTitle: String = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TObjArray")
|
@SerialName("TObjArray")
|
||||||
public class TObjArray(public val arr: List<TObject>){
|
public class TObjArray(public val arr: List<TObject>): TObject() {
|
||||||
public companion object{
|
public companion object{
|
||||||
public val empty = TObjArray(emptyList())
|
public val empty: TObjArray = TObjArray(emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("TList")
|
||||||
|
public class TList(public val arr: List<TObject>): TObject()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("THashList")
|
||||||
|
public class THashList(public val arr: List<TObject>): TObject()
|
@ -1,107 +1,223 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.DeserializationStrategy
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import kotlinx.serialization.modules.PolymorphicModuleBuilder
|
import kotlinx.serialization.modules.*
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
import kotlin.reflect.KClass
|
||||||
import kotlinx.serialization.modules.polymorphic
|
|
||||||
import kotlinx.serialization.modules.subclass
|
|
||||||
|
|
||||||
|
|
||||||
private typealias RefCache = MutableList<TObject>
|
/**
|
||||||
|
* Load Json encoded TObject
|
||||||
|
*/
|
||||||
|
public fun TObject.Companion.decodeFromJson(serializer: KSerializer<out TObject>, jsonElement: JsonElement): TObject =
|
||||||
|
RootDecoder.decode(serializer, jsonElement)
|
||||||
|
|
||||||
private class RootJsonSerializer<T : TObject>(
|
public fun TObject.Companion.decodeFromString(serializer: KSerializer<out TObject>, string: String): TObject {
|
||||||
private val refCache: RefCache,
|
val json = RootDecoder.json.parseToJsonElement(string)
|
||||||
private val tSerializer: KSerializer<T>
|
return RootDecoder.decode(serializer, json)
|
||||||
) : KSerializer<T> {
|
}
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor get() = tSerializer.descriptor
|
private object RootDecoder {
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): T {
|
private class RootUnrefSerializer<T>(
|
||||||
val input = decoder as JsonDecoder
|
private val tSerializer: KSerializer<T>,
|
||||||
val element = input.decodeJsonElement()
|
private val refCache: MutableList<RefEntry>,// = ArrayList<RefEntry>(4096)
|
||||||
val refId = (element as? JsonObject)?.get("\$ref")?.jsonPrimitive?.int
|
private val counter: ReferenceCounter
|
||||||
return if (refId != null) {
|
) : KSerializer<T> by tSerializer {
|
||||||
//Do unref
|
|
||||||
val refValue = refCache[refId]
|
override fun deserialize(decoder: Decoder): T {
|
||||||
refValue as T //TODO research means to make it safe
|
val input = decoder as JsonDecoder
|
||||||
} else {
|
val element = input.decodeJsonElement()
|
||||||
val res = input.json.decodeFromJsonElement(tSerializer, element)
|
val refId = (element as? JsonObject)?.get("\$ref")?.jsonPrimitive?.int
|
||||||
//val uid = res.fUniqueID
|
val ref = if (refId != null) {
|
||||||
refCache.add(res)
|
//Do unref
|
||||||
res
|
refCache[refId]
|
||||||
|
} else {
|
||||||
|
refCache[counter.value].also {
|
||||||
|
counter.increment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ref.value(tSerializer) as T //TODO research means to make it safe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: T) {
|
private fun <T> KSerializer<T>.unref(refCache: MutableList<RefEntry>, counter: ReferenceCounter): KSerializer<T> =
|
||||||
tSerializer.serialize(encoder, value)
|
RootUnrefSerializer(this, refCache, counter)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
fun unrefSerializersModule(
|
||||||
|
refCache: MutableList<RefEntry>, counter: ReferenceCounter
|
||||||
|
): SerializersModule = SerializersModule {
|
||||||
|
val collector = this
|
||||||
|
val unrefCollector = object : SerializersModuleCollector {
|
||||||
|
|
||||||
|
override fun <T : Any> contextual(
|
||||||
|
kClass: KClass<T>,
|
||||||
|
provider: (typeArgumentsSerializers: List<KSerializer<*>>) -> KSerializer<*>
|
||||||
|
) {
|
||||||
|
collector.contextual(kClass) { provider(it).unref(refCache, counter) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <Base : Any, Sub : Base> polymorphic(
|
||||||
|
baseClass: KClass<Base>,
|
||||||
|
actualClass: KClass<Sub>,
|
||||||
|
actualSerializer: KSerializer<Sub>
|
||||||
|
) {
|
||||||
|
collector.polymorphic(baseClass, actualClass, actualSerializer.unref(refCache, counter))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <Base : Any> polymorphicDefault(
|
||||||
|
baseClass: KClass<Base>,
|
||||||
|
defaultSerializerProvider: (className: String?) -> DeserializationStrategy<out Base>?
|
||||||
|
) {
|
||||||
|
collector.polymorphicDefault(baseClass) {
|
||||||
|
(defaultSerializerProvider(it) as KSerializer<out Base>).unref(refCache, counter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serializersModule.dumpTo(unrefCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Create an instance of Json with unfolding Root references. This instance could not be reused because of the cache.
|
||||||
private fun <T : TObject> KSerializer<T>.unref(refCache: RefCache): RootJsonSerializer<T> =
|
*/
|
||||||
RootJsonSerializer(refCache, this)
|
private fun unrefJson(refCache: MutableList<RefEntry>, counter: ReferenceCounter): Json = Json {
|
||||||
|
|
||||||
|
|
||||||
private fun PolymorphicModuleBuilder<TGeoShape>.shapes(refCache: RefCache) {
|
|
||||||
subclass(TGeoBBox.serializer().unref(refCache))
|
|
||||||
subclass(TGeoCompositeShape.serializer().unref(refCache))
|
|
||||||
subclass(TGeoXtru.serializer().unref(refCache))
|
|
||||||
subclass(TGeoTube.serializer().unref(refCache))
|
|
||||||
subclass(TGeoTubeSeg.serializer().unref(refCache))
|
|
||||||
subclass(TGeoShapeAssembly.serializer().unref(refCache))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun PolymorphicModuleBuilder<TGeoMatrix>.matrices(refCache: RefCache) {
|
|
||||||
subclass(TGeoIdentity.serializer().unref(refCache))
|
|
||||||
subclass(TGeoHMatrix.serializer().unref(refCache))
|
|
||||||
subclass(TGeoTranslation.serializer().unref(refCache))
|
|
||||||
subclass(TGeoRotation.serializer().unref(refCache))
|
|
||||||
subclass(TGeoCombiTrans.serializer().unref(refCache))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of Json with unfolding Root references. This instance could not be reused because of the cache.
|
|
||||||
*/
|
|
||||||
internal fun rootJson(): Json {
|
|
||||||
val refCache = ArrayList<TObject>(4096)
|
|
||||||
return Json {
|
|
||||||
encodeDefaults = true
|
encodeDefaults = true
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
classDiscriminator = "_typename"
|
classDiscriminator = "_typename"
|
||||||
serializersModule = SerializersModule {
|
serializersModule = unrefSerializersModule(refCache, counter)
|
||||||
polymorphic(TGeoShape::class) {
|
}
|
||||||
default { TGeoBBox.serializer().unref(refCache) }
|
|
||||||
shapes(refCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphic(TGeoMatrix::class) {
|
|
||||||
matrices(refCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphic(TObject::class) {
|
fun decode(sourceDeserializer: KSerializer<out TObject>, source: JsonElement): TObject {
|
||||||
shapes(refCache)
|
val counter = ReferenceCounter()
|
||||||
matrices(refCache)
|
val refCache = ArrayList<RefEntry>()
|
||||||
|
|
||||||
subclass(TGeoMaterial.serializer().unref(refCache))
|
fun fillCache(element: JsonElement) {
|
||||||
subclass(TGeoMixture.serializer().unref(refCache))
|
when (element) {
|
||||||
|
is JsonObject -> {
|
||||||
subclass(TGeoMedium.serializer().unref(refCache))
|
if (element["_typename"] != null) {
|
||||||
|
refCache.add(RefEntry(element))
|
||||||
subclass(TGeoNode.serializer().unref(refCache))
|
}
|
||||||
subclass(TGeoNodeMatrix.serializer().unref(refCache))
|
element.values.forEach {
|
||||||
subclass(TGeoVolume.serializer().unref(refCache))
|
fillCache(it)
|
||||||
subclass(TGeoVolumeAssembly.serializer().unref(refCache))
|
}
|
||||||
}
|
}
|
||||||
polymorphic(TGeoNode::class, TGeoNode.serializer().unref(refCache)) {
|
is JsonArray -> {
|
||||||
subclass(TGeoNodeMatrix.serializer().unref(refCache))
|
element.forEach {
|
||||||
}
|
fillCache(it)
|
||||||
polymorphic(TGeoVolume::class, TGeoVolume.serializer().unref(refCache)) {
|
}
|
||||||
subclass(TGeoVolumeAssembly.serializer().unref(refCache))
|
}
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fillCache(source)
|
||||||
|
|
||||||
|
return unrefJson(refCache, counter).decodeFromJsonElement(sourceDeserializer.unref(refCache, counter), source)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ReferenceCounter(var value: Int = 0) {
|
||||||
|
fun increment() {
|
||||||
|
value += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = value.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
class RefEntry(val obj: JsonObject) {
|
||||||
|
|
||||||
|
private var cachedValue: Any? = null
|
||||||
|
|
||||||
|
fun value(serializer: KSerializer<*>): Any {
|
||||||
|
if (cachedValue == null) {
|
||||||
|
cachedValue = json.decodeFromJsonElement(serializer, obj)
|
||||||
|
}
|
||||||
|
return cachedValue!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = obj.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PolymorphicModuleBuilder<TGeoShape>.shapes() {
|
||||||
|
subclass(TGeoBBox.serializer())
|
||||||
|
subclass(TGeoCompositeShape.serializer())
|
||||||
|
subclass(TGeoXtru.serializer())
|
||||||
|
subclass(TGeoTube.serializer())
|
||||||
|
subclass(TGeoTubeSeg.serializer())
|
||||||
|
subclass(TGeoShapeAssembly.serializer())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PolymorphicModuleBuilder<TGeoMatrix>.matrices() {
|
||||||
|
subclass(TGeoIdentity.serializer())
|
||||||
|
subclass(TGeoHMatrix.serializer())
|
||||||
|
subclass(TGeoTranslation.serializer())
|
||||||
|
subclass(TGeoRotation.serializer())
|
||||||
|
subclass(TGeoCombiTrans.serializer())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PolymorphicModuleBuilder<TGeoBoolNode>.boolNodes() {
|
||||||
|
subclass(TGeoIntersection.serializer())
|
||||||
|
subclass(TGeoUnion.serializer())
|
||||||
|
subclass(TGeoSubtraction.serializer())
|
||||||
|
}
|
||||||
|
|
||||||
|
private val serializersModule = SerializersModule {
|
||||||
|
contextual(TGeoManager::class) { TGeoManager.serializer() }
|
||||||
|
contextual(TObjArray::class) { TObjArray.serializer() }
|
||||||
|
contextual(TGeoVolumeAssembly::class) { TGeoVolumeAssembly.serializer() }
|
||||||
|
contextual(TGeoShapeAssembly::class) { TGeoShapeAssembly.serializer() }
|
||||||
|
contextual(TGeoRotation::class) { TGeoRotation.serializer() }
|
||||||
|
contextual(TGeoMedium::class) { TGeoMedium.serializer() }
|
||||||
|
|
||||||
|
polymorphic(TGeoShape::class) {
|
||||||
|
default { TGeoBBox.serializer() }
|
||||||
|
shapes()
|
||||||
|
}
|
||||||
|
|
||||||
|
polymorphic(TGeoMatrix::class) {
|
||||||
|
matrices()
|
||||||
|
}
|
||||||
|
|
||||||
|
polymorphic(TGeoBoolNode::class) {
|
||||||
|
boolNodes()
|
||||||
|
}
|
||||||
|
|
||||||
|
polymorphic(TObject::class) {
|
||||||
|
subclass(TObjArray.serializer())
|
||||||
|
|
||||||
|
shapes()
|
||||||
|
matrices()
|
||||||
|
boolNodes()
|
||||||
|
|
||||||
|
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 json = Json {
|
||||||
|
encodeDefaults = true
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
classDiscriminator = "_typename"
|
||||||
|
serializersModule = this@RootDecoder.serializersModule
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,31 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.*
|
||||||
|
|
||||||
|
private fun JsonElement.countTypes(): Sequence<String> = sequence {
|
||||||
|
val json = this@countTypes
|
||||||
|
when (json){
|
||||||
|
is JsonObject -> {
|
||||||
|
json["_typename"]?.let { yield(it.jsonPrimitive.content) }
|
||||||
|
json.values.forEach { yieldAll(it.countTypes()) }
|
||||||
|
}
|
||||||
|
is JsonArray -> {
|
||||||
|
json.forEach {
|
||||||
|
yieldAll(it.countTypes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val string = TGeoManager::class.java.getResourceAsStream("/BM@N.root.json")!!
|
val string = TGeoManager::class.java.getResourceAsStream("/BM@N.root.json")!!
|
||||||
.readAllBytes().decodeToString()
|
.readAllBytes().decodeToString()
|
||||||
val geo = TGeoManager.decodeFromString(string)
|
val json = Json.parseToJsonElement(string)
|
||||||
|
val sizes = json.countTypes().groupBy { it }.mapValues { it.value.size }
|
||||||
|
sizes.forEach {
|
||||||
|
println(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val geo = TObject.decodeFromString(TGeoManager.serializer(), string)
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user