diff --git a/build.gradle.kts b/build.gradle.kts index d0725f9d1b8..9b5cf318b5c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -99,6 +99,12 @@ val enablePythonFrontend: Boolean by extra { } project.logger.lifecycle("Python frontend is ${if (enablePythonFrontend) "enabled" else "disabled"}") +val enableRustFrontend: Boolean by extra { + val enableRustFrontend: String? by project + enableRustFrontend.toBoolean() +} +project.logger.lifecycle("Rust frontend is ${if (enableRustFrontend) "enabled" else "disabled"}") + val enableLLVMFrontend: Boolean by extra { val enableLLVMFrontend: String? by project enableLLVMFrontend.toBoolean() diff --git a/buildSrc/src/main/kotlin/cpg.frontend-dependency-conventions.gradle.kts b/buildSrc/src/main/kotlin/cpg.frontend-dependency-conventions.gradle.kts index 812bbd98555..6cca9664baa 100644 --- a/buildSrc/src/main/kotlin/cpg.frontend-dependency-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/cpg.frontend-dependency-conventions.gradle.kts @@ -10,6 +10,7 @@ val enablePythonFrontend: Boolean by rootProject.extra val enableLLVMFrontend: Boolean by rootProject.extra val enableTypeScriptFrontend: Boolean by rootProject.extra val enableRubyFrontend: Boolean by rootProject.extra +val enableRustFrontend: Boolean by rootProject.extra val enableJVMFrontend: Boolean by rootProject.extra val enableINIFrontend: Boolean by rootProject.extra @@ -38,6 +39,9 @@ dependencies { if (enableRubyFrontend) { implementation(project(":cpg-language-ruby")) } + if (enableRustFrontend) { + implementation(project(":cpg-language-rust")) + } if (enableINIFrontend) { implementation(project(":cpg-language-ini")) } diff --git a/configure_frontends.sh b/configure_frontends.sh index 8ff8627683e..476d3811ab5 100755 --- a/configure_frontends.sh +++ b/configure_frontends.sh @@ -52,6 +52,8 @@ answerGo=$(ask "Do you want to enable the Go frontend? (currently $(getProperty setProperty "enableGoFrontend" $answerGo answerPython=$(ask "Do you want to enable the Python frontend? (currently $(getProperty "enablePythonFrontend"))") setProperty "enablePythonFrontend" $answerPython +answerRust=$(ask "Do you want to enable the Rust frontend? (currently $(getProperty "enableRustFrontend"))") +setProperty "enableRustFrontend" $answerRust answerLLVM=$(ask "Do you want to enable the LLVM frontend? (currently $(getProperty "enableLLVMFrontend"))") setProperty "enableLLVMFrontend" $answerLLVM answerTypescript=$(ask "Do you want to enable the TypeScript frontend? (currently $(getProperty "enableTypeScriptFrontend"))") diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/ExpressionBuilder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/ExpressionBuilder.kt index f17cb5e501b..eea5b5e17e0 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/ExpressionBuilder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/ExpressionBuilder.kt @@ -610,6 +610,51 @@ fun MetadataProvider.newThrow(rawNode: Any? = null): Throw { return node } +/** + * Creates a new [ObjectDeconstruction]. The [MetadataProvider] receiver will be used to fill + * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin + * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional + * prepended argument. + */ +@JvmOverloads +fun MetadataProvider.newObjectDeconstruction(rawNode: Any? = null): ObjectDeconstruction { + val node = ObjectDeconstruction() + node.applyMetadata(this, EMPTY_NAME, rawNode, true) + + log(node) + return node +} + +/** + * Creates a new [NamedDeconstruction]. The [MetadataProvider] receiver will be used to fill + * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin + * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional + * prepended argument. + */ +@JvmOverloads +fun MetadataProvider.newNamedDeconstruction(rawNode: Any? = null): NamedDeconstruction { + val node = NamedDeconstruction() + node.applyMetadata(this, EMPTY_NAME, rawNode, true) + + log(node) + return node +} + +/** + * Creates a new [AlternativeDeconstruction]. The [MetadataProvider] receiver will be used to fill + * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin + * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional + * prepended argument. + */ +@JvmOverloads +fun MetadataProvider.newAlternativeDeconstruction(rawNode: Any? = null): AlternativeDeconstruction { + val node = AlternativeDeconstruction() + node.applyMetadata(this, EMPTY_NAME, rawNode, true) + + log(node) + return node +} + /** * Creates a new [ProblemExpression]. The [MetadataProvider] receiver will be used to fill different * meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin requires diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ExtensionDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ExtensionDeclaration.kt new file mode 100644 index 00000000000..b803abf0f66 --- /dev/null +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ExtensionDeclaration.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.graph.declarations + +import de.fraunhofer.aisec.cpg.graph.DeclarationHolder +import de.fraunhofer.aisec.cpg.graph.Node +import de.fraunhofer.aisec.cpg.graph.edges.ast.astEdgesOf +import de.fraunhofer.aisec.cpg.graph.edges.unwrapping +import java.util.Objects + +/** + * Children in this declaration are added to an existing node with namespace. This can be a Record, + * or another similar construct that contains declarations. The children are therefore in this ast + * construct but are added to the symbol table of the construct it is extending. + * + * The name that this extension has needs to identify the construct, it is extending + */ +class ExtensionDeclaration : Declaration(), DeclarationHolder { + /** + * Edges to nested namespaces, records, functions, fields etc. contained in the current + * namespace. + */ + val declarationEdges = astEdgesOf() + override val declarations by unwrapping(ExtensionDeclaration::declarationEdges) + + /** + * In some languages, there is a relationship between paths / directories and the package + * structure. Therefore, we need to be aware of the path this namespace / package is in. + */ + var path: String? = null + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is ExtensionDeclaration) return false + return super.equals(other) && declarations == other.declarations + } + + override fun hashCode() = Objects.hash(super.hashCode(), declarations) + + override fun addDeclaration(declaration: Declaration) { + addIfNotContains(declarations, declaration) + } + + override fun getStartingPrevEOG(): Collection { + return setOf() + } + + override fun getExitNextEOG(): Collection { + return setOf() + } +} diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/AlternativeDeconstruction.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/AlternativeDeconstruction.kt new file mode 100644 index 00000000000..8329542b2bd --- /dev/null +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/AlternativeDeconstruction.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.graph.expressions + +import de.fraunhofer.aisec.cpg.graph.ArgumentHolder +import de.fraunhofer.aisec.cpg.graph.edges.ast.astEdgesOf +import de.fraunhofer.aisec.cpg.graph.edges.unwrapping +import de.fraunhofer.aisec.cpg.graph.types.HasType +import de.fraunhofer.aisec.cpg.graph.types.Type +import de.fraunhofer.aisec.cpg.persistence.Relationship +import java.util.Objects +import kotlin.collections.plusAssign + +class AlternativeDeconstruction : Deconstruction(), ArgumentHolder, HasType.TypeObserver { + + @Relationship("ALTERNATIVES") var alternativeEdges = astEdgesOf() + var alternatives by unwrapping(AlternativeDeconstruction::alternativeEdges) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is AlternativeDeconstruction) return false + return super.equals(other) && alternatives == other.alternatives + } + + override fun hashCode() = Objects.hash(super.hashCode(), alternatives) + + override fun addArgument(expression: Expression) { + this.alternatives += expression + expression.access = this.access + } + + override fun replaceArgument(old: Expression, new: Expression): Boolean { + val idx = alternativeEdges.indexOfFirst { it.end == old } + if (idx != -1) { + old.unregisterTypeObserver(this) + alternativeEdges[idx].end = new + new.registerTypeObserver(this) + new.access = this.access + return true + } + + return false + } + + override fun hasArgument(expression: Expression): Boolean { + return expression in this.alternatives + } + + override fun typeChanged(newType: Type, src: HasType) { + val type = type + typeObservers.forEach { it.typeChanged(type, this) } + } + + override fun assignedTypeChanged(assignedTypes: Set, src: HasType) { + addAssignedTypes(assignedTypes) + typeObservers.forEach { it.assignedTypeChanged(assignedTypes, this) } + } +} diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/Break.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/Break.kt index 5f5f9075d2e..9143361da92 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/Break.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/Break.kt @@ -26,6 +26,11 @@ package de.fraunhofer.aisec.cpg.graph.expressions import de.fraunhofer.aisec.cpg.graph.Node +import de.fraunhofer.aisec.cpg.graph.edges.ast.astOptionalEdgeOf +import de.fraunhofer.aisec.cpg.graph.edges.unwrapping +import de.fraunhofer.aisec.cpg.graph.types.HasType +import de.fraunhofer.aisec.cpg.graph.types.Type +import de.fraunhofer.aisec.cpg.persistence.Relationship import java.util.Objects /** @@ -33,20 +38,46 @@ import java.util.Objects * context. Can have a loop label, e.g. in Java, to specify which of the nested loops should be * broken out of. */ -class Break : Expression(false) { +class Break : Expression(false), HasType.TypeObserver { /** Specifies the label of the loop in a nested structure that this statement will 'break' */ var label: String? = null + @Relationship("EXPR") + var exprEdge = + astOptionalEdgeOf( + onChanged = { old, new -> exchangeTypeObserverWithAccessPropagation(old, new) } + ) + /** The expression on which the operation is applied. */ + var expr by unwrapping(Break::exprEdge) + override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is Break) return false - return super.equals(other) && label == other.label + return super.equals(other) && label == other.label && expr == other.expr } - override fun hashCode() = Objects.hash(super.hashCode(), label) + override fun hashCode() = Objects.hash(super.hashCode(), label, expr) override fun getStartingPrevEOG(): Collection { return this.prevEOG } + + override fun typeChanged(newType: Type, src: HasType) { + if (src != expr) { + return + } + + this.type = newType + } + + override fun assignedTypeChanged(assignedTypes: Set, src: HasType) { + // Only accept type changes from out input + if (src != expr) { + return + } + + // Apply our operator to all assigned types and forward them to us + this.addAssignedTypes(assignedTypes) + } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/Deconstruction.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/Deconstruction.kt new file mode 100644 index 00000000000..52806db7809 --- /dev/null +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/Deconstruction.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.graph.expressions + +abstract class Deconstruction : Expression() diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/NamedDeconstruction.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/NamedDeconstruction.kt new file mode 100644 index 00000000000..c1ea9c7a353 --- /dev/null +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/NamedDeconstruction.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.graph.expressions + +import de.fraunhofer.aisec.cpg.graph.ArgumentHolder +import de.fraunhofer.aisec.cpg.graph.edges.ast.astEdgeOf +import de.fraunhofer.aisec.cpg.graph.edges.unwrapping +import de.fraunhofer.aisec.cpg.persistence.Relationship +import java.util.Objects + +class NamedDeconstruction : Deconstruction(), ArgumentHolder { + + @Relationship("VALUE") var valueEdge = astEdgeOf(ProblemExpression("missing value")) + + /** + * The value that is decomposed into, i.e. a variable the named member is bound to, or further + * decompositions. + */ + var value by unwrapping(NamedDeconstruction::valueEdge) + + override fun addArgument(expression: Expression) { + if (value is ProblemExpression) { + value = expression + } + } + + override fun replaceArgument(old: Expression, new: Expression): Boolean { + if (value == old) { + value = new + return true + } + + return false + } + + override fun hasArgument(expression: Expression): Boolean { + return value == expression + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is KeyValue) return false + return super.equals(other) && value == other.value + } + + override fun hashCode() = Objects.hash(super.hashCode(), value) +} diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/ObjectDeconstruction.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/ObjectDeconstruction.kt new file mode 100644 index 00000000000..c63c7c9dc87 --- /dev/null +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/expressions/ObjectDeconstruction.kt @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.graph.expressions + +import de.fraunhofer.aisec.cpg.graph.ArgumentHolder +import de.fraunhofer.aisec.cpg.graph.edges.ast.astEdgesOf +import de.fraunhofer.aisec.cpg.graph.edges.unwrapping +import de.fraunhofer.aisec.cpg.graph.types.HasType +import de.fraunhofer.aisec.cpg.graph.types.Type +import de.fraunhofer.aisec.cpg.persistence.Relationship +import java.util.Objects + +/** + * Deconstructs an object of a specified type, if the [components] are [NamedDeconstruction], the + * name will define how deconstruction is done, i.e. data flows based on names, if not it will be + * done based on position. + */ +class ObjectDeconstruction : Deconstruction(), ArgumentHolder, HasType.TypeObserver { + @Relationship("COMPONENTS") var componentEdges = astEdgesOf() + var components by unwrapping(ObjectDeconstruction::componentEdges) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is ObjectDeconstruction) return false + return super.equals(other) && components == other.components + } + + override fun hashCode() = Objects.hash(super.hashCode(), components) + + override fun addArgument(expression: Expression) { + this.components += expression + expression.access = this.access + } + + override fun replaceArgument(old: Expression, new: Expression): Boolean { + val idx = componentEdges.indexOfFirst { it.end == old } + if (idx != -1) { + old.unregisterTypeObserver(this) + componentEdges[idx].end = new + new.registerTypeObserver(this) + new.access = this.access + return true + } + + return false + } + + override fun hasArgument(expression: Expression): Boolean { + return expression in this.components + } + + override fun typeChanged(newType: Type, src: HasType) { + val type = type + // Todo if my type changes i need to forward these changes to my `children`. Here Type + // deconstruction + // works inversely to expression evaluation. + } + + override fun assignedTypeChanged(assignedTypes: Set, src: HasType) { + addAssignedTypes(assignedTypes) + // Todo if my type changes i need to forward these changes to my `children`. Here Type + // deconstruction + // works inversely to expression evaluation. + } +} diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt index 547b7531e8c..f1621bb43b5 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt @@ -33,6 +33,7 @@ import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.declarations.Function import de.fraunhofer.aisec.cpg.graph.edges.flows.* import de.fraunhofer.aisec.cpg.graph.expressions.* +import de.fraunhofer.aisec.cpg.graph.types.ObjectType import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker.IterativeGraphWalker import de.fraunhofer.aisec.cpg.helpers.Util import de.fraunhofer.aisec.cpg.passes.configuration.DependsOn @@ -156,6 +157,9 @@ open class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { is Function -> handleFunction(node, functionSummaries) is Tuple -> handleTuple(node) is Variable -> handleVariable(node) + is ObjectDeconstruction -> handleObjectDeconstruction(node) + is AlternativeDeconstruction -> handleAlternativeDeconstruction(node) + is NamedDeconstruction -> handleNamedDeconstruction(node) } } @@ -369,6 +373,7 @@ open class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { * statement is mutually exclusive. */ protected fun handleSwitch(node: Switch) { + if (node.usedAsExpression) { node.statement?.let { node.prevDFGEdges += it @@ -684,10 +689,40 @@ open class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { */ protected fun handleDeclarationStatement(node: DeclarationStatement) { if (node.usedAsExpression) { + + val inDeconstruction = + node.astParent?.let { parent -> node.prevDFG.contains(parent) } ?: false + node.declarations.forEach { - if (it is ValueDeclaration) { - it.astChildren.filterIsInstance().lastOrNull()?.let { - node.prevDFGEdges += it + if (it is Variable) { + // Expression case: + // [parent: Expression] -> [DeclarationStatement] <- [Initializer] -> [Variable] + // ^-- [children: + // Expression] + // If the parent of the declaration Statement is a Deconstruction, the dfg needs + // to go from the + // declaration statement to the initializer of the variable, because the + // initializer potentially + // deconstructs the variable further. The DFG handling for variables should + // naturally draw a DFG + // edge from the initializer to the variable, creating a path to properly bind + // the value to the + // variable that goes over the deconstruction that may hold type information. + // [parent: Deconstruction] -> [DeclarationStatement] -> [Initializer] -> + // [Variable] + // '--> + // [children: Deconstruction] + // Todo: what happens if there are nested bindings that i would depict as + // declaration statements with + // variables and their initializers are declarations statements? + + // The default for the dfg targets are the initializers + val dfgTarget = it.initializer ?: it + // If there is no initializer, the variable is the target + if (inDeconstruction) { + node.nextDFGEdges += dfgTarget + } else { + node.prevDFGEdges += dfgTarget } } } @@ -701,7 +736,9 @@ open class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { } protected fun handleBreak(node: Break) { - // no action + if (node.usedAsExpression) { + node.expr?.let { node.prevDFGEdges += it } + } } protected fun handleAssert(node: Assert) { @@ -735,4 +772,51 @@ open class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { breaksOfNode.forEach { node.prevDFGEdges += it } } } + + protected fun handleObjectDeconstruction(node: ObjectDeconstruction) { + // If this Deconstruction has no incoming DFG, the data comes from the previously evaluated + // node, e.g. the switch or initializer + if (node.prevDFG.isEmpty()) { + node.prevEOG.forEach { node.prevDFGEdges += it } + } + + node.components.forEach { + node.nextDFGEdges.add(it) { + granularity = + if (node.components.size == 1) full() + else if (it is NamedDeconstruction) + getField(node, it)?.let { field(it) } ?: indexed(it.name.toString()) + else indexed(node.components.indexOf(it)) + } + } + } + + fun getField( + objectDeconstruction: ObjectDeconstruction, + namedDeconstruction: NamedDeconstruction, + ): Field? { + val type = objectDeconstruction.type + if (type is ObjectType) { + return type.recordDeclaration.fields.firstOrNull { it.name == namedDeconstruction.name } + } + return null + } + + protected fun handleAlternativeDeconstruction(node: AlternativeDeconstruction) { + // If this Deconstruction has no incoming DFG, the data comes from the previously evaluated + // node, e.g. the switch or initializer + if (node.prevDFG.isEmpty()) { + node.prevEOG.forEach { node.prevDFGEdges += it } + } + node.alternatives.forEach { node.nextDFGEdges += it } + } + + protected fun handleNamedDeconstruction(node: NamedDeconstruction) { + // If this Deconstruction has no incoming DFG, the data comes from the previously evaluated + // node, e.g. the switch or initializer + if (node.prevDFG.isEmpty()) { + node.prevEOG.forEach { node.prevDFGEdges += it } + } + node.value.let { node.nextDFGEdges += it } + } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt index 01c1e08f11f..8cb427a7d6e 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt @@ -423,6 +423,9 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa is Import -> handleDefault(node) // These nodes are not added to the EOG is Include -> doNothing() + is ObjectDeconstruction -> handleObjectDeconstruction(node) + is NamedDeconstruction -> handleNamedDeconstruction(node) + is AlternativeDeconstruction -> handleAlternativeDeconstruction(node) else -> LOGGER.info("Parsing of type ${node.javaClass} is not supported (yet)") } } @@ -847,6 +850,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa * See [Specification for Break](https://fraunhofer-aisec.github.io/cpg/CPG/specs/eog/#break) */ protected fun handleBreak(node: Break) { + node.expr?.let { handleEOG(it) } attachToEOG(node) val label = node.label val breakableNode = @@ -1270,6 +1274,45 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa attachToEOG(node) } + /** + * See + * [Specification for ObjectDeconstruction](https://fraunhofer-aisec.github.io/cpg/CPG/specs/eog/#ObjectDeconstruction) + * + * Note that we model Deconstructions in the inverse order than you may be used for other + * expressions. First the root node is evaluated, and then the children, as we walk down during + * the decomposition process. + */ + protected fun handleObjectDeconstruction(node: ObjectDeconstruction) { + attachToEOG(node) + node.components.forEach { handleEOG(it) } + } + + /** + * See + * [Specification for AlternativeDeconstruction](https://fraunhofer-aisec.github.io/cpg/CPG/specs/eog/#AlternativeDeconstruction) + * + * Note that we model Deconstructions in the inverse order than you may be used for other + * expressions. First the root node is evaluated, and then the children, as we walk down during + * the decomposition process. + */ + protected fun handleAlternativeDeconstruction(node: AlternativeDeconstruction) { + attachToEOG(node) + node.alternatives.forEach { handleEOG(it) } + } + + /** + * See + * [Specification for NamedDeconstruction](https://fraunhofer-aisec.github.io/cpg/CPG/specs/eog/#NamedDeconstruction) + * + * Note that we model Deconstructions in the inverse order than you may be used for other + * expressions. First the root node is evaluated, and then the children, as we walk down during + * the decomposition process. + */ + protected fun handleNamedDeconstruction(node: NamedDeconstruction) { + attachToEOG(node) + handleEOG(node.value) + } + /** * See * [Specification for LookupScope](https://fraunhofer-aisec.github.io/cpg/CPG/specs/eog/#lookupScope) diff --git a/cpg-language-rust/build.gradle.kts b/cpg-language-rust/build.gradle.kts new file mode 100644 index 00000000000..a427f03e7cc --- /dev/null +++ b/cpg-language-rust/build.gradle.kts @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +import de.undercouch.gradle.tasks.download.Download + +plugins { + id("cpg.frontend-conventions") + alias(libs.plugins.download) +} + +mavenPublishing { + pom { + name.set("Code Property Graph - Rust Frontend") + description.set("A Rust language frontend for the CPG") + } +} + +sourceSets { main { kotlin { srcDir("src/main/rust") } } } + +dependencies { implementation(libs.jna) } + +tasks { + val downloadLibRustAST by + registering(Download::class) { + val version = "v0.0.9" + + src( + listOf( + "https://github.com/Fraunhofer-AISEC/libast/releases/download/${version}/librustast-arm64.dylib", + "https://github.com/Fraunhofer-AISEC/libast/releases/download/${version}/librustast-amd64.dylib", + "https://github.com/Fraunhofer-AISEC/libast/releases/download/${version}/librustast-arm64.so", + "https://github.com/Fraunhofer-AISEC/libast/releases/download/${version}/librustast-amd64.so", + "https://github.com/Fraunhofer-AISEC/libast/releases/download/${version}/librustast-amd64.dll", + ) + ) + dest(projectDir.resolve("build/downloads/rustast")) + onlyIfModified(true) + } + + val prepareRustAstResources by + registering(Copy::class) { + dependsOn(downloadLibRustAST) + + into(projectDir.resolve("src/main/resources")) + + from("build/downloads/rustast/librustast-amd64.so") { + into("linux-x86-64") + rename { "librustast.so" } + } + + from("build/downloads/rustast/librustast-arm64.so") { + into("linux-aarch64") + rename { "librustast.so" } + } + + from("build/downloads/rustast/librustast-amd64.dylib") { + into("darwin-x86-64") + rename { "librustast.dylib" } + } + + from("build/downloads/rustast/librustast-arm64.dylib") { + into("darwin-aarch64") + rename { "librustast.dylib" } + } + + from("build/downloads/rustast/librustast-amd64.dll") { + into("win32-x86-64") + rename { "rustast.dll" } + } + } + + processResources { dependsOn(prepareRustAstResources) } + + sourcesJar { dependsOn(prepareRustAstResources) } +} diff --git a/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/DeclarationHandler.kt b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/DeclarationHandler.kt new file mode 100644 index 00000000000..d88f1d61b25 --- /dev/null +++ b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/DeclarationHandler.kt @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2025, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.graph.* +import de.fraunhofer.aisec.cpg.graph.declarations.* +import de.fraunhofer.aisec.cpg.graph.declarations.Function +import de.fraunhofer.aisec.cpg.graph.edges.scopes.ImportStyle +import uniffi.rustast.RsAssocItem +import uniffi.rustast.RsAst +import uniffi.rustast.RsConst +import uniffi.rustast.RsEnum +import uniffi.rustast.RsFieldList +import uniffi.rustast.RsFn +import uniffi.rustast.RsImpl +import uniffi.rustast.RsItem +import uniffi.rustast.RsModule +import uniffi.rustast.RsParam +import uniffi.rustast.RsPat +import uniffi.rustast.RsPath +import uniffi.rustast.RsStruct +import uniffi.rustast.RsTrait +import uniffi.rustast.RsType +import uniffi.rustast.RsUse +import uniffi.rustast.RsUseTree + +class DeclarationHandler(frontend: RustLanguageFrontend) : + RustHandler(::ProblemDeclaration, frontend) { + override fun handleNode(node: RsAst.RustItem): Declaration { + val item = node.v1 + return when (item) { + is RsItem.Fn -> handleFunctionDeclaration(item.v1) + is RsItem.Param -> handleParameterDeclaration(item.v1) + is RsItem.Module -> handleModule(item.v1) + is RsItem.Struct -> handleStruct(item.v1) + is RsItem.Impl -> handleImpl(item.v1) + is RsItem.Trait -> handleTrait(item.v1) + is RsItem.Const -> handleConst(item.v1) + is RsItem.Use -> handleUse(item.v1) + is RsItem.Enum -> handleEnum(item.v1) + else -> handleNotSupported(node, item::class.simpleName ?: "") + } + } + + private fun handleFunctionDeclaration(fn: RsFn): Function { + val name = frontend.scopeManager.currentNamespace.fqn(fn.name ?: "") + val raw = RsAst.RustItem(RsItem.Fn(fn)) + + val function = + fn.paramList?.selfParam?.let { + newMethod( + name, + recordDeclaration = frontend.scopeManager.currentRecord, + rawNode = raw, + ) + .apply { + val type = it.ty?.let { frontend.typeOf(it) } + this.parameters += + newParameter( + // Todo We need to handle destructuring in a parameter properly + it.astNode.text, + type = type ?: unknownType(), + rawNode = RsAst.RustItem(RsItem.SelfParam(it)), + ) + } + } ?: newFunction(name, rawNode = raw) + + frontend.scopeManager.addDeclaration(function) + + fn.retType?.let { function.type = frontend.typeOf(it) } + + frontend.scopeManager.enterScope(function) + + // Adding implicitly created parameters to the scope + function.parameters.forEach { frontend.scopeManager.addDeclaration(it) } + + for (param in fn.paramList?.params ?: listOf()) { + function.parameters += handleParameterDeclaration(param) as Parameter + } + + fn.body?.let { function.body = frontend.expressionHandler.handleBlockExpr(it) } + + frontend.scopeManager.leaveScope(function) + return function + } + + private fun handleParameterDeclaration(param: RsParam): Declaration { + + val type = param.ty?.let { frontend.typeOf(it) } + + val name = (param.pat as? RsPat.IdentPat)?.v1?.name ?: "" + + val parameter = + newParameter( + name, + type = type ?: unknownType(), + rawNode = RsAst.RustItem(RsItem.Param(param)), + ) + + frontend.scopeManager.addDeclaration(parameter) + + return parameter + } + + private fun handleModule(module: RsModule): Declaration { + val namespace = + newNamespace(module.name ?: "", rawNode = RsAst.RustItem(RsItem.Module(module))) + + frontend.scopeManager.enterScope(namespace) + + for (item in module.items) { + val declaration = handle(RsAst.RustItem(item)) + ((declaration as? DeclarationSequence)?.declarations ?: listOf(declaration)).forEach { + declItem -> + frontend.scopeManager.addDeclaration(declItem) + namespace.declarations += declItem + } + } + + frontend.scopeManager.leaveScope(namespace) + return namespace + } + + private fun handleStruct(struct: RsStruct): Declaration { + val raw = RsAst.RustItem(RsItem.Struct(struct)) + + val record = newRecord(struct.name ?: "", "struct", raw) + + frontend.scopeManager.enterScope(record) + + struct.fieldList?.let { fields -> + when (fields) { + is RsFieldList.RecordFieldList -> { + val rfs = fields.v1 + for (rField in rfs.fields) { + val type = rField.fieldType?.let { frontend.typeOf(it) } + + val field = newField(rField.name ?: "", type ?: unknownType()) + + field.initializer = + rField.expr?.let { + frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + record.fields += field + frontend.scopeManager.addDeclaration(field) + } + } + is RsFieldList.TupleFieldList -> { + var fieldCounter = 0 + val tfs = fields.v1 + for (tField in tfs.fields) { + val type = tField.fieldType?.let { frontend.typeOf(it) } + + val field = newField(fieldCounter.toString(), type ?: unknownType()) + + record.fields += field + frontend.scopeManager.addDeclaration(field) + fieldCounter++ + } + } + else -> {} + } + } + + frontend.scopeManager.leaveScope(record) + + return record + } + + private fun handleTrait(trait: RsTrait): Declaration { + val raw = RsAst.RustItem(RsItem.Trait(trait)) + + val record = newRecord(trait.name ?: "", "trait", raw) + + frontend.scopeManager.enterScope(record) + + for (item in trait.items) { + when (item) { + is RsAssocItem.Fn -> { + val func = handleFunctionDeclaration(item.v1) + record.addDeclaration(func) + frontend.scopeManager.addDeclaration(func) + } + is RsAssocItem.Const -> { + val const = + frontend.declarationHandler.handleNode( + RsAst.RustItem(RsItem.Const(item.v1)) + ) + // Todo Add Consts + } + is RsAssocItem.TypeAlias -> {} // Todo handle Type Alias + is RsAssocItem.MacroCall -> {} // Todo handle Macro Calls + } + } + + frontend.scopeManager.leaveScope(record) + + return record + } + + private fun handleImpl(impl: RsImpl): Declaration { + val implTarget = impl.pathTypes.last() + // The last part of the implementation block path is the target of the implementation, the + // record to add definitions to + var name = implTarget.path?.segment?.nameRef?.let { parseName(it.text) } ?: Name("") + + val scope = + frontend.scopeManager.lookupScope( + parseName( + frontend.scopeManager.currentNamespace + .fqn(name.toString(), delimiter = name.delimiter) + .toString() + ) + ) + val currentScope = frontend.scopeManager.currentScope + + scope?.let { frontend.scopeManager.enterScope(it) } + + val scopedNode = scope?.astNode + + // If the implementation blocks pathTypes is longer than one element, a trait was + // implemented for the record. + if (scopedNode is Record && impl.pathTypes.size > 1) { + val implInterface = impl.pathTypes.first() + name = implInterface.path?.segment?.nameRef?.let { parseName(it.text) } ?: Name("") + scopedNode.implementedInterfaces += + objectType(name, rawNode = RsAst.RustType(RsType.PathType(implInterface))) + } + + val extensionDeclaration = newExtension(name, RsAst.RustItem(RsItem.Impl(impl))) + + frontend.scopeManager.enterScope(extensionDeclaration) + + for (item in impl.items) { + when (item) { + is RsAssocItem.Fn -> { + val func = handleFunctionDeclaration(item.v1) + + if (scopedNode is Record) { + frontend.scopeManager.addDeclaration(func) + } + extensionDeclaration.declarations += func + } + is RsAssocItem.Const -> { + val const = + frontend.declarationHandler.handleNode( + RsAst.RustItem(RsItem.Const(item.v1)) + ) + extensionDeclaration.addDeclaration(const) + frontend.scopeManager.addDeclaration(const) + } + is RsAssocItem.TypeAlias -> {} // Todo handle type alias + is RsAssocItem.MacroCall -> {} // Todo handle macro call + } + } + + scope?.let { + frontend.scopeManager.leaveScope(it) + frontend.scopeManager.enterScope(currentScope) + } + + frontend.scopeManager.leaveScope(extensionDeclaration) + + return extensionDeclaration + } + + private fun handleUse(use: RsUse): Declaration { + val raw = RsAst.RustItem(RsItem.Use(use)) + + var imports = use.useTree?.let { flattenUseTree(rsUseTree = it) } + + imports?.forEach { import -> + // After Flattening we must check if the first part of the import name starts with + // crate, self or super + // If they do we replace them with the concrete name they represent in the context + import.import = frontend.handleKeywordsInNames(import.import) ?: Name("") + } + + val declarations = DeclarationSequence() + + for (import in imports ?: listOf()) { + declarations += import + frontend.scopeManager.addDeclaration(import) + } + + return if (declarations.isSingle) declarations.first() else declarations + } + + private fun flattenUseTree( + prefixName: Name? = null, + rsUseTree: RsUseTree, + ): MutableList { + val imports = mutableListOf() + + var importName = rsUseTree.path?.let { handlePathForImport(it) } ?: newName("") + + importName = newName(importName, namespace = prefixName) + + rsUseTree.useTrees.forEach { + flattenUseTree(prefixName = importName, it).let { imports += it } + } + + if (rsUseTree.useTrees.isEmpty()) { + // Todo Consider how we have to handle _ + val alias = rsUseTree.rename?.let { language.parseName(it) } + imports += + when (importName.localName) { + "self" -> + newImport( + importName.parent ?: newName(""), + alias = alias, + style = ImportStyle.IMPORT_SINGLE_SYMBOL_FROM_NAMESPACE, + rawNode = RsAst.RustUseTree(rsUseTree), + ) + else -> + newImport( + importName, + alias = alias, + style = + if (rsUseTree.star) ImportStyle.IMPORT_ALL_SYMBOLS_FROM_NAMESPACE + else ImportStyle.IMPORT_SINGLE_SYMBOL_FROM_NAMESPACE, + rawNode = RsAst.RustUseTree(rsUseTree), + ) + } + } + + return imports + } + + fun handleEnum(enum: RsEnum): Declaration { + val raw = RsAst.RustItem(RsItem.Enum(enum)) + + val enumRecord = newRecord(enum.name ?: "", "enum", raw) + + frontend.scopeManager.enterScope(enumRecord) + + for (variant in enum.variants) { + val variantRecord = newRecord(variant.name ?: "", "variant", RsAst.RustVariant(variant)) + + frontend.scopeManager.enterScope(variantRecord) + + // Handle discriminant expressions (integer discriminants) + if (variant.expr.isNotEmpty()) { + // Variant has an explicit discriminant value + val discriminantField = newField("discriminant", primitiveType("isize")) + discriminantField.initializer = + frontend.expressionHandler.handle(RsAst.RustExpr(variant.expr.first())) + variantRecord.fields += discriminantField + frontend.scopeManager.addDeclaration(discriminantField) + } + + // Todo We have an issue with variants where these cannot always be used as a type. + // While normally this would + // not be a problem, the type of the invariant captures the type of struct references + // and we get an incorrect + // type if we use records of the same type name, in an Enum with a variant that has the + // same type name + + // Handle field lists + for (fieldList in variant.fields) { + when (fieldList) { + is RsFieldList.RecordFieldList -> { + // Named fields - like struct with named fields + val rfs = fieldList.v1 + for (rField in rfs.fields) { + val type = rField.fieldType?.let { frontend.typeOf(it) } + val field = newField(rField.name ?: "", type ?: unknownType()) + field.initializer = + rField.expr?.let { + frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + variantRecord.fields += field + frontend.scopeManager.addDeclaration(field) + } + } + is RsFieldList.TupleFieldList -> { + // Unnamed fields - like struct with unnamed fields + var fieldCounter = 0 + val tfs = fieldList.v1 + for (tField in tfs.fields) { + val type = tField.fieldType?.let { frontend.typeOf(it) } + val field = newField(fieldCounter.toString(), type ?: unknownType()) + variantRecord.fields += field + frontend.scopeManager.addDeclaration(field) + fieldCounter++ + } + } + } + } + + variantRecord.implementedInterfaces += objectType(enumRecord.name, rawNode = raw) + + frontend.scopeManager.leaveScope(variantRecord) + + // Add the variant record as a sub-record of the enum + enumRecord.addDeclaration(variantRecord) + frontend.scopeManager.addDeclaration(variantRecord) + } + + frontend.scopeManager.leaveScope(enumRecord) + + return enumRecord + } + + private fun handlePathForImport(rsPath: RsPath): Name? { + // In the case of imports we do not have to handle return type, type args, type anchor and + // type args + + val qualifierName = + rsPath.qualifier.firstOrNull()?.let { qualifier -> handlePathForImport(qualifier) } + + return rsPath.segment?.nameRef?.text?.let { text -> + newName(text, namespace = qualifierName) + } + } + + private fun handleConst(const: RsConst): Declaration { + val raw = RsAst.RustItem(RsItem.Const(const)) + + val name = const.name ?: "" + + val type = const.ty?.let { frontend.typeOf(it) } + + return newVariable(name, type ?: unknownType(), rawNode = raw).apply { + const.expr.firstOrNull()?.let { + this.initializer = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + frontend.scopeManager.addDeclaration(this) + } + } +} diff --git a/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/ExpressionHandler.kt b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/ExpressionHandler.kt new file mode 100644 index 00000000000..47b336cd145 --- /dev/null +++ b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/ExpressionHandler.kt @@ -0,0 +1,872 @@ +/* + * Copyright (c) 2023, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.assumptions.AssumptionType +import de.fraunhofer.aisec.cpg.assumptions.assume +import de.fraunhofer.aisec.cpg.graph.* +import de.fraunhofer.aisec.cpg.graph.expressions.* +import de.fraunhofer.aisec.cpg.graph.newBreak +import de.fraunhofer.aisec.cpg.graph.newCase +import de.fraunhofer.aisec.cpg.graph.types.FunctionType.Companion.computeType +import uniffi.rustast.RsArrayExpr +import uniffi.rustast.RsAst +import uniffi.rustast.RsBinExpr +import uniffi.rustast.RsBlockExpr +import uniffi.rustast.RsBreakExpr +import uniffi.rustast.RsCallExpr +import uniffi.rustast.RsCastExpr +import uniffi.rustast.RsClosureExpr +import uniffi.rustast.RsContinueExpr +import uniffi.rustast.RsExpr +import uniffi.rustast.RsFieldExpr +import uniffi.rustast.RsForExpr +import uniffi.rustast.RsIfExpr +import uniffi.rustast.RsIndexExpr +import uniffi.rustast.RsItem +import uniffi.rustast.RsLetExpr +import uniffi.rustast.RsLiteral +import uniffi.rustast.RsLiteralType +import uniffi.rustast.RsLoopExpr +import uniffi.rustast.RsMacroExpr +import uniffi.rustast.RsMatchArm +import uniffi.rustast.RsMatchExpr +import uniffi.rustast.RsMethodCallExpr +import uniffi.rustast.RsParenExpr +import uniffi.rustast.RsPathExpr +import uniffi.rustast.RsPrefixExpr +import uniffi.rustast.RsRangeExpr +import uniffi.rustast.RsRecordExpr +import uniffi.rustast.RsRefExpr +import uniffi.rustast.RsReturnExpr +import uniffi.rustast.RsTryExpr +import uniffi.rustast.RsTupleExpr +import uniffi.rustast.RsUnderscoreExpr +import uniffi.rustast.RsWhileExpr + +class ExpressionHandler(frontend: RustLanguageFrontend) : + RustHandler(::ProblemExpression, frontend) { + + override fun handleNode(node: RsAst.RustExpr): Expression { + val unwrapped = node.v1 + return handleNode(unwrapped) + } + + fun handleNode(node: RsExpr): Expression { + return when (node) { + is RsExpr.BlockExpr -> handleBlockExpr(node.v1) + is RsExpr.Literal -> handleLiteral(node.v1) + is RsExpr.CallExpr -> handleCallExpr(node.v1) + is RsExpr.MethodCallExpr -> handleMethodCallExpr(node.v1) + is RsExpr.MacroExpr -> handleMacroExpr(node.v1) + is RsExpr.PathExpr -> handlePathExpr(node.v1) + is RsExpr.BinExpr -> handleBinExpr(node.v1) + is RsExpr.PrefixExpr -> handlePrefixExpr(node.v1) + is RsExpr.ParenExpr -> handleParenExpr(node.v1) + is RsExpr.RecordExpr -> handleRecordExpr(node.v1) + is RsExpr.IfExpr -> handleIfExpr(node.v1) + is RsExpr.LetExpr -> handleLetExpr(node.v1) + is RsExpr.WhileExpr -> handleWhileExpr(node.v1) + is RsExpr.ForExpr -> handleForExpr(node.v1) + is RsExpr.LoopExpr -> handleLoopExpr(node.v1) + is RsExpr.RangeExpr -> handleRangeExpr(node.v1) + is RsExpr.FieldExpr -> handleFieldExpr(node.v1) + is RsExpr.BreakExpr -> handleBreakExpr(node.v1) + is RsExpr.ContinueExpr -> handleContinueExpr(node.v1) + is RsExpr.CastExpr -> handleCastExpr(node.v1) + is RsExpr.IndexExpr -> handleIndexExpr(node.v1) + is RsExpr.RefExpr -> handleRefExpr(node.v1) + is RsExpr.ArrayExpr -> handleArrayExpr(node.v1) + is RsExpr.TupleExpr -> handleTupleExpr(node.v1) + is RsExpr.MatchExpr -> handleMatchExpr(node.v1) + is RsExpr.UnderscoreExpr -> handleUnderscoreExpr(node.v1) + is RsExpr.ReturnExpr -> handleReturnExpr(node.v1) + is RsExpr.TryExpr -> handleTryExpr(node.v1) + is RsExpr.ClosureExpr -> handleClosureExpr(node.v1) + + else -> handleNotSupported(RsAst.RustExpr(node), node::class.simpleName ?: "") + } + } + + fun handleBlockExpr(blockExpr: RsBlockExpr): Expression { + + val block = newBlock(RsAst.RustExpr(RsExpr.BlockExpr(blockExpr))) + + frontend.scopeManager.enterScope(block) + + for (stmt in blockExpr.stmts) { + block.statements += frontend.statementHandler.handle(RsAst.RustStmt(stmt)) + } + + blockExpr.tailExpr.getOrNull(0)?.let { + block.statements += frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + + frontend.scopeManager.leaveScope(block) + return block.also { it.usedAsExpression = true } + } + + fun handleLiteral(literal: RsLiteral): Expression { + val stringValue = literal.astNode.text + val raw = RsAst.RustExpr(RsExpr.Literal(literal)) + + return when (literal.literalType) { + RsLiteralType.CHAR_L -> + newLiteral(stringValue[0], language.builtInTypes["char"] ?: unknownType(), raw) + RsLiteralType.STRING_L -> + newLiteral(stringValue, language.builtInTypes["str"] ?: unknownType(), raw) + RsLiteralType.BYTE_L -> + newLiteral( + stringValue.removePrefix("b'").removeSuffix("'").let { + if (it.startsWith("\\x")) it.removePrefix("\\x").toInt(16) + else it.toInt(256) + }, + language.builtInTypes["u8"] ?: unknownType(), + raw, + ) + RsLiteralType.C_STRING_L -> + newLiteral( + stringValue.removePrefix("c").removeSuffix("'"), + objectType("CString"), + raw, + ) + RsLiteralType.INT_NUMBER_L -> + newLiteral(stringValue.toInt(), language.builtInTypes["str"] ?: unknownType(), raw) + RsLiteralType.BYTE_STRING_L -> + newLiteral( + stringValue.removePrefix("b").removeSuffix("'"), + language.builtInTypes["u8"] ?: unknownType().array(), + raw, + ) + RsLiteralType.FLOAT_NUMBER_L -> + newLiteral( + stringValue.substringBefore("f").toFloat(), + (if (stringValue.endsWith("f32")) language.builtInTypes["f32"] + else language.builtInTypes["f32"]) ?: unknownType(), + raw, + ) + RsLiteralType.UNKNOWN_L -> + newLiteral(stringValue, language.builtInTypes["str"] ?: unknownType(), raw) + } + } + + fun handleCallExpr(callExpr: RsCallExpr): Call { + + val callee: Expression? = callExpr.expr.getOrNull(0)?.let { handleNode(it) } + + val call = newCall(callee = callee, rawNode = RsAst.RustExpr(RsExpr.CallExpr(callExpr))) + + for (arg in callExpr.arguments) { + call.arguments += handleNode(arg) + } + + return call + } + + fun handleMethodCallExpr(methodCallExpr: RsMethodCallExpr): MemberCall { + + val callee: Expression? = + methodCallExpr.receiver.firstOrNull()?.let { + val base = handleNode(it) + + methodCallExpr.nameRef?.let { call -> + newMemberAccess(call.text, base, rawNode = RsAst.RustExpr(RsExpr.NameRef(call))) + } + } + + val method = + newMemberCall( + callee = callee, + rawNode = RsAst.RustExpr(RsExpr.MethodCallExpr(methodCallExpr)), + ) + + for (arg in methodCallExpr.arguments) { + method.arguments += handleNode(arg) + } + + return method + } + + fun handleMacroExpr(macroExpr: RsMacroExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.MacroExpr(macroExpr)) + macroExpr.macroCall?.let { + val base = + it.path?.segment?.nameRef?.let { + newReference(it.text, rawNode = RsAst.RustExpr(RsExpr.NameRef(it))) + } + val call = newCall(callee = base, rawNode = raw) + call.arguments += newLiteral(it.macroString) + return call + } + + return newProblemExpression( + problem = "MacroExpression does not contain Macro Call", + rawNode = raw, + ) + } + + fun handlePathExpr(pathExpr: RsPathExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.PathExpr(pathExpr)) + + pathExpr.path?.let { rsPath -> + return newReference( + frontend.handleKeywordsInNames(frontend.handlePathForRef(rsPath) ?: newName("")), + rawNode = raw, + ) + } + + return newProblemExpression( + problem = "PathExpression does not contain reference to a name", + rawNode = raw, + ) + } + + fun handleRefExpr(refExpr: RsRefExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.RefExpr(refExpr)) + + refExpr.expr.firstOrNull()?.let { + val subExpr = handleNode(it) + + // We for now do not handle const and mut modifiers as they have no direct consequence + // in control or data flow. + // They are relevant to whether code is compilable, and therefore we may need to include + // it as the type. + return if (refExpr.isRef) + newUnaryOperator(operatorCode = "&", postfix = false, prefix = true, rawNode = raw) + .also { unaryOp -> unaryOp.input = subExpr } + else subExpr + } + + return newProblemExpression( + problem = "Reference expressions are not supported yet", + rawNode = raw, + ) + } + + fun handlePrefixExpr(prefixExpr: RsPrefixExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.PrefixExpr(prefixExpr)) + return newUnaryOperator(prefixExpr.operator, postfix = false, prefix = true, rawNode = raw) + .also { + it.input = + frontend.expressionHandler.handle(RsAst.RustExpr(prefixExpr.expr.first())) + } + } + + fun handleBinExpr(binExpr: RsBinExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.BinExpr(binExpr)) + if (binExpr.expressions.size == 2) { + val lhs = frontend.expressionHandler.handle(RsAst.RustExpr(binExpr.expressions.first())) + val rhs = frontend.expressionHandler.handle(RsAst.RustExpr(binExpr.expressions.last())) + if ( + binExpr.operator in language.compoundAssignmentOperators || + binExpr.operator in language.simpleAssignmentOperators + ) { + return newAssign(binExpr.operator, listOf(lhs), listOf(rhs), raw) + } + + return newBinaryOperator(binExpr.operator, raw).also { + it.lhs = lhs + it.rhs = rhs + } + } else if (binExpr.expressions.size == 1) { + return newUnaryOperator( + binExpr.operator, + postfix = false, + prefix = false, + rawNode = raw, + ) + .also { + it.input = + frontend.expressionHandler.handle( + RsAst.RustExpr(binExpr.expressions.first()) + ) + } + } + + return newProblemExpression( + problem = + "Operator based expression has an incorrect amount of ${binExpr.expressions} operators", + rawNode = raw, + ) + } + + fun handleIfExpr(ifExpr: RsIfExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.IfExpr(ifExpr)) + val ifElse = newIfElse(raw) + frontend.scopeManager.enterScope(ifElse) + + // Depending on whether the first expression is a let expression we want fo fill condition + // or condition declaration + ifExpr.expressions.first().let { + val condExpr = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + if (condExpr is DeclarationStatement) { + // There should only be one declaration inside a let of an if + ifElse.conditionDeclaration = condExpr.declarations.first() + } else { + ifElse.condition = condExpr + } + } + + ifExpr.expressions.getOrNull(1)?.let { + ifElse.thenStatement = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + + ifExpr.expressions.getOrNull(2)?.let { + ifElse.elseStatement = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + + frontend.scopeManager.leaveScope(ifElse) + return ifElse.also { it.usedAsExpression = true } + } + + fun handleLetExpr(letExpr: RsLetExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.LetExpr(letExpr)) + + // for us, a let expression is an assigment with a deconstruction + + val assign: Assign = + newAssign( + operatorCode = "=", + lhs = + letExpr.pat.firstOrNull()?.let { + listOf(frontend.patternHandler.handle(RsAst.RustPat(it))) + } ?: emptyList(), + rhs = + letExpr.expr.firstOrNull()?.let { + listOf(frontend.expressionHandler.handle(RsAst.RustExpr(it))) + } ?: emptyList(), + rawNode = raw, + ) + + assign.usedAsExpression = true + + return assign + } + + fun handleWhileExpr(whileExpr: RsWhileExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.WhileExpr(whileExpr)) + + val whileExpression = newWhile(raw) + + frontend.scopeManager.enterScope(whileExpression) + + whileExpr.expressions.first().let { + val condExpr = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + if (condExpr is DeclarationStatement) { + // There should only be one declaration inside a let of an if + whileExpression.conditionDeclaration = condExpr.declarations.first() + } else { + whileExpression.condition = condExpr + } + } + + whileExpr.expressions.getOrNull(1)?.let { + whileExpression.statement = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + + frontend.scopeManager.leaveScope(whileExpression) + + whileExpression.usedAsExpression = true + + return whileExpression.also { it.usedAsExpression = true } + } + + fun handleLoopExpr(loopExpr: RsLoopExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.LoopExpr(loopExpr)) + val whileExpression = newWhile(raw) + + frontend.scopeManager.enterScope(whileExpression) + + whileExpression.condition = + newLiteral(true, language.builtInTypes["bool"] ?: unknownType(), raw).also { + it.isImplicit = true + } + + loopExpr.body.firstOrNull()?.let { + whileExpression.statement = frontend.expressionHandler.handleBlockExpr(it) + } + + frontend.scopeManager.leaveScope(whileExpression) + + whileExpression.usedAsExpression = true + + return whileExpression.also { it.usedAsExpression = true } + } + + fun handleForExpr(forExpr: RsForExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.ForExpr(forExpr)) + val forEach = newForEach(rawNode = raw) + frontend.scopeManager.enterScope(forEach) + + val variable = + forExpr.pat?.let { frontend.patternHandler.handle(RsAst.RustPat(it)) } + ?: newProblemExpression("Variable pattern is null") + + forExpr.expressions.first().let { + val iterable = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + forEach.iterable = iterable + } + + forExpr.expressions.getOrNull(1)?.let { + forEach.statement = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + + forEach.variable = variable + + frontend.scopeManager.leaveScope(forEach) + + forEach.usedAsExpression = true + + return forEach.also { it.usedAsExpression = true } + } + + fun handleBreakExpr(breakExpr: RsBreakExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.BreakExpr(breakExpr)) + + val breakExpression = newBreak(raw) + + breakExpr.lifetime?.let { breakExpression.label = it.name } + + breakExpr.expr.firstOrNull()?.let { + breakExpression.expr = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + breakExpression.usedAsExpression = true + } + + return breakExpression + } + + fun handleContinueExpr(continueExpr: RsContinueExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.ContinueExpr(continueExpr)) + + val continueExpression = newContinue(raw) + + continueExpr.lifetime?.let { continueExpression.label = it.name } + + return continueExpression + } + + fun handleRangeExpr(rangeExpr: RsRangeExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.RangeExpr(rangeExpr)) + val range = newRange(rawNode = raw) + + rangeExpr.expressions.getOrNull(0)?.let { + range.floor = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + + rangeExpr.expressions.getOrNull(1)?.let { + range.ceiling = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + + range.operatorCode = rangeExpr.operator + return range + } + + fun handleFieldExpr(fieldExpr: RsFieldExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.FieldExpr(fieldExpr)) + + fieldExpr.expr.first().let { + val base = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + fieldExpr.nameRef?.let { nameRef -> + return newMemberAccess(name = nameRef.text, base = base, rawNode = raw) + } + } + + return newProblemExpression( + problem = "FieldExpression does not contain a base expression or a name reference", + rawNode = raw, + ) + } + + fun handleCastExpr(castExpr: RsCastExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.CastExpr(castExpr)) + + val input = frontend.expressionHandler.handle(RsAst.RustExpr(castExpr.expr.first())) + + val type = castExpr.ty.firstOrNull()?.let { frontend.typeOf(it) } ?: unknownType() + + return newCast(raw).also { + it.expression = input + it.castType = type + } + } + + fun handleIndexExpr(indexExpr: RsIndexExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.IndexExpr(indexExpr)) + + if (indexExpr.expressions.size >= 2) { + return newSubscription(rawNode = raw).also { subscription -> + indexExpr.expressions.getOrNull(0)?.let { + subscription.arrayExpression = + frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + + indexExpr.expressions.getOrNull(1)?.let { + subscription.subscriptExpression = + frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + } + } + + return newProblemExpression( + problem = "Index expressions was not parsed with two ore more expressions.", + rawNode = raw, + ) + } + + fun handleArrayExpr(arrayExpr: RsArrayExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.ArrayExpr(arrayExpr)) + + val arrayConstruction = + newArrayConstruction(rawNode = raw).also { arrayConstruction -> + val initializer = newInitializerList(rawNode = raw) + for (expr in arrayExpr.expressions) { + initializer.initializers += + frontend.expressionHandler.handle(RsAst.RustExpr(expr)) + } + arrayConstruction.initializer = initializer + } + + if (arrayExpr.repeating) { + arrayConstruction.assume( + assumptionType = AssumptionType.DataFlowAssumption, + "Using the repetition expression as value in the array model a direct DF although it is an indirect DF.", + arrayConstruction, + ) + } + + return arrayConstruction + } + + fun handleRecordExpr(recordExpr: RsRecordExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.RecordExpr(recordExpr)) + + val t = recordExpr.path?.let { frontend.typeOf(it.astNode.text) } ?: unknownType() + + // Todo Look if we can replace this with an initializer list as there is no effective + // constructor call + val construction = newConstruction(rawNode = raw) + construction.type = t + + val refName = "null" + + // We add this first, such that dfg handling then properly captures overwriting variables + recordExpr.spread.firstOrNull()?.let { + construction.addArgument( + newAssign( + lhs = listOf(newReference(refName)), + rhs = listOf(handle(RsAst.RustExpr(it))), + rawNode = RsAst.RustExpr(it), + ) + ) + } + + recordExpr.fields.forEach { field -> + val rawField = RsAst.RustExpr(RsExpr.RecordExprField(field)) + field.expr.firstOrNull()?.let { expr -> + val value = handle(RsAst.RustExpr(expr)) + + val member = + field.name?.let { + newMemberAccess(it.text, newReference(refName), rawNode = rawField) + } + ?: newMemberAccess( + value.toString(), + newReference(refName), + rawNode = rawField, + ) + + construction.addArgument( + newAssign(lhs = listOf(member), rhs = listOf(value), rawNode = rawField).also { + it.usedAsExpression = true + } + ) + } + } + + return construction + } + + fun handleTupleExpr(tupleExpr: RsTupleExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.TupleExpr(tupleExpr)) + + val tupleConstruction = newInitializerList(rawNode = raw) + + tupleExpr.exprs.forEach { expr -> + tupleConstruction.initializers += handle(RsAst.RustExpr(expr)) + } + + return tupleConstruction + } + + fun handleReturnExpr(returnExpr: RsReturnExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.ReturnExpr(returnExpr)) + val ret = newReturn(raw) + returnExpr.expr.firstOrNull()?.let { + ret.returnValue = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + return ret + } + + fun handleMatchExpr(matchExpr: RsMatchExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.MatchExpr(matchExpr)) + + // Get the scrutinee (the value being matched) + val scrutinee = + matchExpr.expr.firstOrNull()?.let { handleNode(it) } + ?: return newProblemExpression( + problem = "Match expression does not contain a scrutinee", + rawNode = raw, + ) + + // Create the switch statement + val switchStatement = + newSwitch(rawNode = raw) + .assume( + assumptionType = AssumptionType.ControlFlowAssumption, + "Modeling match as a switch leads to an overapproximation of EOG paths as switch fallthrough can lead to guards being evaluated that would fail at the pattern matching, i.e. case expression.", + ) + switchStatement.selector = scrutinee + + frontend.scopeManager.enterScope(switchStatement) + + // Create a block to hold all case statements + val caseBlock = newBlock(raw) + caseBlock.usedAsExpression = true + + // Process each match arm + for (arm in matchExpr.arms) { + caseBlock.statements += handleMatchArm(arm) + } + + switchStatement.statement = caseBlock + + frontend.scopeManager.leaveScope(switchStatement) + + switchStatement.usedAsExpression = true + + return switchStatement + } + + fun handleUnderscoreExpr(underscoreExpr: RsUnderscoreExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.UnderscoreExpr(underscoreExpr)) + return newEmpty(raw) + } + + fun handleParenExpr(parenExpr: RsParenExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.ParenExpr(parenExpr)) + + parenExpr.expr.firstOrNull()?.let { + return handleNode(it) + } + return newEmpty(raw) + } + + fun handleTryExpr(tryExpr: RsTryExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.TryExpr(tryExpr)) + tryExpr.expr.firstOrNull()?.let { + // Here we translate a try expression to: + // match expr { Ok(val) => val, Err(err) => err } + // This does not fully depict the structure it is translated to as this depends on the + // implementation + // of the try trait, but is sufficient to modell the same EOG and DFG + + // We model the try operator as a function call, as it is basically syntactic sugar for + // a match on the result + return newSwitch(rawNode = raw).also { switch -> + switch.selector = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + frontend.scopeManager.enterScope(switch) + + // Create a block to hold two case statements + val caseBlock = newBlock(raw) + caseBlock.usedAsExpression = true + + caseBlock.statements += + newCase(raw).also { value -> + value.caseExpression = + newObjectDeconstruction(raw).also { obj -> + obj.type = frontend.typeOf("Ok") + obj.components += + newDeclarationStatement(rawNode = raw).also { declaration -> + declaration.usedAsExpression = true + val variable = newVariable(rawNode = raw, name = "val") + declaration.declarations += variable + + variable.initializer = newEmpty(raw) + frontend.scopeManager.addDeclaration(variable) + } + } + } + + val breakStatement = newBreak() + breakStatement.expr = newReference("val") + breakStatement.usedAsExpression = true + caseBlock.statements += breakStatement + + caseBlock.statements += + newCase(raw).also { value -> + value.caseExpression = + newObjectDeconstruction(raw).also { obj -> + obj.type = frontend.typeOf("Err") + obj.components += + newDeclarationStatement(rawNode = raw).also { declaration -> + declaration.usedAsExpression = true + val variable = newVariable(rawNode = raw, name = "err") + declaration.declarations += variable + variable.initializer = newEmpty(raw) + frontend.scopeManager.addDeclaration(variable) + } + } + } + caseBlock.statements += + newReturn(raw).also { ret -> ret.returnValue = newReference("err") } + + switch.statement = caseBlock + + frontend.scopeManager.leaveScope(switch) + + switch.usedAsExpression = true + } + } + + return newProblemExpression( + problem = "Try expressions are not supported yet", + rawNode = raw, + ) + } + + private fun handleMatchArm(arm: RsMatchArm): List { + val raw = RsAst.RustExpr(RsExpr.MatchArm(arm)) + // Deconstruct the pattern and create a case statement + val pattern = + arm.pat.firstOrNull()?.let { frontend.patternHandler.handleNode(it) } + ?: return listOf( + newProblemExpression( + problem = "Match arm does not contain a pattern", + rawNode = raw, + ) + ) + + val caseStatement = + newCase(rawNode = arm.pat.firstOrNull()?.let { RsAst.RustPat(it) } ?: raw) + caseStatement.caseExpression = pattern + + var caseExpressions = mutableListOf(caseStatement) + + // Get the match arm expression + val armExpr = + arm.expr.firstOrNull()?.let { handleNode(it) } + ?: return listOf( + newProblemExpression( + problem = "Match arm does not contain an expression", + rawNode = raw, + ) + ) + val wrappedRawExpr = arm.expr.firstOrNull()?.let { RsAst.RustExpr(it) } ?: raw + + // If there's a guard, wrap the break statement in an if + if (arm.guard.isNotEmpty()) { + val guard = + arm.guard.firstOrNull()?.let { handleNode(it) } + ?: return listOf( + newProblemExpression( + problem = "Match arm guard could not be parsed", + rawNode = raw, + ) + ) + + val ifElse = newIfElse(raw) + ifElse.condition = guard + + val breakStatement = newBreak(wrappedRawExpr) + breakStatement.expr = armExpr + breakStatement.usedAsExpression = true + + val ifBlock = newBlock(raw) + ifBlock.statements += breakStatement + ifElse.thenStatement = ifBlock + + caseExpressions += ifElse + } else { + // No guard, directly create break statement + val breakStatement = newBreak(wrappedRawExpr) + breakStatement.expr = armExpr + breakStatement.usedAsExpression = true + + caseExpressions += breakStatement + } + + return caseExpressions + } + + fun handleClosureExpr(closureExpr: RsClosureExpr): Expression { + val raw = RsAst.RustExpr(RsExpr.ClosureExpr(closureExpr)) + + val lambda = newLambda(rawNode = raw) + val enclosedFunction = newFunction("", rawNode = raw) + frontend.scopeManager.enterScope(enclosedFunction) + + val paramsList = closureExpr.paramList.firstOrNull() + + val function = + paramsList?.selfParam?.let { + newMethod( + "", + recordDeclaration = frontend.scopeManager.currentRecord, + rawNode = raw, + ) + .apply { + val type = it.ty?.let { frontend.typeOf(it) } + this.parameters += + newParameter( + it.astNode.text, + type = type ?: unknownType(), + rawNode = RsAst.RustItem(RsItem.SelfParam(it)), + ) + } + } ?: newFunction("", rawNode = raw) + + paramsList?.let { params -> + for (parameter in params.params) { + val resolvedType = parameter.ty?.let { frontend.typeOf(it) } ?: unknownType() + // Todo We need to handle destructuring in a parameter properly + val param = newParameter(parameter.astNode.text, resolvedType) + frontend.scopeManager.addDeclaration(param) + enclosedFunction.parameters += param + } + } + + val functionType = computeType(enclosedFunction) + enclosedFunction.type = functionType + closureExpr.expressions.firstOrNull()?.let { + enclosedFunction.body = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + frontend.scopeManager.leaveScope(enclosedFunction) + + lambda.function = enclosedFunction + + return lambda + } +} diff --git a/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/PatternHandler.kt b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/PatternHandler.kt new file mode 100644 index 00000000000..81529414733 --- /dev/null +++ b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/PatternHandler.kt @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.graph.AccessValues +import de.fraunhofer.aisec.cpg.graph.declarations.Variable +import de.fraunhofer.aisec.cpg.graph.expressions.Expression +import de.fraunhofer.aisec.cpg.graph.expressions.ProblemExpression +import de.fraunhofer.aisec.cpg.graph.newAlternativeDeconstruction +import de.fraunhofer.aisec.cpg.graph.newAssign +import de.fraunhofer.aisec.cpg.graph.newDeclarationStatement +import de.fraunhofer.aisec.cpg.graph.newEmpty +import de.fraunhofer.aisec.cpg.graph.newName +import de.fraunhofer.aisec.cpg.graph.newNamedDeconstruction +import de.fraunhofer.aisec.cpg.graph.newObjectDeconstruction +import de.fraunhofer.aisec.cpg.graph.newProblemExpression +import de.fraunhofer.aisec.cpg.graph.newRange +import de.fraunhofer.aisec.cpg.graph.newReference +import de.fraunhofer.aisec.cpg.graph.newVariable +import uniffi.rustast.RsAst +import uniffi.rustast.RsBoxPat +import uniffi.rustast.RsConstBlockPat +import uniffi.rustast.RsExpr +import uniffi.rustast.RsIdentPat +import uniffi.rustast.RsLiteralPat +import uniffi.rustast.RsMacroPat +import uniffi.rustast.RsOrPat +import uniffi.rustast.RsParenPat +import uniffi.rustast.RsPat +import uniffi.rustast.RsPathPat +import uniffi.rustast.RsRangePat +import uniffi.rustast.RsRecordPat +import uniffi.rustast.RsRecordPatField +import uniffi.rustast.RsRefPat +import uniffi.rustast.RsRestPat +import uniffi.rustast.RsSlicePat +import uniffi.rustast.RsTuplePat +import uniffi.rustast.RsTupleStructPat +import uniffi.rustast.RsWildcardPat + +class PatternHandler(frontend: RustLanguageFrontend) : + RustHandler(::ProblemExpression, frontend) { + + override fun handleNode(node: RsAst.RustPat): Expression { + val unwrapped = node.v1 + return handleNode(unwrapped) + } + + fun handleNode(node: RsPat): Expression { + return when (node) { + is RsPat.BoxPat -> handleBoxPat(node.v1) + is RsPat.ConstBlockPat -> handleConstBlockPat(node.v1) + is RsPat.IdentPat -> handleIdentPat(node.v1) + is RsPat.LiteralPat -> handleLiteralPat(node.v1) + is RsPat.MacroPat -> handleMacroPat(node.v1) + is RsPat.OrPat -> handleOrPat(node.v1) + is RsPat.ParenPat -> handleParenPat(node.v1) + is RsPat.PathPat -> handlePathPat(node.v1) + is RsPat.RangePat -> handleRangePat(node.v1) + is RsPat.RecordPat -> handleRecordPat(node.v1) + is RsPat.RefPat -> handleRefPat(node.v1) + is RsPat.RestPat -> handleRestPat(node.v1) + is RsPat.SlicePat -> handleSlicePat(node.v1) + is RsPat.TuplePat -> handleTuplePat(node.v1) + is RsPat.TupleStructPat -> handleTupleStructPat(node.v1) + is RsPat.WildcardPat -> handleWildcardPat(node.v1) + is RsPat.RecordPatField -> handleRecordPatField(node.v1) + } + } + + fun handleIdentPat(identPat: RsIdentPat): Expression { + val raw = RsAst.RustPat(RsPat.IdentPat(identPat)) + + val variable = + frontend.scopeManager.currentScope.symbols[identPat.name] + ?.filterIsInstance() + ?.firstOrNull() + + variable?.let { + val lhsRef = + newReference(identPat.name, rawNode = raw).also { it.access = AccessValues.WRITE } + // If identPat has a nested pattern, translate it as an assignment + identPat.pat.firstOrNull()?.let { nestedPat -> + val rhs = handleNode(nestedPat) + return newAssign("=", listOf(lhsRef), listOf(rhs), rawNode = raw) + } + + return lhsRef + } + + return newDeclarationStatement(rawNode = raw).also { declaration -> + declaration.usedAsExpression = true + val variable = newVariable(rawNode = raw, name = identPat.name) + declaration.declarations += variable + + // If the pattern is empty we use an empty expression as initializer, it forwards dfgs + // that are pointing to it + // during deconstruction + variable.initializer = + identPat.pat.firstOrNull()?.let { handleNode(it) } ?: newEmpty(raw) + frontend.scopeManager.addDeclaration(variable) + } + } + + fun handleBoxPat(boxPat: RsBoxPat): Expression { + val raw = RsAst.RustPat(RsPat.BoxPat(boxPat)) + + val box = newObjectDeconstruction(raw) + + // Todo add type according to box pattern + + boxPat.pat.firstOrNull()?.let { box.components += handleNode(it) } + + return box + } + + fun handleConstBlockPat(constBlockPat: RsConstBlockPat): Expression { + val raw = RsAst.RustPat(RsPat.ConstBlockPat(constBlockPat)) + + constBlockPat.blockExpr?.let { + return frontend.expressionHandler.handleNode(RsExpr.BlockExpr(it)) + } + + return newProblemExpression("ConstBlockPat does not contain a handleable block expression") + } + + fun handleLiteralPat(literalPat: RsLiteralPat): Expression { + val raw = RsAst.RustPat(RsPat.LiteralPat(literalPat)) + + literalPat.literal?.let { + return frontend.expressionHandler.handleNode(RsExpr.Literal(it)) + } + + return newProblemExpression("RsLiteralPat does not contain a handleable literal") + } + + fun handleMacroPat(macroPat: RsMacroPat): Expression { + val raw = RsAst.RustPat(RsPat.MacroPat(macroPat)) + + return newProblemExpression("MacroPat need to be resolved before translation") + } + + fun handleOrPat(orPat: RsOrPat): Expression { + val raw = RsAst.RustPat(RsPat.OrPat(orPat)) + + val alternative = newAlternativeDeconstruction(raw) + + orPat.pats.forEach { alternative.alternatives += handleNode(it) } + + return alternative + } + + fun handleParenPat(parenPat: RsParenPat): Expression { + val raw = RsAst.RustPat(RsPat.ParenPat(parenPat)) + + parenPat.pat.firstOrNull()?.let { + return handleNode(it) + } + + return newProblemExpression("ParenPat does not contain a valid subpattern") + } + + fun handlePathPat(pathPat: RsPathPat): Expression { + val raw = RsAst.RustPat(RsPat.PathPat(pathPat)) + + pathPat.path?.let { rsPath -> + return newReference( + frontend.handleKeywordsInNames(frontend.handlePathForRef(rsPath) ?: newName("")), + rawNode = raw, + ) + } + + return newProblemExpression("RsPathPat cannot be parsed properly") + } + + fun handleRangePat(rangePat: RsRangePat): Expression { + val raw = RsAst.RustPat(RsPat.RangePat(rangePat)) + + val range = newRange(rawNode = raw) + + rangePat.patterns.getOrNull(0)?.let { + range.floor = frontend.patternHandler.handle(RsAst.RustPat(it)) + } + + rangePat.patterns.getOrNull(1)?.let { + range.ceiling = frontend.patternHandler.handle(RsAst.RustPat(it)) + } + + range.operatorCode = rangePat.operator + + return range + } + + fun handleRecordPat(recordPat: RsRecordPat): Expression { + val raw = RsAst.RustPat(RsPat.RecordPat(recordPat)) + + val objectDeconstruction = newObjectDeconstruction(raw) + + recordPat.path?.let { rsPath -> + // Todo If I set a type base on a name, shouldn't the resolution then use the scope + objectDeconstruction.type = + frontend.typeOf( + frontend + .handleKeywordsInNames(frontend.handlePathForRef(rsPath) ?: newName("")) + .toString() + ) + } + + recordPat.fields.forEach { field -> + objectDeconstruction.components += handleRecordPatField(field) + } + + return objectDeconstruction + } + + fun handleRefPat(refPat: RsRefPat): Expression { + val raw = RsAst.RustPat(RsPat.RefPat(refPat)) + + refPat.pat.firstOrNull()?.let { + val contained = handleNode(it) + if (refPat.isRef) { + val objectDeconstruction = newObjectDeconstruction(raw) + objectDeconstruction.components += contained + // Todo handle type as this behaves like a deref + return objectDeconstruction + } else { + return contained + } + } + + return newProblemExpression("RefPat is not supported yet") + } + + fun handleRestPat(restPat: RsRestPat): Expression { + val raw = RsAst.RustPat(RsPat.RestPat(restPat)) + return newEmpty(rawNode = raw) + } + + fun handleSlicePat(slicePat: RsSlicePat): Expression { + val raw = RsAst.RustPat(RsPat.SlicePat(slicePat)) + + return newObjectDeconstruction(raw).also { oDec -> + slicePat.pats.forEach { oDec.components += handleNode(it) } + } + } + + fun handleTuplePat(tuplePat: RsTuplePat): Expression { + val raw = RsAst.RustPat(RsPat.TuplePat(tuplePat)) + + return newObjectDeconstruction(raw).also { oDec -> + tuplePat.fields.forEach { oDec.components += handleNode(it) } + } + } + + fun handleTupleStructPat(tupleStructPat: RsTupleStructPat): Expression { + val raw = RsAst.RustPat(RsPat.TupleStructPat(tupleStructPat)) + + return newObjectDeconstruction(raw).also { oDec -> + tupleStructPat.fields.forEach { oDec.components += handleNode(it) } + } + } + + fun handleWildcardPat(wildcardPat: RsWildcardPat): Expression { + val raw = RsAst.RustPat(RsPat.WildcardPat(wildcardPat)) + return newEmpty(rawNode = raw) + } + + fun handleRecordPatField(recordPatField: RsRecordPatField): Expression { + val raw = RsAst.RustPat(RsPat.RecordPatField(recordPatField)) + + recordPatField.pat.firstOrNull()?.let { + return newNamedDeconstruction(raw).also { namedDec -> + namedDec.value = handleNode(it) + + namedDec.name = + recordPatField.name?.let { name -> newName(name.text) } ?: namedDec.value.name + } + } + + return newProblemExpression("RecordPatField does not contain a valid pattern") + } +} diff --git a/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/Rust.kt b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/Rust.kt new file mode 100644 index 00000000000..c0a6c420761 --- /dev/null +++ b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/Rust.kt @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2025, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.frontends.rust + +import uniffi.rustast.RsAst +import uniffi.rustast.RsExpr +import uniffi.rustast.RsItem +import uniffi.rustast.RsNode +import uniffi.rustast.RsPat +import uniffi.rustast.RsStmt +import uniffi.rustast.RsType + +/** + * I dislike accessing a field by continuous extending of an access function, but Rust does not + * support inheritance, and therefore the generated bindings don't either. We cannot specify that a + * field exists in several class. + */ +fun RsAst.astNode(): RsNode { + return when (this) { + is RsAst.RustExpr -> this.v1.astNode() + is RsAst.RustItem -> this.v1.astNode() + is RsAst.RustStmt -> this.v1.astNode() + is RsAst.RustType -> this.v1.astNode() + is RsAst.RustAbi -> this.v1.astNode + is RsAst.RustProblem -> this.v1.astNode + is RsAst.RustUseTree -> this.v1.astNode + is RsAst.RustPat -> this.v1.astNode() + is RsAst.RustVariant -> this.v1.astNode + } +} + +fun RsExpr.astNode(): RsNode { + return when (this) { + is RsExpr.ArrayExpr -> this.v1.astNode + is RsExpr.Literal -> this.v1.astNode + is RsExpr.AsmExpr -> this.v1.astNode + is RsExpr.IfExpr -> this.v1.astNode + is RsExpr.ParenExpr -> this.v1.astNode + is RsExpr.AwaitExpr -> this.v1.astNode + is RsExpr.BecomeExpr -> this.v1.astNode + is RsExpr.BinExpr -> this.v1.astNode + is RsExpr.BlockExpr -> this.v1.astNode + is RsExpr.BreakExpr -> this.v1.astNode + is RsExpr.CallExpr -> this.v1.astNode + is RsExpr.CastExpr -> this.v1.astNode + is RsExpr.ClosureExpr -> this.v1.astNode + is RsExpr.ContinueExpr -> this.v1.astNode + is RsExpr.FieldExpr -> this.v1.astNode + is RsExpr.ForExpr -> this.v1.astNode + is RsExpr.FormatArgsExpr -> this.v1.astNode + is RsExpr.IndexExpr -> this.v1.astNode + is RsExpr.LetExpr -> this.v1.astNode + is RsExpr.LoopExpr -> this.v1.astNode + is RsExpr.MacroExpr -> this.v1.astNode + is RsExpr.MatchExpr -> this.v1.astNode + is RsExpr.MethodCallExpr -> this.v1.astNode + is RsExpr.OffsetOfExpr -> this.v1.astNode + is RsExpr.PathExpr -> this.v1.astNode + is RsExpr.PrefixExpr -> this.v1.astNode + is RsExpr.RangeExpr -> this.v1.astNode + is RsExpr.RecordExpr -> this.v1.astNode + is RsExpr.RefExpr -> this.v1.astNode + is RsExpr.ReturnExpr -> this.v1.astNode + is RsExpr.TryExpr -> this.v1.astNode + is RsExpr.TupleExpr -> this.v1.astNode + is RsExpr.UnderscoreExpr -> this.v1.astNode + is RsExpr.WhileExpr -> this.v1.astNode + is RsExpr.YeetExpr -> this.v1.astNode + is RsExpr.YieldExpr -> this.v1.astNode + is RsExpr.Path -> this.v1.astNode + is RsExpr.PathSegment -> this.v1.astNode + is RsExpr.NameRef -> this.v1.astNode + is RsExpr.RecordExprField -> this.v1.astNode + is RsExpr.MatchArm -> this.v1.astNode + } +} + +fun RsItem.astNode(): RsNode { + return when (this) { + is RsItem.Fn -> this.v1.astNode + is RsItem.Module -> this.v1.astNode + is RsItem.Use -> this.v1.astNode + is RsItem.Enum -> this.v1.astNode + is RsItem.Impl -> this.v1.astNode + is RsItem.AsmExpr -> this.v1.astNode + is RsItem.Const -> this.v1.astNode + is RsItem.ExternBlock -> this.v1.astNode + is RsItem.ExternCrate -> this.v1.astNode + is RsItem.MacroCall -> this.v1.astNode + is RsItem.MacroDef -> this.v1.astNode + is RsItem.MacroRules -> this.v1.astNode + is RsItem.Static -> this.v1.astNode + is RsItem.Struct -> this.v1.astNode + is RsItem.Trait -> this.v1.astNode + is RsItem.TypeAlias -> this.v1.astNode + is RsItem.Union -> this.v1.astNode + is RsItem.Param -> this.v1.astNode + is RsItem.SelfParam -> this.v1.astNode + } +} + +fun RsStmt.astNode(): RsNode { + return when (this) { + is RsStmt.ExprStmt -> this.v1.astNode + is RsStmt.LetStmt -> this.v1.astNode + is RsStmt.Item -> this.v1.astNode() + } +} + +fun RsType.astNode(): RsNode { + return when (this) { + is RsType.ArrayType -> this.v1.astNode + is RsType.DynTraitType -> this.v1.astNode + is RsType.FnPtrType -> this.v1.astNode + is RsType.ForType -> this.v1.astNode + is RsType.ImplTraitType -> this.v1.astNode + is RsType.InferType -> this.v1.astNode + is RsType.MacroType -> this.v1.astNode + is RsType.NeverType -> this.v1.astNode + is RsType.ParenType -> this.v1.astNode + is RsType.PathType -> this.v1.astNode + is RsType.PtrType -> this.v1.astNode + is RsType.RefType -> this.v1.astNode + is RsType.SliceType -> this.v1.astNode + is RsType.TupleType -> this.v1.astNode + } +} + +fun RsPat.astNode(): RsNode { + return when (this) { + is RsPat.BoxPat -> this.v1.astNode + is RsPat.ConstBlockPat -> this.v1.astNode + is RsPat.IdentPat -> this.v1.astNode + is RsPat.LiteralPat -> this.v1.astNode + is RsPat.MacroPat -> this.v1.astNode + is RsPat.OrPat -> this.v1.astNode + is RsPat.ParenPat -> this.v1.astNode + is RsPat.PathPat -> this.v1.astNode + is RsPat.RangePat -> this.v1.astNode + is RsPat.RecordPat -> this.v1.astNode + is RsPat.RefPat -> this.v1.astNode + is RsPat.RestPat -> this.v1.astNode + is RsPat.SlicePat -> this.v1.astNode + is RsPat.TuplePat -> this.v1.astNode + is RsPat.TupleStructPat -> this.v1.astNode + is RsPat.WildcardPat -> this.v1.astNode + is RsPat.RecordPatField -> this.v1.astNode + } +} diff --git a/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustHandler.kt b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustHandler.kt new file mode 100644 index 00000000000..c7389dd5c9e --- /dev/null +++ b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustHandler.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.frontends.Handler +import de.fraunhofer.aisec.cpg.graph.Node +import de.fraunhofer.aisec.cpg.graph.ProblemNode +import de.fraunhofer.aisec.cpg.helpers.Util +import java.util.function.Supplier +import uniffi.rustast.RsAst + +abstract class RustHandler( + configConstructor: Supplier, + lang: RustLanguageFrontend, +) : Handler(configConstructor, lang) { + /** + * We intentionally override the logic of [Handler.handle] because we do not want the map-based + * logic, but rather want to make use of the Kotlin-when syntax. + * + * We also want non-nullable result handlers + */ + override fun handle(ctx: HandlerNode): ResultNode { + val node = handleNode(ctx) + + frontend.setComment(node, ctx) + frontend.process(ctx, node) + + return node + } + + abstract fun handleNode(node: HandlerNode): ResultNode + + /** + * This function should be called by classes that derive from [RustHandler] to denote, that the + * supplied node (type) is not supported. + */ + protected fun handleNotSupported(node: HandlerNode, name: String): ResultNode { + Util.errorWithFileLocation( + frontend, + node, + log, + "Parsing of type $name is not supported (yet)", + ) + + val cpgNode = this.configConstructor.get() + if (cpgNode is ProblemNode) { + cpgNode.problem = "Parsing of type $name is not supported (yet)" + } + + return cpgNode + } +} diff --git a/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustLanguage.kt b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustLanguage.kt new file mode 100644 index 00000000000..a5a0cfe154c --- /dev/null +++ b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustLanguage.kt @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2022, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.evaluation.ValueEvaluator +import de.fraunhofer.aisec.cpg.frontends.* +import de.fraunhofer.aisec.cpg.graph.HasOverloadedOperation +import de.fraunhofer.aisec.cpg.graph.Node +import de.fraunhofer.aisec.cpg.graph.declarations.Parameter +import de.fraunhofer.aisec.cpg.graph.expressions.BinaryOperator +import de.fraunhofer.aisec.cpg.graph.expressions.UnaryOperator +import de.fraunhofer.aisec.cpg.graph.scopes.Symbol +import de.fraunhofer.aisec.cpg.graph.types.* +import de.fraunhofer.aisec.cpg.helpers.Util.warnWithFileLocation +import de.fraunhofer.aisec.cpg.persistence.Convert +import de.fraunhofer.aisec.cpg.persistence.DoNotPersist +import de.fraunhofer.aisec.cpg.persistence.converters.SimpleNameConverter +import kotlin.reflect.KClass + +/** The Rust language. */ +class RustLanguage : + Language(), + HasShortCircuitOperators, + HasOperatorOverloading, + HasFunctionStyleConstruction { + override val fileExtensions = listOf("rs") + override val namespaceDelimiter = "::" + @Convert(value = SimpleNameConverter::class) + @Transient + override val frontend: KClass = RustLanguageFrontend::class + override val conjunctiveOperators = listOf("&&") + override val disjunctiveOperators = listOf("||") + + override val simpleAssignmentOperators: Set + get() = setOf("=") + + override val compoundAssignmentOperators = + setOf("+=", "-=", "*=", "/=", "%=", "&=", "<<=", ">>=", "^=", "|=") + + @Transient + // https://doc.rust-lang.org/book/appendix-02-operators.html + override val overloadedOperatorNames: + Map, String>, Symbol> = + mapOf( + UnaryOperator::class of "!" to "Not::not", + UnaryOperator::class of "*" to "Deref::deref", + UnaryOperator::class of "-" to "Neg::neg", + BinaryOperator::class of "!=" to "PartialEq::ne", + BinaryOperator::class of "%" to "Rem::rem", + BinaryOperator::class of "%=" to "RemAssign::rem_assign", + BinaryOperator::class of "&" to "BitAnd::bitand", + BinaryOperator::class of "&=" to "BitAndAssign::bitand_assign", + BinaryOperator::class of "*" to "Mul::mul", + BinaryOperator::class of "*=" to "MulAssign::mul_assign", + BinaryOperator::class of "+" to "Add::add", + BinaryOperator::class of "+=" to "AddAssign::add_assign", + BinaryOperator::class of "-" to "Sub::sub", + BinaryOperator::class of "-=" to "SubAssign::sub_assign", + BinaryOperator::class of "/" to "Div::div", + BinaryOperator::class of "/=" to "DivAssign::div_assign", + BinaryOperator::class of "<<" to "Shl::shl", + BinaryOperator::class of "<<=" to "ShlAssign::shl_assign", + BinaryOperator::class of "<" to "PartialOrd::lt", + BinaryOperator::class of "<=" to "PartialOrd::le", + BinaryOperator::class of "==" to "PartialEq::eq", + BinaryOperator::class of ">" to "PartialOrd::gt", + BinaryOperator::class of ">=" to "PartialOrd::ge", + BinaryOperator::class of ">>" to "Shr::shr", + BinaryOperator::class of ">>=" to "ShrAssign::she_assign", + BinaryOperator::class of "^" to "BitXor::bitxor", + BinaryOperator::class of "^=" to "BitXorAssign::bitxor_assign", + BinaryOperator::class of "|" to "BitOr::bitor", + BinaryOperator::class of "|=" to "BitOrAssign::bitor_assign", + // It looks like the following two operators are not directly overloaded but rather by + // the used comparative ops + // BinaryOperator::class of ".." to "PartialOrd", + // BinaryOperator::class of "..=" to "PartialOrd", + + ) + + /** See [Documentation](https://doc.rust-lang.org/stable/std/index.html#primitives). */ + @Transient + override val builtInTypes = + mapOf( + // https://doc.rust-lang.org/stable/reference/types/boolean.html + "bool" to BooleanType(typeName = "bool", language = this), + // https://doc.rust-lang.org/stable/reference/types/numeric.html + "u8" to IntegerType("u8", 8, this, NumericType.Modifier.UNSIGNED), + "u16" to IntegerType("u16", 16, this, NumericType.Modifier.UNSIGNED), + "u32" to IntegerType("u32", 32, this, NumericType.Modifier.UNSIGNED), + "u64" to IntegerType("u64", 64, this, NumericType.Modifier.UNSIGNED), + "u128" to IntegerType("u128", 128, this, NumericType.Modifier.UNSIGNED), + "i8" to IntegerType("i8", 8, this, NumericType.Modifier.SIGNED), + "i16" to IntegerType("i16", 16, this, NumericType.Modifier.SIGNED), + "i32" to IntegerType("i32", 32, this, NumericType.Modifier.SIGNED), + "i64" to IntegerType("i64", 64, this, NumericType.Modifier.SIGNED), + "i128" to IntegerType("i128", 128, this, NumericType.Modifier.SIGNED), + "usize" to + IntegerType( + "usize", + null /* At least 16 bits, but architecture dependent */, + this, + NumericType.Modifier.UNSIGNED, + ), + "isize" to + IntegerType( + "isize", + null /* At least 16 bits, but architecture dependent */, + this, + NumericType.Modifier.UNSIGNED, + ), + "f32" to FloatingPointType("f32", 32, this, NumericType.Modifier.SIGNED), + "f64" to FloatingPointType("f64", 64, this, NumericType.Modifier.SIGNED), + + // https://doc.rust-lang.org/stable/reference/types/textual.html + "char" to IntegerType("char", 32, this, NumericType.Modifier.UNSIGNED), + "str" to + StringType( + typeName = "str", + language = this, + generics = listOf(), + primitive = true, // Debatable whether this is primitive or not + mutable = false, + ), + "String" to + StringType( + typeName = "String", + language = this, + generics = listOf(), + primitive = false, + mutable = true, + ), + // https://doc.rust-lang.org/stable/reference/types/never.html + // Tuples in rust are of fixed size with well-defined element types, so here we just + // create an empty tuple + "!" to ObjectType("Never", listOf(), false, this), + // https://doc.rust-lang.org/stable/reference/types/tuple.html + "()" to TupleType(types = listOf()), + // https://doc.rust-lang.org/stable/reference/types/array.html + // Arrays similarly are of a defined type, but we cannot infer them from the string + // entry of the mapping + // types of slices are noted in the same way as arrays, we therefore use them + // interchangeably + "[]" to + ListType( + typeName = "array", + elementType = ObjectType(), + language = this, + primitive = false, + ), + // https://doc.rust-lang.org/stable/reference/types/function-item.html + "fn()" to + FunctionType( + typeName = "fn", + parameters = listOf(), + returnTypes = listOf(), + language = this, + ), + ) + + @DoNotPersist + override val evaluator: ValueEvaluator + get() = ValueEvaluator() + + override fun propagateTypeOfBinaryOperation( + operatorCode: String?, + lhsType: Type, + rhsType: Type, + hint: BinaryOperator?, + ): Type { + when { + operatorCode == "+" && lhsType is StringType && rhsType is StringType -> { + return builtInTypes.get("String") as Type + } + else -> + return super.propagateTypeOfBinaryOperation(operatorCode, lhsType, rhsType, hint) + } + } + + override fun tryCast( + type: Type, + targetType: Type, + hint: HasType?, + targetHint: HasType?, + ): CastResult { + + if (targetHint is Parameter) { + + if (hint != null && targetType !is UnknownType && targetType !is AutoType) { + val match = super.tryCast(type, targetType, hint, targetHint) + if (match == CastNotPossible) { + warnWithFileLocation( + hint as Node, + log, + "Argument type of call to {} ({}) does not match type annotation on the function parameter ({}), we ignore this", + hint.astParent?.name, + type.name, + targetType.name, + ) + } + } + + return DirectMatch + } + + return super.tryCast(type, targetType, hint, targetHint) + } + + companion object {} +} diff --git a/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustLanguageFrontend.kt b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustLanguageFrontend.kt new file mode 100644 index 00000000000..a4fb6683298 --- /dev/null +++ b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/RustLanguageFrontend.kt @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2021, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.TranslationContext +import de.fraunhofer.aisec.cpg.frontends.Language +import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend +import de.fraunhofer.aisec.cpg.frontends.SupportsParallelParsing +import de.fraunhofer.aisec.cpg.frontends.TranslationException +import de.fraunhofer.aisec.cpg.graph.* +import de.fraunhofer.aisec.cpg.graph.declarations.DeclarationSequence +import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnit +import de.fraunhofer.aisec.cpg.graph.types.TupleType +import de.fraunhofer.aisec.cpg.graph.types.Type +import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation +import de.fraunhofer.aisec.cpg.sarif.Region +import java.io.File +import java.net.URI +import kotlin.collections.plusAssign +import kotlin.math.min +import uniffi.rustast.RsAst +import uniffi.rustast.RsPath +import uniffi.rustast.RsType +import uniffi.rustast.parseRustCode + +/** The [LanguageFrontend] for Rust. It uses the TreeSitter project to generate a RUST AST. */ +@SupportsParallelParsing(true) +class RustLanguageFrontend(ctx: TranslationContext, language: Language) : + LanguageFrontend(ctx, language) { + val lineSeparator = "\n" + private val tokenTypeIndex = 0 + + internal val declarationHandler = DeclarationHandler(this) + internal var statementHandler = StatementHandler(this) + internal var expressionHandler = ExpressionHandler(this) + internal var patternHandler = PatternHandler(this) + + private lateinit var fileContent: String + private lateinit var uri: URI + private var lastLineNumber: Int = -1 + private var lastColumnLength: Int = -1 + + @Throws(TranslationException::class) + override fun parse(file: File): TranslationUnit { + fileContent = file.readText(Charsets.UTF_8) + uri = file.toURI() + + // Extract the file length for later usage + val fileAsLines = fileContent.lines() + lastLineNumber = fileAsLines.size + lastColumnLength = fileAsLines.lastOrNull()?.length ?: -1 + + val rsRustFile = parseRustCode(file.absolutePath) + val tud = + newTranslationUnit(file.path, rawNode = null).apply { + this.location = + PhysicalLocation( + uri = uri, + region = + Region( + startLine = 1, + startColumn = 1, + endLine = lastLineNumber, + endColumn = lastColumnLength, + ), + ) + } + + for (rsItem in rsRustFile?.items ?: listOf()) { + when (rsItem) { + is RsAst.RustItem -> { + val decl = declarationHandler.handle(rsItem) + ((decl as? DeclarationSequence)?.declarations ?: listOf(decl)).forEach { + declItem -> + scopeManager.addDeclaration(declItem) + tud.addDeclaration(declItem) + } + } + else -> log.warn("Not handling ${rsItem.javaClass.simpleName}.") + } + } + + return tud + } + + override fun typeOf(type: RsType): Type { + return when (type) { + is RsType.ArrayType -> typeOf(type.v1.ty.first()).array() + is RsType.TupleType -> TupleType(type.v1.fields.map { t -> typeOf(t) }) + is RsType.ParenType -> typeOf(type.v1.ty.first()) + is RsType.PathType -> typeFromPath(type) + is RsType.PtrType -> typeOf(type.v1.ty.first()).pointer() + is RsType.RefType -> typeOf(type.v1.ty.first()).ref() + is RsType.SliceType -> typeOf(type.v1.ty.first()).array() + is RsType.FnPtrType -> unknownType() + is RsType.InferType -> unknownType() // Todo Auto type? + is RsType.MacroType -> unknownType() + is RsType.DynTraitType -> unknownType() + is RsType.ForType -> unknownType() + is RsType.ImplTraitType -> unknownType() + is RsType.NeverType -> unknownType() + } + } + + fun typeFromPath(typePath: RsType.PathType): Type { + typePath.v1.path?.segment?.nameRef?.let { + language.builtInTypes[it.text]?.let { + return it + } + return objectType(parseName(it.text)) + } + return unknownType() + } + + /** Resolves a [Type] based on its string identifier. */ + fun typeOf(typeId: String): Type { + // Check if the typeId contains a namespace delimiter for qualified types + val name = + if (language.namespaceDelimiter in typeId) { + parseName(typeId) + } else { + // Unqualified name, resolved by the type resolver + typeId + } + + return objectType(name) + } + + override fun codeOf(astNode: RsAst): String? { + return astNode.astNode().text + } + + override fun locationOf(astNode: RsAst): PhysicalLocation? { + val metaAstNode = astNode.astNode() + val contentBefore = + fileContent.substring( + 0, + if (metaAstNode.startOffset.toInt() < fileContent.length) + metaAstNode.startOffset.toInt() + else fileContent.length, + ) + val upTo = contentBefore.split(lineSeparator) + val contentBeforeAndIn = + fileContent.substring(0, min(metaAstNode.endOffset.toInt(), fileContent.length)) + val upToIncluding = contentBeforeAndIn.split(lineSeparator) + return PhysicalLocation( + uri, + Region( + upTo.size, + upTo.last().length + 1, + upToIncluding.size, + upToIncluding.last().length + 1, + ), + ) + } + + fun handlePathForRef(rsPath: RsPath): Name? { + + val qualifierName = + rsPath.qualifier.firstOrNull()?.let { qualifier -> handlePathForRef(qualifier) } + + return rsPath.segment?.nameRef?.text?.let { text -> + newName(text, namespace = qualifierName) + } + } + + /** + * This function replaces the keyword prefixes of a path in a name with the concrete value that + * is defined by the current scope. + */ + fun handleKeywordsInNames(name: Name): Name? { + name.parent?.let { parent -> + return when (name.localName) { + "super" -> handleKeywordsInNames(parent)?.parent + else -> newName(name.localName, namespace = handleKeywordsInNames(parent)) + } + } + + val current = scopeManager.currentNamespace + + return when (name.localName) { + "self" -> current + "super" -> current?.parent + "crate" -> null + else -> name + } + } + + override fun setComment(node: Node, astNode: RsAst) { + node.comment = astNode.astNode().comments + } +} diff --git a/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/StatementHandler.kt b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/StatementHandler.kt new file mode 100644 index 00000000000..0fa8d123ac4 --- /dev/null +++ b/cpg-language-rust/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/rust/StatementHandler.kt @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2023, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.graph.* +import de.fraunhofer.aisec.cpg.graph.declarations.* +import de.fraunhofer.aisec.cpg.graph.expressions.* +import kotlin.collections.plusAssign +import uniffi.rustast.RsAst +import uniffi.rustast.RsBlockExpr +import uniffi.rustast.RsExpr +import uniffi.rustast.RsExprStmt +import uniffi.rustast.RsItem +import uniffi.rustast.RsLetStmt +import uniffi.rustast.RsPat +import uniffi.rustast.RsStmt + +class StatementHandler(frontend: RustLanguageFrontend) : + RustHandler(::ProblemExpression, frontend) { + + override fun handleNode(node: RsAst.RustStmt): Expression { + val unwrapped = node.v1 + return handleNode(unwrapped) + } + + fun handleNode(node: RsStmt): Expression { + return when (node) { + is RsStmt.LetStmt -> handleLetStmt(node.v1) + is RsStmt.ExprStmt -> handleExprStmt(node.v1) + is RsStmt.Item -> handleItem(node.v1) + else -> + newProblemExpression( + problem = "The statement of class ${node.javaClass} is not supported yet", + rawNode = RsAst.RustStmt(node), + ) + } + } + + fun handleLetStmt(letStmt: RsLetStmt): Expression { + val raw = RsAst.RustStmt(RsStmt.LetStmt(letStmt)) + // for us, a let expression is an assigment with a deconstruction + + var initializer = + letStmt.initializer?.let { frontend.expressionHandler.handle(RsAst.RustExpr(it)) } + ?: newProblemExpression("Let statement does not have an initializer", rawNode = raw) + + letStmt.letElse?.let { + return handleLetElse(letStmt, it, raw) + } + + // If the Pattern is a simple identity pattern we make it a declaration statement + (letStmt.pat as? RsPat.IdentPat)?.let { + val declarationStatement = newDeclarationStatement(rawNode = raw) + + val variable = + newVariable( + name = it.v1.name ?: "", + type = letStmt.ty?.let { frontend.typeOf(it) } ?: unknownType(), + rawNode = raw, + ) + + letStmt.initializer?.let { + // Todo If this is a tuple struct, rust analyzer will actually make a call out of it + variable.initializer = frontend.expressionHandler.handle(RsAst.RustExpr(it)) + + // Here, if we have the classical pattern for initializers we set the base of the + // contained member access. This part needs to be made more precise. + val initializingExpressions = + when (variable.initializer) { + is Construction -> (variable.initializer as Construction).arguments + is InitializerList -> (variable.initializer as InitializerList).initializers + else -> listOf() + } + initializingExpressions.forEach { + (it as? Assign)?.lhs?.forEach { + val targetRef = (it as? MemberAccess)?.base ?: it + (targetRef as? Reference)?.let { + if (it.name.toString() == "null") { + it.name = variable.name + } + } + } + } + } + declarationStatement.declarations += variable + + frontend.scopeManager.addDeclaration(variable) + return declarationStatement + } + + val assign: Assign = + newAssign( + operatorCode = "=", + lhs = + letStmt.pat?.let { listOf(frontend.patternHandler.handle(RsAst.RustPat(it))) } + ?: emptyList(), + rhs = + letStmt.initializer?.let { + listOf(frontend.expressionHandler.handle(RsAst.RustExpr(it))) + } ?: emptyList(), + rawNode = raw, + ) + + assign.usedAsExpression = true + return assign + } + + fun handleLetElse(letStmt: RsLetStmt, blockExpr: RsBlockExpr, raw: RsAst.RustStmt): Expression { + + val patternResult = + letStmt.pat?.let { frontend.patternHandler.handle(RsAst.RustPat(it)) } + ?: newProblemExpression("Pattern cannot be parsed.", rawNode = raw) + + val declarations = patternResult.nodes.filterIsInstance() + + val variableDeconstruction = + newObjectDeconstruction(raw).also { obj -> + letStmt.ty?.let { obj.type = frontend.typeOf(it) } + ?: run { obj.type = unknownType() } + declarations.forEach { declStmt -> obj.components += declStmt } + } + + // Handle the pattern, extract the variable declarations, put them into an object + // deconstruction, + // are they already added to the scope?, for every variable, make a tuple expression with a + // reference for each + // variable and put that as the return expression + // Translate the pattern a second time as case expression + + val switch = + newSwitch(rawNode = raw).also { switch -> + switch.selector = + letStmt.initializer?.let { + frontend.expressionHandler.handle(RsAst.RustExpr(it)) + } + ?: newProblemExpression( + "Let statement does not have an initializer", + rawNode = raw, + ) + frontend.scopeManager.enterScope(switch) + + // Create a block to hold two case statements + val caseBlock = newBlock(raw) + caseBlock.usedAsExpression = true + + caseBlock.statements += + newCase(raw).also { value -> + value.caseExpression = + letStmt.pat?.let { frontend.patternHandler.handle(RsAst.RustPat(it)) } + ?: newProblemExpression("Pattern cannot be parsed.", rawNode = raw) + } + + val bindingsList = newInitializerList(rawNode = raw) + + declarations + .flatMap { it.variables } + .forEach { variable -> + val reference = newReference(variable.name.toString(), rawNode = raw) + reference.refersTo = variable + bindingsList.initializers += reference + } + + val breakExpr = newBreak(raw) + breakExpr.expr = bindingsList + breakExpr.usedAsExpression = true + + caseBlock.statements += breakExpr + + caseBlock.statements += newDefault(raw) + caseBlock.statements += + frontend.expressionHandler.handleNode(RsExpr.BlockExpr(blockExpr)) + + switch.statement = caseBlock + + frontend.scopeManager.leaveScope(switch) + + switch.usedAsExpression = true + } + + return newAssign( + operatorCode = "=", + lhs = listOf(variableDeconstruction), + rhs = listOf(switch), + rawNode = raw, + ) + } + + fun handleExprStmt(exprStmt: RsExprStmt): Expression { + val raw = RsAst.RustStmt(RsStmt.ExprStmt(exprStmt)) + + exprStmt.expr.getOrNull(0)?.let { + return frontend.expressionHandler.handle(RsAst.RustExpr(it)).also { + it.usedAsExpression = false + } + } + + return newProblemExpression( + "${exprStmt.javaClass.simpleName} does not contain an expression", + rawNode = raw, + ) + } + + fun handleItem(item: RsItem): Expression { + + val declarationStatement = newDeclarationStatement(rawNode = RsAst.RustItem(item)) + + val declaration = frontend.declarationHandler.handle(RsAst.RustItem(item)) + ((declaration as? DeclarationSequence)?.declarations ?: listOf(declaration)).forEach { + declItem -> + declarationStatement.declarations += declItem + frontend.scopeManager.addDeclaration(declItem) + } + + return declarationStatement + } +} diff --git a/cpg-language-rust/src/main/rust/uniffi/cpgrust/rustast.kt b/cpg-language-rust/src/main/rust/uniffi/cpgrust/rustast.kt new file mode 100644 index 00000000000..301af73baac --- /dev/null +++ b/cpg-language-rust/src/main/rust/uniffi/cpgrust/rustast.kt @@ -0,0 +1,8170 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +@file:Suppress("NAME_SHADOWING") + +package uniffi.rustast + +// Common helper code. +// +// Ideally this would live in a separate .kt file where it can be unittested etc +// in isolation, and perhaps even published as a re-useable package. +// +// However, it's important that the details of how this helper code works (e.g. the +// way that different builtin types are passed across the FFI) exactly match what's +// expected by the Rust code on the other side of the interface. In practice right +// now that means coming from the exact some version of `uniffi` that was used to +// compile the Rust component. The easiest way to ensure this is to bundle the Kotlin +// helpers directly inline like we're doing here. + +import com.sun.jna.Callback +import com.sun.jna.Native +import com.sun.jna.Pointer +import com.sun.jna.Structure +import com.sun.jna.ptr.* +import java.nio.ByteBuffer +import java.nio.ByteOrder +import java.nio.CharBuffer +import java.nio.charset.CodingErrorAction +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.AtomicLong + +// This is a helper for safely working with byte buffers returned from the Rust code. +// A rust-owned buffer is represented by its capacity, its current length, and a +// pointer to the underlying data. + +/** @suppress */ +@Structure.FieldOrder("capacity", "len", "data") +open class RustBuffer : Structure() { + // Note: `capacity` and `len` are actually `ULong` values, but JVM only supports signed values. + // When dealing with these fields, make sure to call `toULong()`. + @JvmField var capacity: Long = 0 + @JvmField var len: Long = 0 + @JvmField var data: Pointer? = null + + class ByValue : RustBuffer(), Structure.ByValue + + class ByReference : RustBuffer(), Structure.ByReference + + internal fun setValue(other: RustBuffer) { + capacity = other.capacity + len = other.len + data = other.data + } + + companion object { + internal fun alloc(size: ULong = 0UL) = + uniffiRustCall() { status -> + // Note: need to convert the size to a `Long` value to make this work with JVM. + UniffiLib.ffi_rustast_rustbuffer_alloc(size.toLong(), status) + } + .also { + if (it.data == null) { + throw RuntimeException( + "RustBuffer.alloc() returned null data pointer (size=${size})" + ) + } + } + + internal fun create(capacity: ULong, len: ULong, data: Pointer?): RustBuffer.ByValue { + var buf = RustBuffer.ByValue() + buf.capacity = capacity.toLong() + buf.len = len.toLong() + buf.data = data + return buf + } + + internal fun free(buf: RustBuffer.ByValue) = + uniffiRustCall() { status -> UniffiLib.ffi_rustast_rustbuffer_free(buf, status) } + } + + @Suppress("TooGenericExceptionThrown") + fun asByteBuffer() = + this.data?.getByteBuffer(0, this.len.toLong())?.also { it.order(ByteOrder.BIG_ENDIAN) } +} + +// This is a helper for safely passing byte references into the rust code. +// It's not actually used at the moment, because there aren't many things that you +// can take a direct pointer to in the JVM, and if we're going to copy something +// then we might as well copy it into a `RustBuffer`. But it's here for API +// completeness. + +@Structure.FieldOrder("len", "data") +internal open class ForeignBytes : Structure() { + @JvmField var len: Int = 0 + @JvmField var data: Pointer? = null + + class ByValue : ForeignBytes(), Structure.ByValue +} + +/** + * The FfiConverter interface handles converter types to and from the FFI + * + * All implementing objects should be public to support external types. When a type is external we + * need to import it's FfiConverter. + * + * @suppress + */ +public interface FfiConverter { + // Convert an FFI type to a Kotlin type + fun lift(value: FfiType): KotlinType + + // Convert an Kotlin type to an FFI type + fun lower(value: KotlinType): FfiType + + // Read a Kotlin type from a `ByteBuffer` + fun read(buf: ByteBuffer): KotlinType + + // Calculate bytes to allocate when creating a `RustBuffer` + // + // This must return at least as many bytes as the write() function will + // write. It can return more bytes than needed, for example when writing + // Strings we can't know the exact bytes needed until we the UTF-8 + // encoding, so we pessimistically allocate the largest size possible (3 + // bytes per codepoint). Allocating extra bytes is not really a big deal + // because the `RustBuffer` is short-lived. + fun allocationSize(value: KotlinType): ULong + + // Write a Kotlin type to a `ByteBuffer` + fun write(value: KotlinType, buf: ByteBuffer) + + // Lower a value into a `RustBuffer` + // + // This method lowers a value into a `RustBuffer` rather than the normal + // FfiType. It's used by the callback interface code. Callback interface + // returns are always serialized into a `RustBuffer` regardless of their + // normal FFI type. + fun lowerIntoRustBuffer(value: KotlinType): RustBuffer.ByValue { + val rbuf = RustBuffer.alloc(allocationSize(value)) + try { + val bbuf = + rbuf.data!!.getByteBuffer(0, rbuf.capacity).also { it.order(ByteOrder.BIG_ENDIAN) } + write(value, bbuf) + rbuf.writeField("len", bbuf.position().toLong()) + return rbuf + } catch (e: Throwable) { + RustBuffer.free(rbuf) + throw e + } + } + + // Lift a value from a `RustBuffer`. + // + // This here mostly because of the symmetry with `lowerIntoRustBuffer()`. + // It's currently only used by the `FfiConverterRustBuffer` class below. + fun liftFromRustBuffer(rbuf: RustBuffer.ByValue): KotlinType { + val byteBuf = rbuf.asByteBuffer()!! + try { + val item = read(byteBuf) + if (byteBuf.hasRemaining()) { + throw RuntimeException( + "junk remaining in buffer after lifting, something is very wrong!!" + ) + } + return item + } finally { + RustBuffer.free(rbuf) + } + } +} + +/** + * FfiConverter that uses `RustBuffer` as the FfiType + * + * @suppress + */ +public interface FfiConverterRustBuffer : FfiConverter { + override fun lift(value: RustBuffer.ByValue) = liftFromRustBuffer(value) + + override fun lower(value: KotlinType) = lowerIntoRustBuffer(value) +} + +// A handful of classes and functions to support the generated data structures. +// This would be a good candidate for isolating in its own ffi-support lib. + +internal const val UNIFFI_CALL_SUCCESS = 0.toByte() +internal const val UNIFFI_CALL_ERROR = 1.toByte() +internal const val UNIFFI_CALL_UNEXPECTED_ERROR = 2.toByte() + +@Structure.FieldOrder("code", "error_buf") +internal open class UniffiRustCallStatus : Structure() { + @JvmField var code: Byte = 0 + @JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue() + + class ByValue : UniffiRustCallStatus(), Structure.ByValue + + fun isSuccess(): Boolean { + return code == UNIFFI_CALL_SUCCESS + } + + fun isError(): Boolean { + return code == UNIFFI_CALL_ERROR + } + + fun isPanic(): Boolean { + return code == UNIFFI_CALL_UNEXPECTED_ERROR + } + + companion object { + fun create(code: Byte, errorBuf: RustBuffer.ByValue): UniffiRustCallStatus.ByValue { + val callStatus = UniffiRustCallStatus.ByValue() + callStatus.code = code + callStatus.error_buf = errorBuf + return callStatus + } + } +} + +class InternalException(message: String) : kotlin.Exception(message) + +/** + * Each top-level error class has a companion object that can lift the error from the call status's + * rust buffer + * + * @suppress + */ +interface UniffiRustCallStatusErrorHandler { + fun lift(error_buf: RustBuffer.ByValue): E +} + +// Helpers for calling Rust +// In practice we usually need to be synchronized to call this safely, so it doesn't +// synchronize itself + +// Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds +// to the Err +private inline fun uniffiRustCallWithError( + errorHandler: UniffiRustCallStatusErrorHandler, + callback: (UniffiRustCallStatus) -> U, +): U { + var status = UniffiRustCallStatus() + val return_value = callback(status) + uniffiCheckCallStatus(errorHandler, status) + return return_value +} + +// Check UniffiRustCallStatus and throw an error if the call wasn't successful +private fun uniffiCheckCallStatus( + errorHandler: UniffiRustCallStatusErrorHandler, + status: UniffiRustCallStatus, +) { + if (status.isSuccess()) { + return + } else if (status.isError()) { + throw errorHandler.lift(status.error_buf) + } else if (status.isPanic()) { + // when the rust code sees a panic, it tries to construct a rustbuffer + // with the message. but if that code panics, then it just sends back + // an empty buffer. + if (status.error_buf.len > 0) { + throw InternalException(FfiConverterString.lift(status.error_buf)) + } else { + throw InternalException("Rust panic") + } + } else { + throw InternalException("Unknown rust call status: $status.code") + } +} + +/** + * UniffiRustCallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR + * + * @suppress + */ +object UniffiNullRustCallStatusErrorHandler : UniffiRustCallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): InternalException { + RustBuffer.free(error_buf) + return InternalException("Unexpected CALL_ERROR") + } +} + +// Call a rust function that returns a plain value +private inline fun uniffiRustCall(callback: (UniffiRustCallStatus) -> U): U { + return uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback) +} + +internal inline fun uniffiTraitInterfaceCall( + callStatus: UniffiRustCallStatus, + makeCall: () -> T, + writeReturn: (T) -> Unit, +) { + try { + writeReturn(makeCall()) + } catch (e: kotlin.Exception) { + callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR + callStatus.error_buf = FfiConverterString.lower(e.toString()) + } +} + +internal inline fun uniffiTraitInterfaceCallWithError( + callStatus: UniffiRustCallStatus, + makeCall: () -> T, + writeReturn: (T) -> Unit, + lowerError: (E) -> RustBuffer.ByValue, +) { + try { + writeReturn(makeCall()) + } catch (e: kotlin.Exception) { + if (e is E) { + callStatus.code = UNIFFI_CALL_ERROR + callStatus.error_buf = lowerError(e) + } else { + callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR + callStatus.error_buf = FfiConverterString.lower(e.toString()) + } + } +} + +// Initial value and increment amount for handles. +// These ensure that Kotlin-generated handles always have the lowest bit set +private const val UNIFFI_HANDLEMAP_INITIAL = 1.toLong() +private const val UNIFFI_HANDLEMAP_DELTA = 2.toLong() + +// Map handles to objects +// +// This is used pass an opaque 64-bit handle representing a foreign object to the Rust code. +internal class UniffiHandleMap { + private val map = ConcurrentHashMap() + // Start + private val counter = java.util.concurrent.atomic.AtomicLong(UNIFFI_HANDLEMAP_INITIAL) + + val size: Int + get() = map.size + + // Insert a new object into the handle map and get a handle for it + fun insert(obj: T): Long { + val handle = counter.getAndAdd(UNIFFI_HANDLEMAP_DELTA) + map.put(handle, obj) + return handle + } + + // Clone a handle, creating a new one + fun clone(handle: Long): Long { + val obj = + map.get(handle) ?: throw InternalException("UniffiHandleMap.clone: Invalid handle") + return insert(obj) + } + + // Get an object from the handle map + fun get(handle: Long): T { + return map.get(handle) ?: throw InternalException("UniffiHandleMap.get: Invalid handle") + } + + // Remove an entry from the handlemap and get the Kotlin object back + fun remove(handle: Long): T { + return map.remove(handle) ?: throw InternalException("UniffiHandleMap: Invalid handle") + } +} + +// Contains loading, initialization code, +// and the FFI Function declarations in a com.sun.jna.Library. +@Synchronized +private fun findLibraryName(componentName: String): String { + val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride") + if (libOverride != null) { + return libOverride + } + return "rustast" +} + +// Define FFI callback types +internal interface UniffiRustFutureContinuationCallback : com.sun.jna.Callback { + fun callback(`data`: Long, `pollResult`: Byte) +} + +internal interface UniffiForeignFutureDroppedCallback : com.sun.jna.Callback { + fun callback(`handle`: Long) +} + +internal interface UniffiCallbackInterfaceFree : com.sun.jna.Callback { + fun callback(`handle`: Long) +} + +internal interface UniffiCallbackInterfaceClone : com.sun.jna.Callback { + fun callback(`handle`: Long): Long +} + +@Structure.FieldOrder("handle", "free") +internal open class UniffiForeignFutureDroppedCallbackStruct( + @JvmField internal var `handle`: Long = 0.toLong(), + @JvmField internal var `free`: UniffiForeignFutureDroppedCallback? = null, +) : Structure() { + class UniffiByValue( + `handle`: Long = 0.toLong(), + `free`: UniffiForeignFutureDroppedCallback? = null, + ) : UniffiForeignFutureDroppedCallbackStruct(`handle`, `free`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureDroppedCallbackStruct) { + `handle` = other.`handle` + `free` = other.`free` + } +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultU8( + @JvmField internal var `returnValue`: Byte = 0.toByte(), + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Byte = 0.toByte(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultU8(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultU8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteU8 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultU8.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultI8( + @JvmField internal var `returnValue`: Byte = 0.toByte(), + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Byte = 0.toByte(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultI8(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultI8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteI8 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultI8.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultU16( + @JvmField internal var `returnValue`: Short = 0.toShort(), + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Short = 0.toShort(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultU16(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultU16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteU16 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultU16.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultI16( + @JvmField internal var `returnValue`: Short = 0.toShort(), + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Short = 0.toShort(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultI16(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultI16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteI16 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultI16.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultU32( + @JvmField internal var `returnValue`: Int = 0, + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Int = 0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultU32(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultU32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteU32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultU32.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultI32( + @JvmField internal var `returnValue`: Int = 0, + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Int = 0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultI32(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultI32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteI32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultI32.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultU64( + @JvmField internal var `returnValue`: Long = 0.toLong(), + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Long = 0.toLong(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultU64(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultU64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteU64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultU64.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultI64( + @JvmField internal var `returnValue`: Long = 0.toLong(), + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Long = 0.toLong(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultI64(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultI64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteI64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultI64.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultF32( + @JvmField internal var `returnValue`: Float = 0.0f, + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Float = 0.0f, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultF32(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultF32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteF32 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultF32.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultF64( + @JvmField internal var `returnValue`: Double = 0.0, + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Double = 0.0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultF64(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultF64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteF64 : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultF64.UniffiByValue) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureResultRustBuffer( + @JvmField internal var `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(), + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureResultRustBuffer(`returnValue`, `callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultRustBuffer) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteRustBuffer : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultRustBuffer.UniffiByValue) +} + +@Structure.FieldOrder("callStatus") +internal open class UniffiForeignFutureResultVoid( + @JvmField + internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue() +) : Structure() { + class UniffiByValue( + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue() + ) : UniffiForeignFutureResultVoid(`callStatus`), Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureResultVoid) { + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback { + fun callback(`callbackData`: Long, `result`: UniffiForeignFutureResultVoid.UniffiByValue) +} + +// A JNA Library to expose the extern-C FFI definitions. +// This is an implementation detail which will be called internally by the public API. + +// For large crates we prevent `MethodTooLargeException` (see #2340) +// N.B. the name of the extension is very misleading, since it is +// rather `InterfaceTooLargeException`, caused by too many methods +// in the interface for large crates. +// +// By splitting the otherwise huge interface into two parts +// * UniffiLib (this) +// * IntegrityCheckingUniffiLib +// And all checksum methods are put into `IntegrityCheckingUniffiLib` +// we allow for ~2x as many methods in the UniffiLib interface. +// +// Note: above all written when we used JNA's `loadIndirect` etc. +// We now use JNA's "direct mapping" - unclear if same considerations apply exactly. +internal object IntegrityCheckingUniffiLib { + init { + Native.register( + IntegrityCheckingUniffiLib::class.java, + findLibraryName(componentName = "rustast"), + ) + uniffiCheckContractApiVersion(this) + uniffiCheckApiChecksums(this) + } + + external fun uniffi_rustast_checksum_func_parse_rust_code(): Short + + external fun ffi_rustast_uniffi_contract_version(): Int +} + +internal object UniffiLib { + + init { + Native.register(UniffiLib::class.java, findLibraryName(componentName = "rustast")) + } + + external fun uniffi_rustast_fn_func_parse_rust_code( + `source`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + external fun ffi_rustast_rustbuffer_alloc( + `size`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + external fun ffi_rustast_rustbuffer_from_bytes( + `bytes`: ForeignBytes.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + external fun ffi_rustast_rustbuffer_free( + `buf`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + external fun ffi_rustast_rustbuffer_reserve( + `buf`: RustBuffer.ByValue, + `additional`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + external fun ffi_rustast_rust_future_poll_u8( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_u8(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_u8(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_u8( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + external fun ffi_rustast_rust_future_poll_i8( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_i8(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_i8(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_i8( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + external fun ffi_rustast_rust_future_poll_u16( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_u16(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_u16(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_u16( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Short + + external fun ffi_rustast_rust_future_poll_i16( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_i16(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_i16(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_i16( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Short + + external fun ffi_rustast_rust_future_poll_u32( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_u32(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_u32(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_u32( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Int + + external fun ffi_rustast_rust_future_poll_i32( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_i32(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_i32(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_i32( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Int + + external fun ffi_rustast_rust_future_poll_u64( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_u64(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_u64(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_u64( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + external fun ffi_rustast_rust_future_poll_i64( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_i64(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_i64(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_i64( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + external fun ffi_rustast_rust_future_poll_f32( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_f32(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_f32(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_f32( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Float + + external fun ffi_rustast_rust_future_poll_f64( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_f64(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_f64(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_f64( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Double + + external fun ffi_rustast_rust_future_poll_rust_buffer( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_rust_buffer(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_rust_buffer(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_rust_buffer( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + external fun ffi_rustast_rust_future_poll_void( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + external fun ffi_rustast_rust_future_cancel_void(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_free_void(`handle`: Long): Unit + + external fun ffi_rustast_rust_future_complete_void( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Unit +} + +private fun uniffiCheckContractApiVersion(lib: IntegrityCheckingUniffiLib) { + // Get the bindings contract version from our ComponentInterface + val bindings_contract_version = 30 + // Get the scaffolding contract version by calling the into the dylib + val scaffolding_contract_version = lib.ffi_rustast_uniffi_contract_version() + if (bindings_contract_version != scaffolding_contract_version) { + throw RuntimeException( + "UniFFI contract version mismatch: try cleaning and rebuilding your project" + ) + } +} + +@Suppress("UNUSED_PARAMETER") +private fun uniffiCheckApiChecksums(lib: IntegrityCheckingUniffiLib) { + if (lib.uniffi_rustast_checksum_func_parse_rust_code() != 45886.toShort()) { + throw RuntimeException( + "UniFFI API checksum mismatch: try cleaning and rebuilding your project" + ) + } +} + +/** @suppress */ +public fun uniffiEnsureInitialized() { + IntegrityCheckingUniffiLib + // UniffiLib() initialized as objects are used, but we still need to explicitly + // reference it so initialization across crates works as expected. + UniffiLib +} + +// Async support + +// Public interface members begin here. + +// Interface implemented by anything that can contain an object reference. +// +// Such types expose a `destroy()` method that must be called to cleanly +// dispose of the contained objects. Failure to call this method may result +// in memory leaks. +// +// The easiest way to ensure this method is called is to use the `.use` +// helper method to execute a block and destroy the object at the end. +interface Disposable { + fun destroy() + + companion object { + fun destroy(vararg args: Any?) { + for (arg in args) { + when (arg) { + is Disposable -> arg.destroy() + is ArrayList<*> -> { + for (idx in arg.indices) { + val element = arg[idx] + if (element is Disposable) { + element.destroy() + } + } + } + is Map<*, *> -> { + for (element in arg.values) { + if (element is Disposable) { + element.destroy() + } + } + } + is Iterable<*> -> { + for (element in arg) { + if (element is Disposable) { + element.destroy() + } + } + } + } + } + } + } +} + +/** @suppress */ +inline fun T.use(block: (T) -> R) = + try { + block(this) + } finally { + try { + // N.B. our implementation is on the nullable type `Disposable?`. + this?.destroy() + } catch (e: Throwable) { + // swallow + } + } + +/** + * Placeholder object used to signal that we're constructing an interface with a FFI handle. + * + * This is the first argument for interface constructors that input a raw handle. It exists is that + * so we can avoid signature conflicts when an interface has a regular constructor than inputs a + * Long. + * + * @suppress + */ +object UniffiWithHandle + +/** + * Used to instantiate an interface without an actual pointer, for fakes in tests, mostly. + * + * @suppress + */ +object NoHandle + +/** @suppress */ +public object FfiConverterUInt : FfiConverter { + override fun lift(value: Int): UInt { + return value.toUInt() + } + + override fun read(buf: ByteBuffer): UInt { + return lift(buf.getInt()) + } + + override fun lower(value: UInt): Int { + return value.toInt() + } + + override fun allocationSize(value: UInt) = 4UL + + override fun write(value: UInt, buf: ByteBuffer) { + buf.putInt(value.toInt()) + } +} + +/** @suppress */ +public object FfiConverterBoolean : FfiConverter { + override fun lift(value: Byte): Boolean { + return value.toInt() != 0 + } + + override fun read(buf: ByteBuffer): Boolean { + return lift(buf.get()) + } + + override fun lower(value: Boolean): Byte { + return if (value) 1.toByte() else 0.toByte() + } + + override fun allocationSize(value: Boolean) = 1UL + + override fun write(value: Boolean, buf: ByteBuffer) { + buf.put(lower(value)) + } +} + +/** @suppress */ +public object FfiConverterString : FfiConverter { + // Note: we don't inherit from FfiConverterRustBuffer, because we use a + // special encoding when lowering/lifting. We can use `RustBuffer.len` to + // store our length and avoid writing it out to the buffer. + override fun lift(value: RustBuffer.ByValue): String { + try { + val byteArr = ByteArray(value.len.toInt()) + value.asByteBuffer()!!.get(byteArr) + return byteArr.toString(Charsets.UTF_8) + } finally { + RustBuffer.free(value) + } + } + + override fun read(buf: ByteBuffer): String { + val len = buf.getInt() + val byteArr = ByteArray(len) + buf.get(byteArr) + return byteArr.toString(Charsets.UTF_8) + } + + fun toUtf8(value: String): ByteBuffer { + // Make sure we don't have invalid UTF-16, check for lone surrogates. + return Charsets.UTF_8.newEncoder().run { + onMalformedInput(CodingErrorAction.REPORT) + encode(CharBuffer.wrap(value)) + } + } + + override fun lower(value: String): RustBuffer.ByValue { + val byteBuf = toUtf8(value) + // Ideally we'd pass these bytes to `ffi_bytebuffer_from_bytes`, but doing so would require + // us + // to copy them into a JNA `Memory`. So we might as well directly copy them into a + // `RustBuffer`. + val rbuf = RustBuffer.alloc(byteBuf.limit().toULong()) + rbuf.asByteBuffer()!!.put(byteBuf) + return rbuf + } + + // We aren't sure exactly how many bytes our string will be once it's UTF-8 + // encoded. Allocate 3 bytes per UTF-16 code unit which will always be + // enough. + override fun allocationSize(value: String): ULong { + val sizeForLength = 4UL + val sizeForString = value.length.toULong() * 3UL + return sizeForLength + sizeForString + } + + override fun write(value: String, buf: ByteBuffer) { + val byteBuf = toUtf8(value) + buf.putInt(byteBuf.limit()) + buf.put(byteBuf) + } +} + +data class RsAbi( + var `astNode`: RsNode, + var `hasExtern`: kotlin.Boolean, + var `stringLiteral`: kotlin.String, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAbi : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAbi { + return RsAbi( + FfiConverterTypeRSNode.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterString.read(buf), + ) + } + + override fun allocationSize(value: RsAbi) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterBoolean.allocationSize(value.`hasExtern`) + + FfiConverterString.allocationSize(value.`stringLiteral`)) + + override fun write(value: RsAbi, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterBoolean.write(value.`hasExtern`, buf) + FfiConverterString.write(value.`stringLiteral`, buf) + } +} + +data class RsArrayExpr( + var `astNode`: RsNode, + var `expressions`: List, + var `repeating`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSArrayExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsArrayExpr { + return RsArrayExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsArrayExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expressions`) + + FfiConverterBoolean.allocationSize(value.`repeating`)) + + override fun write(value: RsArrayExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expressions`, buf) + FfiConverterBoolean.write(value.`repeating`, buf) + } +} + +data class RsArrayType(var `astNode`: RsNode, var `ty`: List, var `constArg`: RsConstArg?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSArrayType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsArrayType { + return RsArrayType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + FfiConverterOptionalTypeRSConstArg.read(buf), + ) + } + + override fun allocationSize(value: RsArrayType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`) + + FfiConverterOptionalTypeRSConstArg.allocationSize(value.`constArg`)) + + override fun write(value: RsArrayType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + FfiConverterOptionalTypeRSConstArg.write(value.`constArg`, buf) + } +} + +data class RsAsmClobberAbi(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmClobberAbi : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmClobberAbi { + return RsAsmClobberAbi(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsAsmClobberAbi) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsAsmClobberAbi, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsAsmConst(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmConst : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmConst { + return RsAsmConst( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsAsmConst) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsAsmConst, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsAsmExpr(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmExpr { + return RsAsmExpr(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsAsmExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsAsmExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsAsmLabel(var `astNode`: RsNode, var `blockExpr`: RsBlockExpr?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmLabel : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmLabel { + return RsAsmLabel( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSBlockExpr.read(buf), + ) + } + + override fun allocationSize(value: RsAsmLabel) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSBlockExpr.allocationSize(value.`blockExpr`)) + + override fun write(value: RsAsmLabel, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSBlockExpr.write(value.`blockExpr`, buf) + } +} + +data class RsAsmOperandNamed(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmOperandNamed : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmOperandNamed { + return RsAsmOperandNamed(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsAsmOperandNamed) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsAsmOperandNamed, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsAsmOptions(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmOptions : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmOptions { + return RsAsmOptions(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsAsmOptions) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsAsmOptions, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsAsmRegOperand(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmRegOperand : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmRegOperand { + return RsAsmRegOperand(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsAsmRegOperand) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsAsmRegOperand, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsAsmSym(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmSym : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmSym { + return RsAsmSym(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsAsmSym) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsAsmSym, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsAssocTypeArg( + var `astNode`: RsNode, + var `constArg`: RsConstArg?, + var `name`: RsNameRef?, + var `paramList`: RsParamList?, + var `retType`: RsType?, + var `returnTypeSyntax`: RsReturnTypeSyntax?, + var `ty`: RsType?, + var `typeBounds`: List, + var `genericArgs`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAssocTypeArg : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAssocTypeArg { + return RsAssocTypeArg( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSConstArg.read(buf), + FfiConverterOptionalTypeRSNameRef.read(buf), + FfiConverterOptionalTypeRSParamList.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + FfiConverterOptionalTypeRSReturnTypeSyntax.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + FfiConverterSequenceTypeRSTypeBound.read(buf), + FfiConverterSequenceTypeRSGenericArg.read(buf), + ) + } + + override fun allocationSize(value: RsAssocTypeArg) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSConstArg.allocationSize(value.`constArg`) + + FfiConverterOptionalTypeRSNameRef.allocationSize(value.`name`) + + FfiConverterOptionalTypeRSParamList.allocationSize(value.`paramList`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`retType`) + + FfiConverterOptionalTypeRSReturnTypeSyntax.allocationSize(value.`returnTypeSyntax`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`) + + FfiConverterSequenceTypeRSTypeBound.allocationSize(value.`typeBounds`) + + FfiConverterSequenceTypeRSGenericArg.allocationSize(value.`genericArgs`)) + + override fun write(value: RsAssocTypeArg, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSConstArg.write(value.`constArg`, buf) + FfiConverterOptionalTypeRSNameRef.write(value.`name`, buf) + FfiConverterOptionalTypeRSParamList.write(value.`paramList`, buf) + FfiConverterOptionalTypeRSType.write(value.`retType`, buf) + FfiConverterOptionalTypeRSReturnTypeSyntax.write(value.`returnTypeSyntax`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + FfiConverterSequenceTypeRSTypeBound.write(value.`typeBounds`, buf) + FfiConverterSequenceTypeRSGenericArg.write(value.`genericArgs`, buf) + } +} + +data class RsAwaitExpr(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAwaitExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAwaitExpr { + return RsAwaitExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsAwaitExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsAwaitExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsBecomeExpr(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSBecomeExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsBecomeExpr { + return RsBecomeExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsBecomeExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsBecomeExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsBinExpr( + var `astNode`: RsNode, + var `expressions`: List, + var `operator`: kotlin.String, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSBinExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsBinExpr { + return RsBinExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterString.read(buf), + ) + } + + override fun allocationSize(value: RsBinExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expressions`) + + FfiConverterString.allocationSize(value.`operator`)) + + override fun write(value: RsBinExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expressions`, buf) + FfiConverterString.write(value.`operator`, buf) + } +} + +data class RsBlockExpr( + var `astNode`: RsNode, + var `stmts`: List, + var `tailExpr`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSBlockExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsBlockExpr { + return RsBlockExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSStmt.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsBlockExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSStmt.allocationSize(value.`stmts`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`tailExpr`)) + + override fun write(value: RsBlockExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSStmt.write(value.`stmts`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`tailExpr`, buf) + } +} + +data class RsBoxPat(var `astNode`: RsNode, var `pat`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSBoxPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsBoxPat { + return RsBoxPat(FfiConverterTypeRSNode.read(buf), FfiConverterSequenceTypeRSPat.read(buf)) + } + + override fun allocationSize(value: RsBoxPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pat`)) + + override fun write(value: RsBoxPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pat`, buf) + } +} + +data class RsBreakExpr( + var `astNode`: RsNode, + var `expr`: List, + var `lifetime`: RsLifetime?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSBreakExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsBreakExpr { + return RsBreakExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterOptionalTypeRSLifetime.read(buf), + ) + } + + override fun allocationSize(value: RsBreakExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterOptionalTypeRSLifetime.allocationSize(value.`lifetime`)) + + override fun write(value: RsBreakExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterOptionalTypeRSLifetime.write(value.`lifetime`, buf) + } +} + +data class RsCallExpr( + var `astNode`: RsNode, + var `expr`: List, + var `arguments`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSCallExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsCallExpr { + return RsCallExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsCallExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`arguments`)) + + override fun write(value: RsCallExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`arguments`, buf) + } +} + +data class RsCastExpr(var `astNode`: RsNode, var `expr`: List, var `ty`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSCastExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsCastExpr { + return RsCastExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsCastExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsCastExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + } +} + +data class RsClosureExpr( + var `astNode`: RsNode, + var `paramList`: List, + var `retType`: List, + var `expressions`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSClosureExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsClosureExpr { + return RsClosureExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSParamList.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsClosureExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSParamList.allocationSize(value.`paramList`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`retType`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expressions`)) + + override fun write(value: RsClosureExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSParamList.write(value.`paramList`, buf) + FfiConverterSequenceTypeRSType.write(value.`retType`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expressions`, buf) + } +} + +data class RsConst( + var `astNode`: RsNode, + var `name`: kotlin.String?, + var `ty`: RsType?, + var `expr`: List, + var `genericParams`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSConst : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsConst { + return RsConst( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + ) + } + + override fun allocationSize(value: RsConst) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericParams`)) + + override fun write(value: RsConst, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericParams`, buf) + } +} + +data class RsConstArg(var `astNode`: RsNode, var `expr`: RsExpr?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSConstArg : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsConstArg { + return RsConstArg( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsConstArg) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsConstArg, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsConstBlockPat(var `astNode`: RsNode, var `blockExpr`: RsBlockExpr?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSConstBlockPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsConstBlockPat { + return RsConstBlockPat( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSBlockExpr.read(buf), + ) + } + + override fun allocationSize(value: RsConstBlockPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSBlockExpr.allocationSize(value.`blockExpr`)) + + override fun write(value: RsConstBlockPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSBlockExpr.write(value.`blockExpr`, buf) + } +} + +data class RsConstParam(var `astNode`: RsNode, var `defaultVal`: RsConstArg?, var `ty`: RsType?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSConstParam : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsConstParam { + return RsConstParam( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSConstArg.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsConstParam) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSConstArg.allocationSize(value.`defaultVal`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsConstParam, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSConstArg.write(value.`defaultVal`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + } +} + +data class RsContinueExpr(var `astNode`: RsNode, var `lifetime`: RsLifetime?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSContinueExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsContinueExpr { + return RsContinueExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSLifetime.read(buf), + ) + } + + override fun allocationSize(value: RsContinueExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSLifetime.allocationSize(value.`lifetime`)) + + override fun write(value: RsContinueExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSLifetime.write(value.`lifetime`, buf) + } +} + +data class RsDynTraitType(var `astNode`: RsNode, var `typeBoundList`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSDynTraitType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsDynTraitType { + return RsDynTraitType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSTypeBound.read(buf), + ) + } + + override fun allocationSize(value: RsDynTraitType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSTypeBound.allocationSize(value.`typeBoundList`)) + + override fun write(value: RsDynTraitType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSTypeBound.write(value.`typeBoundList`, buf) + } +} + +data class RsEnum( + var `astNode`: RsNode, + var `name`: kotlin.String?, + var `variants`: List, + var `genericParams`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSEnum : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsEnum { + return RsEnum( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSVariant.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + ) + } + + override fun allocationSize(value: RsEnum) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSVariant.allocationSize(value.`variants`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericParams`)) + + override fun write(value: RsEnum, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterSequenceTypeRSVariant.write(value.`variants`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericParams`, buf) + } +} + +data class RsExprStmt(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSExprStmt : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsExprStmt { + return RsExprStmt( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsExprStmt) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsExprStmt, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsExternBlock( + var `astNode`: RsNode, + var `externItems`: List, + var `abi`: RsAbi?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSExternBlock : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsExternBlock { + return RsExternBlock( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExternItem.read(buf), + FfiConverterOptionalTypeRSAbi.read(buf), + ) + } + + override fun allocationSize(value: RsExternBlock) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExternItem.allocationSize(value.`externItems`) + + FfiConverterOptionalTypeRSAbi.allocationSize(value.`abi`)) + + override fun write(value: RsExternBlock, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExternItem.write(value.`externItems`, buf) + FfiConverterOptionalTypeRSAbi.write(value.`abi`, buf) + } +} + +data class RsExternCrate( + var `astNode`: RsNode, + var `nameRef`: RsNameRef?, + var `rename`: kotlin.String?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSExternCrate : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsExternCrate { + return RsExternCrate( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSNameRef.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: RsExternCrate) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSNameRef.allocationSize(value.`nameRef`) + + FfiConverterOptionalString.allocationSize(value.`rename`)) + + override fun write(value: RsExternCrate, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSNameRef.write(value.`nameRef`, buf) + FfiConverterOptionalString.write(value.`rename`, buf) + } +} + +data class RsFieldExpr(var `astNode`: RsNode, var `expr`: List, var `nameRef`: RsNameRef?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSFieldExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsFieldExpr { + return RsFieldExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterOptionalTypeRSNameRef.read(buf), + ) + } + + override fun allocationSize(value: RsFieldExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterOptionalTypeRSNameRef.allocationSize(value.`nameRef`)) + + override fun write(value: RsFieldExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterOptionalTypeRSNameRef.write(value.`nameRef`, buf) + } +} + +data class RsFn( + var `astNode`: RsNode, + var `paramList`: RsParamList?, + var `retType`: RsType?, + var `body`: RsBlockExpr?, + var `name`: kotlin.String?, + var `genericParams`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSFn : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsFn { + return RsFn( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSParamList.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + FfiConverterOptionalTypeRSBlockExpr.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + ) + } + + override fun allocationSize(value: RsFn) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSParamList.allocationSize(value.`paramList`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`retType`) + + FfiConverterOptionalTypeRSBlockExpr.allocationSize(value.`body`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericParams`)) + + override fun write(value: RsFn, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSParamList.write(value.`paramList`, buf) + FfiConverterOptionalTypeRSType.write(value.`retType`, buf) + FfiConverterOptionalTypeRSBlockExpr.write(value.`body`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericParams`, buf) + } +} + +data class RsFnPtrType( + var `astNode`: RsNode, + var `paramList`: List, + var `retType`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSFnPtrType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsFnPtrType { + return RsFnPtrType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSParamList.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsFnPtrType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSParamList.allocationSize(value.`paramList`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`retType`)) + + override fun write(value: RsFnPtrType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSParamList.write(value.`paramList`, buf) + FfiConverterSequenceTypeRSType.write(value.`retType`, buf) + } +} + +data class RsForExpr(var `astNode`: RsNode, var `pat`: RsPat?, var `expressions`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSForExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsForExpr { + return RsForExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPat.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsForExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPat.allocationSize(value.`pat`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expressions`)) + + override fun write(value: RsForExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPat.write(value.`pat`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expressions`, buf) + } +} + +data class RsForType( + var `astNode`: RsNode, + var `ty`: List, + var `genericsInFor`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSForType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsForType { + return RsForType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + ) + } + + override fun allocationSize(value: RsForType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericsInFor`)) + + override fun write(value: RsForType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericsInFor`, buf) + } +} + +data class RsFormatArgsExpr( + var `astNode`: RsNode, + var `template`: List, + var `hasPound`: kotlin.Boolean, + var `hasComma`: kotlin.Boolean, + var `hasBuiltin`: kotlin.Boolean, + var `hasFormatArgs`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSFormatArgsExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsFormatArgsExpr { + return RsFormatArgsExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsFormatArgsExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`template`) + + FfiConverterBoolean.allocationSize(value.`hasPound`) + + FfiConverterBoolean.allocationSize(value.`hasComma`) + + FfiConverterBoolean.allocationSize(value.`hasBuiltin`) + + FfiConverterBoolean.allocationSize(value.`hasFormatArgs`)) + + override fun write(value: RsFormatArgsExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`template`, buf) + FfiConverterBoolean.write(value.`hasPound`, buf) + FfiConverterBoolean.write(value.`hasComma`, buf) + FfiConverterBoolean.write(value.`hasBuiltin`, buf) + FfiConverterBoolean.write(value.`hasFormatArgs`, buf) + } +} + +data class RsIdentPat(var `astNode`: RsNode, var `name`: kotlin.String?, var `pat`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSIdentPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsIdentPat { + return RsIdentPat( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSPat.read(buf), + ) + } + + override fun allocationSize(value: RsIdentPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pat`)) + + override fun write(value: RsIdentPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pat`, buf) + } +} + +data class RsIfExpr(var `astNode`: RsNode, var `expressions`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSIfExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsIfExpr { + return RsIfExpr(FfiConverterTypeRSNode.read(buf), FfiConverterSequenceTypeRSExpr.read(buf)) + } + + override fun allocationSize(value: RsIfExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expressions`)) + + override fun write(value: RsIfExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expressions`, buf) + } +} + +data class RsImpl( + var `astNode`: RsNode, + var `items`: List, + var `pathTypes`: List, + var `genericParams`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSImpl : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsImpl { + return RsImpl( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSAssocItem.read(buf), + FfiConverterSequenceTypeRSPathType.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + ) + } + + override fun allocationSize(value: RsImpl) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSAssocItem.allocationSize(value.`items`) + + FfiConverterSequenceTypeRSPathType.allocationSize(value.`pathTypes`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericParams`)) + + override fun write(value: RsImpl, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSAssocItem.write(value.`items`, buf) + FfiConverterSequenceTypeRSPathType.write(value.`pathTypes`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericParams`, buf) + } +} + +data class RsImplTraitType(var `astNode`: RsNode, var `typeBoundList`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSImplTraitType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsImplTraitType { + return RsImplTraitType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSTypeBound.read(buf), + ) + } + + override fun allocationSize(value: RsImplTraitType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSTypeBound.allocationSize(value.`typeBoundList`)) + + override fun write(value: RsImplTraitType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSTypeBound.write(value.`typeBoundList`, buf) + } +} + +data class RsIndexExpr(var `astNode`: RsNode, var `expressions`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSIndexExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsIndexExpr { + return RsIndexExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsIndexExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expressions`)) + + override fun write(value: RsIndexExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expressions`, buf) + } +} + +data class RsInferType(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSInferType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsInferType { + return RsInferType(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsInferType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsInferType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsLetExpr(var `astNode`: RsNode, var `expr`: List, var `pat`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLetExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLetExpr { + return RsLetExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterSequenceTypeRSPat.read(buf), + ) + } + + override fun allocationSize(value: RsLetExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pat`)) + + override fun write(value: RsLetExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pat`, buf) + } +} + +data class RsLetStmt( + var `astNode`: RsNode, + var `initializer`: RsExpr?, + var `letElse`: RsBlockExpr?, + var `pat`: RsPat?, + var `ty`: RsType?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLetStmt : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLetStmt { + return RsLetStmt( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSExpr.read(buf), + FfiConverterOptionalTypeRSBlockExpr.read(buf), + FfiConverterOptionalTypeRSPat.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsLetStmt) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSExpr.allocationSize(value.`initializer`) + + FfiConverterOptionalTypeRSBlockExpr.allocationSize(value.`letElse`) + + FfiConverterOptionalTypeRSPat.allocationSize(value.`pat`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsLetStmt, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSExpr.write(value.`initializer`, buf) + FfiConverterOptionalTypeRSBlockExpr.write(value.`letElse`, buf) + FfiConverterOptionalTypeRSPat.write(value.`pat`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + } +} + +data class RsLifetime(var `astNode`: RsNode, var `name`: kotlin.String) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLifetime : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLifetime { + return RsLifetime(FfiConverterTypeRSNode.read(buf), FfiConverterString.read(buf)) + } + + override fun allocationSize(value: RsLifetime) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterString.allocationSize(value.`name`)) + + override fun write(value: RsLifetime, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterString.write(value.`name`, buf) + } +} + +data class RsLifetimeArg(var `astNode`: RsNode, var `lifetime`: RsLifetime?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLifetimeArg : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLifetimeArg { + return RsLifetimeArg( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSLifetime.read(buf), + ) + } + + override fun allocationSize(value: RsLifetimeArg) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSLifetime.allocationSize(value.`lifetime`)) + + override fun write(value: RsLifetimeArg, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSLifetime.write(value.`lifetime`, buf) + } +} + +data class RsLifetimeParam( + var `astNode`: RsNode, + var `lifetime`: RsLifetime?, + var `typeBoundList`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLifetimeParam : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLifetimeParam { + return RsLifetimeParam( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSLifetime.read(buf), + FfiConverterSequenceTypeRSTypeBound.read(buf), + ) + } + + override fun allocationSize(value: RsLifetimeParam) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSLifetime.allocationSize(value.`lifetime`) + + FfiConverterSequenceTypeRSTypeBound.allocationSize(value.`typeBoundList`)) + + override fun write(value: RsLifetimeParam, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSLifetime.write(value.`lifetime`, buf) + FfiConverterSequenceTypeRSTypeBound.write(value.`typeBoundList`, buf) + } +} + +data class RsLiteral(var `astNode`: RsNode, var `literalType`: RsLiteralType) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLiteral : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLiteral { + return RsLiteral(FfiConverterTypeRSNode.read(buf), FfiConverterTypeRSLiteralType.read(buf)) + } + + override fun allocationSize(value: RsLiteral) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterTypeRSLiteralType.allocationSize(value.`literalType`)) + + override fun write(value: RsLiteral, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterTypeRSLiteralType.write(value.`literalType`, buf) + } +} + +data class RsLiteralPat(var `astNode`: RsNode, var `literal`: RsLiteral?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLiteralPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLiteralPat { + return RsLiteralPat( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSLiteral.read(buf), + ) + } + + override fun allocationSize(value: RsLiteralPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSLiteral.allocationSize(value.`literal`)) + + override fun write(value: RsLiteralPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSLiteral.write(value.`literal`, buf) + } +} + +data class RsLoopExpr( + var `astNode`: RsNode, + var `label`: kotlin.String?, + var `body`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLoopExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLoopExpr { + return RsLoopExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSBlockExpr.read(buf), + ) + } + + override fun allocationSize(value: RsLoopExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`label`) + + FfiConverterSequenceTypeRSBlockExpr.allocationSize(value.`body`)) + + override fun write(value: RsLoopExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`label`, buf) + FfiConverterSequenceTypeRSBlockExpr.write(value.`body`, buf) + } +} + +data class RsMacroCall( + var `astNode`: RsNode, + var `path`: RsPath?, + var `macroString`: kotlin.String, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMacroCall : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMacroCall { + return RsMacroCall( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPath.read(buf), + FfiConverterString.read(buf), + ) + } + + override fun allocationSize(value: RsMacroCall) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPath.allocationSize(value.`path`) + + FfiConverterString.allocationSize(value.`macroString`)) + + override fun write(value: RsMacroCall, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPath.write(value.`path`, buf) + FfiConverterString.write(value.`macroString`, buf) + } +} + +data class RsMacroDef(var `astNode`: RsNode, var `name`: kotlin.String?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMacroDef : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMacroDef { + return RsMacroDef(FfiConverterTypeRSNode.read(buf), FfiConverterOptionalString.read(buf)) + } + + override fun allocationSize(value: RsMacroDef) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`)) + + override fun write(value: RsMacroDef, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + } +} + +data class RsMacroExpr(var `astNode`: RsNode, var `macroCall`: RsMacroCall?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMacroExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMacroExpr { + return RsMacroExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSMacroCall.read(buf), + ) + } + + override fun allocationSize(value: RsMacroExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSMacroCall.allocationSize(value.`macroCall`)) + + override fun write(value: RsMacroExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSMacroCall.write(value.`macroCall`, buf) + } +} + +data class RsMacroPat(var `astNode`: RsNode, var `macroCall`: RsMacroCall?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMacroPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMacroPat { + return RsMacroPat( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSMacroCall.read(buf), + ) + } + + override fun allocationSize(value: RsMacroPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSMacroCall.allocationSize(value.`macroCall`)) + + override fun write(value: RsMacroPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSMacroCall.write(value.`macroCall`, buf) + } +} + +data class RsMacroRules(var `astNode`: RsNode, var `name`: kotlin.String?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMacroRules : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMacroRules { + return RsMacroRules(FfiConverterTypeRSNode.read(buf), FfiConverterOptionalString.read(buf)) + } + + override fun allocationSize(value: RsMacroRules) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`)) + + override fun write(value: RsMacroRules, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + } +} + +data class RsMacroType(var `astNode`: RsNode, var `macroCall`: RsMacroCall?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMacroType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMacroType { + return RsMacroType( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSMacroCall.read(buf), + ) + } + + override fun allocationSize(value: RsMacroType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSMacroCall.allocationSize(value.`macroCall`)) + + override fun write(value: RsMacroType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSMacroCall.write(value.`macroCall`, buf) + } +} + +data class RsMatchArm( + var `astNode`: RsNode, + var `expr`: List, + var `pat`: List, + var `guard`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMatchArm : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMatchArm { + return RsMatchArm( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterSequenceTypeRSPat.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsMatchArm) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pat`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`guard`)) + + override fun write(value: RsMatchArm, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pat`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`guard`, buf) + } +} + +data class RsMatchExpr( + var `astNode`: RsNode, + var `expr`: List, + var `arms`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMatchExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMatchExpr { + return RsMatchExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterSequenceTypeRSMatchArm.read(buf), + ) + } + + override fun allocationSize(value: RsMatchExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterSequenceTypeRSMatchArm.allocationSize(value.`arms`)) + + override fun write(value: RsMatchExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterSequenceTypeRSMatchArm.write(value.`arms`, buf) + } +} + +data class RsMethodCallExpr( + var `astNode`: RsNode, + var `receiver`: List, + var `nameRef`: RsNameRef?, + var `arguments`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSMethodCallExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMethodCallExpr { + return RsMethodCallExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterOptionalTypeRSNameRef.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsMethodCallExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`receiver`) + + FfiConverterOptionalTypeRSNameRef.allocationSize(value.`nameRef`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`arguments`)) + + override fun write(value: RsMethodCallExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`receiver`, buf) + FfiConverterOptionalTypeRSNameRef.write(value.`nameRef`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`arguments`, buf) + } +} + +data class RsModule(var `astNode`: RsNode, var `name`: kotlin.String?, var `items`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSModule : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsModule { + return RsModule( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSItem.read(buf), + ) + } + + override fun allocationSize(value: RsModule) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSItem.allocationSize(value.`items`)) + + override fun write(value: RsModule, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterSequenceTypeRSItem.write(value.`items`, buf) + } +} + +data class RsNameRef( + var `astNode`: RsNode, + var `text`: kotlin.String, + var `ident`: kotlin.String?, + var `intNumberToken`: kotlin.String?, + var `hasCapSelf`: kotlin.Boolean, + var `hasCrate`: kotlin.Boolean, + var `hasSelf`: kotlin.Boolean, + var `hasSuper`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSNameRef : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsNameRef { + return RsNameRef( + FfiConverterTypeRSNode.read(buf), + FfiConverterString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsNameRef) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterString.allocationSize(value.`text`) + + FfiConverterOptionalString.allocationSize(value.`ident`) + + FfiConverterOptionalString.allocationSize(value.`intNumberToken`) + + FfiConverterBoolean.allocationSize(value.`hasCapSelf`) + + FfiConverterBoolean.allocationSize(value.`hasCrate`) + + FfiConverterBoolean.allocationSize(value.`hasSelf`) + + FfiConverterBoolean.allocationSize(value.`hasSuper`)) + + override fun write(value: RsNameRef, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterString.write(value.`text`, buf) + FfiConverterOptionalString.write(value.`ident`, buf) + FfiConverterOptionalString.write(value.`intNumberToken`, buf) + FfiConverterBoolean.write(value.`hasCapSelf`, buf) + FfiConverterBoolean.write(value.`hasCrate`, buf) + FfiConverterBoolean.write(value.`hasSelf`, buf) + FfiConverterBoolean.write(value.`hasSuper`, buf) + } +} + +data class RsNeverType(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSNeverType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsNeverType { + return RsNeverType(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsNeverType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsNeverType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsNode( + var `text`: kotlin.String, + var `startOffset`: kotlin.UInt, + var `endOffset`: kotlin.UInt, + var `comments`: kotlin.String?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSNode : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsNode { + return RsNode( + FfiConverterString.read(buf), + FfiConverterUInt.read(buf), + FfiConverterUInt.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: RsNode) = + (FfiConverterString.allocationSize(value.`text`) + + FfiConverterUInt.allocationSize(value.`startOffset`) + + FfiConverterUInt.allocationSize(value.`endOffset`) + + FfiConverterOptionalString.allocationSize(value.`comments`)) + + override fun write(value: RsNode, buf: ByteBuffer) { + FfiConverterString.write(value.`text`, buf) + FfiConverterUInt.write(value.`startOffset`, buf) + FfiConverterUInt.write(value.`endOffset`, buf) + FfiConverterOptionalString.write(value.`comments`, buf) + } +} + +data class RsOffsetOfExpr( + var `astNode`: RsNode, + var `fields`: List, + var `ty`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSOffsetOfExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsOffsetOfExpr { + return RsOffsetOfExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSNameRef.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsOffsetOfExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSNameRef.allocationSize(value.`fields`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsOffsetOfExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSNameRef.write(value.`fields`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + } +} + +data class RsOrPat(var `astNode`: RsNode, var `pats`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSOrPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsOrPat { + return RsOrPat(FfiConverterTypeRSNode.read(buf), FfiConverterSequenceTypeRSPat.read(buf)) + } + + override fun allocationSize(value: RsOrPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pats`)) + + override fun write(value: RsOrPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pats`, buf) + } +} + +data class RsParam(var `astNode`: RsNode, var `pat`: RsPat?, var `ty`: RsType?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSParam : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsParam { + return RsParam( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPat.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsParam) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPat.allocationSize(value.`pat`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsParam, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPat.write(value.`pat`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + } +} + +data class RsParamList( + var `astNode`: RsNode, + var `params`: List, + var `selfParam`: RsSelfParam?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSParamList : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsParamList { + return RsParamList( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSParam.read(buf), + FfiConverterOptionalTypeRSSelfParam.read(buf), + ) + } + + override fun allocationSize(value: RsParamList) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSParam.allocationSize(value.`params`) + + FfiConverterOptionalTypeRSSelfParam.allocationSize(value.`selfParam`)) + + override fun write(value: RsParamList, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSParam.write(value.`params`, buf) + FfiConverterOptionalTypeRSSelfParam.write(value.`selfParam`, buf) + } +} + +data class RsParenExpr(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSParenExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsParenExpr { + return RsParenExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsParenExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsParenExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsParenPat(var `astNode`: RsNode, var `pat`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSParenPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsParenPat { + return RsParenPat(FfiConverterTypeRSNode.read(buf), FfiConverterSequenceTypeRSPat.read(buf)) + } + + override fun allocationSize(value: RsParenPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pat`)) + + override fun write(value: RsParenPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pat`, buf) + } +} + +data class RsParenType(var `astNode`: RsNode, var `ty`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSParenType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsParenType { + return RsParenType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsParenType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsParenType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + } +} + +data class RsPath( + var `astNode`: RsNode, + var `segment`: RsPathSegment?, + var `qualifier`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSPath : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPath { + return RsPath( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPathSegment.read(buf), + FfiConverterSequenceTypeRSPath.read(buf), + ) + } + + override fun allocationSize(value: RsPath) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPathSegment.allocationSize(value.`segment`) + + FfiConverterSequenceTypeRSPath.allocationSize(value.`qualifier`)) + + override fun write(value: RsPath, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPathSegment.write(value.`segment`, buf) + FfiConverterSequenceTypeRSPath.write(value.`qualifier`, buf) + } +} + +data class RsPathExpr(var `astNode`: RsNode, var `path`: RsPath?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSPathExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPathExpr { + return RsPathExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPath.read(buf), + ) + } + + override fun allocationSize(value: RsPathExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPath.allocationSize(value.`path`)) + + override fun write(value: RsPathExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPath.write(value.`path`, buf) + } +} + +data class RsPathPat(var `astNode`: RsNode, var `path`: RsPath?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSPathPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPathPat { + return RsPathPat(FfiConverterTypeRSNode.read(buf), FfiConverterOptionalTypeRSPath.read(buf)) + } + + override fun allocationSize(value: RsPathPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPath.allocationSize(value.`path`)) + + override fun write(value: RsPathPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPath.write(value.`path`, buf) + } +} + +data class RsPathSegment( + var `astNode`: RsNode, + var `nameRef`: RsNameRef?, + var `typeArgs`: List, + var `retType`: List, + var `retTypeSyntax`: RsReturnTypeSyntax?, + var `tyAnchor`: RsTypeAnchor?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSPathSegment : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPathSegment { + return RsPathSegment( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSNameRef.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + FfiConverterOptionalTypeRSReturnTypeSyntax.read(buf), + FfiConverterOptionalTypeRSTypeAnchor.read(buf), + ) + } + + override fun allocationSize(value: RsPathSegment) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSNameRef.allocationSize(value.`nameRef`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`typeArgs`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`retType`) + + FfiConverterOptionalTypeRSReturnTypeSyntax.allocationSize(value.`retTypeSyntax`) + + FfiConverterOptionalTypeRSTypeAnchor.allocationSize(value.`tyAnchor`)) + + override fun write(value: RsPathSegment, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSNameRef.write(value.`nameRef`, buf) + FfiConverterSequenceTypeRSType.write(value.`typeArgs`, buf) + FfiConverterSequenceTypeRSType.write(value.`retType`, buf) + FfiConverterOptionalTypeRSReturnTypeSyntax.write(value.`retTypeSyntax`, buf) + FfiConverterOptionalTypeRSTypeAnchor.write(value.`tyAnchor`, buf) + } +} + +data class RsPathType(var `astNode`: RsNode, var `path`: RsPath?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSPathType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPathType { + return RsPathType( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPath.read(buf), + ) + } + + override fun allocationSize(value: RsPathType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPath.allocationSize(value.`path`)) + + override fun write(value: RsPathType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPath.write(value.`path`, buf) + } +} + +data class RsPrefixExpr( + var `astNode`: RsNode, + var `operator`: kotlin.String, + var `expr`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSPrefixExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPrefixExpr { + return RsPrefixExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterString.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsPrefixExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterString.allocationSize(value.`operator`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsPrefixExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterString.write(value.`operator`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsProblem(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSProblem : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsProblem { + return RsProblem(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsProblem) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsProblem, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsPtrType( + var `astNode`: RsNode, + var `ty`: List, + var `hasStar`: kotlin.Boolean, + var `isConst`: kotlin.Boolean, + var `isMut`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSPtrType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPtrType { + return RsPtrType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsPtrType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`) + + FfiConverterBoolean.allocationSize(value.`hasStar`) + + FfiConverterBoolean.allocationSize(value.`isConst`) + + FfiConverterBoolean.allocationSize(value.`isMut`)) + + override fun write(value: RsPtrType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + FfiConverterBoolean.write(value.`hasStar`, buf) + FfiConverterBoolean.write(value.`isConst`, buf) + FfiConverterBoolean.write(value.`isMut`, buf) + } +} + +data class RsRangeExpr( + var `astNode`: RsNode, + var `expressions`: List, + var `operator`: kotlin.String, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRangeExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRangeExpr { + return RsRangeExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterString.read(buf), + ) + } + + override fun allocationSize(value: RsRangeExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expressions`) + + FfiConverterString.allocationSize(value.`operator`)) + + override fun write(value: RsRangeExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expressions`, buf) + FfiConverterString.write(value.`operator`, buf) + } +} + +data class RsRangePat( + var `astNode`: RsNode, + var `patterns`: List, + var `operator`: kotlin.String, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRangePat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRangePat { + return RsRangePat( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSPat.read(buf), + FfiConverterString.read(buf), + ) + } + + override fun allocationSize(value: RsRangePat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`patterns`) + + FfiConverterString.allocationSize(value.`operator`)) + + override fun write(value: RsRangePat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSPat.write(value.`patterns`, buf) + FfiConverterString.write(value.`operator`, buf) + } +} + +data class RsRecordExpr( + var `astNode`: RsNode, + var `path`: RsPath?, + var `fields`: List, + var `spread`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRecordExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRecordExpr { + return RsRecordExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPath.read(buf), + FfiConverterSequenceTypeRSRecordExprField.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsRecordExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPath.allocationSize(value.`path`) + + FfiConverterSequenceTypeRSRecordExprField.allocationSize(value.`fields`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`spread`)) + + override fun write(value: RsRecordExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPath.write(value.`path`, buf) + FfiConverterSequenceTypeRSRecordExprField.write(value.`fields`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`spread`, buf) + } +} + +data class RsRecordExprField( + var `astNode`: RsNode, + var `name`: RsNameRef?, + var `expr`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRecordExprField : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRecordExprField { + return RsRecordExprField( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSNameRef.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsRecordExprField) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSNameRef.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsRecordExprField, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSNameRef.write(value.`name`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsRecordField( + var `astNode`: RsNode, + var `fieldType`: RsType?, + var `expr`: RsExpr?, + var `name`: kotlin.String?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRecordField : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRecordField { + return RsRecordField( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + FfiConverterOptionalTypeRSExpr.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: RsRecordField) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`fieldType`) + + FfiConverterOptionalTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterOptionalString.allocationSize(value.`name`)) + + override fun write(value: RsRecordField, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSType.write(value.`fieldType`, buf) + FfiConverterOptionalTypeRSExpr.write(value.`expr`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + } +} + +data class RsRecordFieldList(var `astNode`: RsNode, var `fields`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRecordFieldList : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRecordFieldList { + return RsRecordFieldList( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSRecordField.read(buf), + ) + } + + override fun allocationSize(value: RsRecordFieldList) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSRecordField.allocationSize(value.`fields`)) + + override fun write(value: RsRecordFieldList, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSRecordField.write(value.`fields`, buf) + } +} + +data class RsRecordPat( + var `astNode`: RsNode, + var `path`: RsPath?, + var `fields`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRecordPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRecordPat { + return RsRecordPat( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPath.read(buf), + FfiConverterSequenceTypeRSRecordPatField.read(buf), + ) + } + + override fun allocationSize(value: RsRecordPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPath.allocationSize(value.`path`) + + FfiConverterSequenceTypeRSRecordPatField.allocationSize(value.`fields`)) + + override fun write(value: RsRecordPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPath.write(value.`path`, buf) + FfiConverterSequenceTypeRSRecordPatField.write(value.`fields`, buf) + } +} + +data class RsRecordPatField(var `astNode`: RsNode, var `name`: RsNameRef?, var `pat`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRecordPatField : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRecordPatField { + return RsRecordPatField( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSNameRef.read(buf), + FfiConverterSequenceTypeRSPat.read(buf), + ) + } + + override fun allocationSize(value: RsRecordPatField) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSNameRef.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pat`)) + + override fun write(value: RsRecordPatField, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSNameRef.write(value.`name`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pat`, buf) + } +} + +data class RsRefExpr( + var `astNode`: RsNode, + var `expr`: List, + var `mutable`: kotlin.Boolean, + var `isRef`: kotlin.Boolean, + var `isConst`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRefExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRefExpr { + return RsRefExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsRefExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterBoolean.allocationSize(value.`mutable`) + + FfiConverterBoolean.allocationSize(value.`isRef`) + + FfiConverterBoolean.allocationSize(value.`isConst`)) + + override fun write(value: RsRefExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterBoolean.write(value.`mutable`, buf) + FfiConverterBoolean.write(value.`isRef`, buf) + FfiConverterBoolean.write(value.`isConst`, buf) + } +} + +data class RsRefPat( + var `astNode`: RsNode, + var `pat`: List, + var `mutable`: kotlin.Boolean, + var `isRef`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRefPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRefPat { + return RsRefPat( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSPat.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsRefPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pat`) + + FfiConverterBoolean.allocationSize(value.`mutable`) + + FfiConverterBoolean.allocationSize(value.`isRef`)) + + override fun write(value: RsRefPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pat`, buf) + FfiConverterBoolean.write(value.`mutable`, buf) + FfiConverterBoolean.write(value.`isRef`, buf) + } +} + +data class RsRefType( + var `astNode`: RsNode, + var `lifetime`: RsLifetime?, + var `ty`: List, + var `hasAmp`: kotlin.Boolean, + var `hasMut`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRefType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRefType { + return RsRefType( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSLifetime.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsRefType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSLifetime.allocationSize(value.`lifetime`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`) + + FfiConverterBoolean.allocationSize(value.`hasAmp`) + + FfiConverterBoolean.allocationSize(value.`hasMut`)) + + override fun write(value: RsRefType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSLifetime.write(value.`lifetime`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + FfiConverterBoolean.write(value.`hasAmp`, buf) + FfiConverterBoolean.write(value.`hasMut`, buf) + } +} + +data class RsRestPat(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSRestPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRestPat { + return RsRestPat(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsRestPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsRestPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsReturnExpr(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSReturnExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsReturnExpr { + return RsReturnExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsReturnExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsReturnExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsReturnTypeSyntax( + var `astNode`: RsNode, + var `lParen`: kotlin.Boolean, + var `rParen`: kotlin.Boolean, + var `dotdot`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSReturnTypeSyntax : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsReturnTypeSyntax { + return RsReturnTypeSyntax( + FfiConverterTypeRSNode.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsReturnTypeSyntax) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterBoolean.allocationSize(value.`lParen`) + + FfiConverterBoolean.allocationSize(value.`rParen`) + + FfiConverterBoolean.allocationSize(value.`dotdot`)) + + override fun write(value: RsReturnTypeSyntax, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterBoolean.write(value.`lParen`, buf) + FfiConverterBoolean.write(value.`rParen`, buf) + FfiConverterBoolean.write(value.`dotdot`, buf) + } +} + +data class RsSelfParam(var `astNode`: RsNode, var `ty`: RsType?, var `lifetime`: RsLifetime?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSSelfParam : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsSelfParam { + return RsSelfParam( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + FfiConverterOptionalTypeRSLifetime.read(buf), + ) + } + + override fun allocationSize(value: RsSelfParam) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`) + + FfiConverterOptionalTypeRSLifetime.allocationSize(value.`lifetime`)) + + override fun write(value: RsSelfParam, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + FfiConverterOptionalTypeRSLifetime.write(value.`lifetime`, buf) + } +} + +data class RsSlicePat(var `astNode`: RsNode, var `pats`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSSlicePat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsSlicePat { + return RsSlicePat(FfiConverterTypeRSNode.read(buf), FfiConverterSequenceTypeRSPat.read(buf)) + } + + override fun allocationSize(value: RsSlicePat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`pats`)) + + override fun write(value: RsSlicePat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSPat.write(value.`pats`, buf) + } +} + +data class RsSliceType(var `astNode`: RsNode, var `ty`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSSliceType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsSliceType { + return RsSliceType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsSliceType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsSliceType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + } +} + +data class RsSourceFile( + var `astNode`: RsNode, + var `path`: kotlin.String, + var `items`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSSourceFile : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsSourceFile { + return RsSourceFile( + FfiConverterTypeRSNode.read(buf), + FfiConverterString.read(buf), + FfiConverterSequenceTypeRSAst.read(buf), + ) + } + + override fun allocationSize(value: RsSourceFile) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterString.allocationSize(value.`path`) + + FfiConverterSequenceTypeRSAst.allocationSize(value.`items`)) + + override fun write(value: RsSourceFile, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterString.write(value.`path`, buf) + FfiConverterSequenceTypeRSAst.write(value.`items`, buf) + } +} + +data class RsStatic(var `astNode`: RsNode, var `name`: kotlin.String?, var `ty`: RsType?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSStatic : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsStatic { + return RsStatic( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsStatic) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsStatic, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + } +} + +data class RsStruct( + var `astNode`: RsNode, + var `name`: kotlin.String?, + var `fieldList`: RsFieldList?, + var `genericParams`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSStruct : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsStruct { + return RsStruct( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalTypeRSFieldList.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + ) + } + + override fun allocationSize(value: RsStruct) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterOptionalTypeRSFieldList.allocationSize(value.`fieldList`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericParams`)) + + override fun write(value: RsStruct, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterOptionalTypeRSFieldList.write(value.`fieldList`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericParams`, buf) + } +} + +data class RsTrait( + var `astNode`: RsNode, + var `name`: kotlin.String?, + var `items`: List, + var `genericParams`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTrait : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTrait { + return RsTrait( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSAssocItem.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + ) + } + + override fun allocationSize(value: RsTrait) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSAssocItem.allocationSize(value.`items`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericParams`)) + + override fun write(value: RsTrait, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterSequenceTypeRSAssocItem.write(value.`items`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericParams`, buf) + } +} + +data class RsTryExpr(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTryExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTryExpr { + return RsTryExpr(FfiConverterTypeRSNode.read(buf), FfiConverterSequenceTypeRSExpr.read(buf)) + } + + override fun allocationSize(value: RsTryExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsTryExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsTupleExpr(var `astNode`: RsNode, var `exprs`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTupleExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTupleExpr { + return RsTupleExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsTupleExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`exprs`)) + + override fun write(value: RsTupleExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`exprs`, buf) + } +} + +data class RsTupleField(var `astNode`: RsNode, var `fieldType`: RsType?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTupleField : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTupleField { + return RsTupleField( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsTupleField) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`fieldType`)) + + override fun write(value: RsTupleField, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSType.write(value.`fieldType`, buf) + } +} + +data class RsTupleFieldList(var `astNode`: RsNode, var `fields`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTupleFieldList : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTupleFieldList { + return RsTupleFieldList( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSTupleField.read(buf), + ) + } + + override fun allocationSize(value: RsTupleFieldList) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSTupleField.allocationSize(value.`fields`)) + + override fun write(value: RsTupleFieldList, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSTupleField.write(value.`fields`, buf) + } +} + +data class RsTuplePat(var `astNode`: RsNode, var `fields`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTuplePat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTuplePat { + return RsTuplePat(FfiConverterTypeRSNode.read(buf), FfiConverterSequenceTypeRSPat.read(buf)) + } + + override fun allocationSize(value: RsTuplePat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`fields`)) + + override fun write(value: RsTuplePat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSPat.write(value.`fields`, buf) + } +} + +data class RsTupleStructPat(var `astNode`: RsNode, var `path`: RsPath?, var `fields`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTupleStructPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTupleStructPat { + return RsTupleStructPat( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPath.read(buf), + FfiConverterSequenceTypeRSPat.read(buf), + ) + } + + override fun allocationSize(value: RsTupleStructPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPath.allocationSize(value.`path`) + + FfiConverterSequenceTypeRSPat.allocationSize(value.`fields`)) + + override fun write(value: RsTupleStructPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPath.write(value.`path`, buf) + FfiConverterSequenceTypeRSPat.write(value.`fields`, buf) + } +} + +data class RsTupleType(var `astNode`: RsNode, var `fields`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTupleType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTupleType { + return RsTupleType( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsTupleType) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`fields`)) + + override fun write(value: RsTupleType, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSType.write(value.`fields`, buf) + } +} + +data class RsTypeAlias( + var `astNode`: RsNode, + var `name`: kotlin.String?, + var `ty`: RsType?, + var `typeBoundList`: List, + var `genericParams`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTypeAlias : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTypeAlias { + return RsTypeAlias( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + FfiConverterSequenceTypeRSTypeBound.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + ) + } + + override fun allocationSize(value: RsTypeAlias) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`) + + FfiConverterSequenceTypeRSTypeBound.allocationSize(value.`typeBoundList`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericParams`)) + + override fun write(value: RsTypeAlias, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + FfiConverterSequenceTypeRSTypeBound.write(value.`typeBoundList`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericParams`, buf) + } +} + +data class RsTypeAnchor( + var `astNode`: RsNode, + var `pathTy`: List, + var `ty`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTypeAnchor : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTypeAnchor { + return RsTypeAnchor( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSPathType.read(buf), + FfiConverterSequenceTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsTypeAnchor) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSPathType.allocationSize(value.`pathTy`) + + FfiConverterSequenceTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsTypeAnchor, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSPathType.write(value.`pathTy`, buf) + FfiConverterSequenceTypeRSType.write(value.`ty`, buf) + } +} + +data class RsTypeArg(var `astNode`: RsNode, var `ty`: RsType?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTypeArg : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTypeArg { + return RsTypeArg(FfiConverterTypeRSNode.read(buf), FfiConverterOptionalTypeRSType.read(buf)) + } + + override fun allocationSize(value: RsTypeArg) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`)) + + override fun write(value: RsTypeArg, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + } +} + +data class RsTypeBound( + var `astNode`: RsNode, + var `ty`: RsType?, + var `genericsInFor`: List, + var `lifetime`: RsLifetime?, + var `boundGenericArgs`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTypeBound : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTypeBound { + return RsTypeBound( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + FfiConverterOptionalTypeRSLifetime.read(buf), + FfiConverterSequenceTypeRSUseBoundGenericArg.read(buf), + ) + } + + override fun allocationSize(value: RsTypeBound) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`ty`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericsInFor`) + + FfiConverterOptionalTypeRSLifetime.allocationSize(value.`lifetime`) + + FfiConverterSequenceTypeRSUseBoundGenericArg.allocationSize(value.`boundGenericArgs`)) + + override fun write(value: RsTypeBound, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSType.write(value.`ty`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericsInFor`, buf) + FfiConverterOptionalTypeRSLifetime.write(value.`lifetime`, buf) + FfiConverterSequenceTypeRSUseBoundGenericArg.write(value.`boundGenericArgs`, buf) + } +} + +data class RsTypeParam( + var `astNode`: RsNode, + var `name`: kotlin.String?, + var `typeBoundList`: List, + var `defaultType`: RsType?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSTypeParam : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTypeParam { + return RsTypeParam( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSTypeBound.read(buf), + FfiConverterOptionalTypeRSType.read(buf), + ) + } + + override fun allocationSize(value: RsTypeParam) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSTypeBound.allocationSize(value.`typeBoundList`) + + FfiConverterOptionalTypeRSType.allocationSize(value.`defaultType`)) + + override fun write(value: RsTypeParam, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterSequenceTypeRSTypeBound.write(value.`typeBoundList`, buf) + FfiConverterOptionalTypeRSType.write(value.`defaultType`, buf) + } +} + +data class RsUnderscoreExpr(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSUnderscoreExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsUnderscoreExpr { + return RsUnderscoreExpr(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsUnderscoreExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsUnderscoreExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsUnion( + var `astNode`: RsNode, + var `genericParams`: List, + var `name`: kotlin.String?, + var `fieldList`: RsRecordFieldList?, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSUnion : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsUnion { + return RsUnion( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSGenericParam.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalTypeRSRecordFieldList.read(buf), + ) + } + + override fun allocationSize(value: RsUnion) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSGenericParam.allocationSize(value.`genericParams`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterOptionalTypeRSRecordFieldList.allocationSize(value.`fieldList`)) + + override fun write(value: RsUnion, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSGenericParam.write(value.`genericParams`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterOptionalTypeRSRecordFieldList.write(value.`fieldList`, buf) + } +} + +data class RsUse(var `astNode`: RsNode, var `useTree`: RsUseTree?) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSUse : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsUse { + return RsUse(FfiConverterTypeRSNode.read(buf), FfiConverterOptionalTypeRSUseTree.read(buf)) + } + + override fun allocationSize(value: RsUse) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSUseTree.allocationSize(value.`useTree`)) + + override fun write(value: RsUse, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSUseTree.write(value.`useTree`, buf) + } +} + +data class RsUseTree( + var `astNode`: RsNode, + var `path`: RsPath?, + var `rename`: kotlin.String?, + var `useTrees`: List, + var `star`: kotlin.Boolean, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSUseTree : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsUseTree { + return RsUseTree( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalTypeRSPath.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSUseTree.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + override fun allocationSize(value: RsUseTree) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalTypeRSPath.allocationSize(value.`path`) + + FfiConverterOptionalString.allocationSize(value.`rename`) + + FfiConverterSequenceTypeRSUseTree.allocationSize(value.`useTrees`) + + FfiConverterBoolean.allocationSize(value.`star`)) + + override fun write(value: RsUseTree, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalTypeRSPath.write(value.`path`, buf) + FfiConverterOptionalString.write(value.`rename`, buf) + FfiConverterSequenceTypeRSUseTree.write(value.`useTrees`, buf) + FfiConverterBoolean.write(value.`star`, buf) + } +} + +data class RsVariant( + var `astNode`: RsNode, + var `name`: kotlin.String?, + var `expr`: List, + var `fields`: List, +) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSVariant : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsVariant { + return RsVariant( + FfiConverterTypeRSNode.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + FfiConverterSequenceTypeRSFieldList.read(buf), + ) + } + + override fun allocationSize(value: RsVariant) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterOptionalString.allocationSize(value.`name`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`) + + FfiConverterSequenceTypeRSFieldList.allocationSize(value.`fields`)) + + override fun write(value: RsVariant, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterOptionalString.write(value.`name`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + FfiConverterSequenceTypeRSFieldList.write(value.`fields`, buf) + } +} + +data class RsWhileExpr(var `astNode`: RsNode, var `expressions`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSWhileExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsWhileExpr { + return RsWhileExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsWhileExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expressions`)) + + override fun write(value: RsWhileExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expressions`, buf) + } +} + +data class RsWildcardPat(var `astNode`: RsNode) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSWildcardPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsWildcardPat { + return RsWildcardPat(FfiConverterTypeRSNode.read(buf)) + } + + override fun allocationSize(value: RsWildcardPat) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`)) + + override fun write(value: RsWildcardPat, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + } +} + +data class RsYeetExpr(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSYeetExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsYeetExpr { + return RsYeetExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsYeetExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsYeetExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +data class RsYieldExpr(var `astNode`: RsNode, var `expr`: List) { + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSYieldExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsYieldExpr { + return RsYieldExpr( + FfiConverterTypeRSNode.read(buf), + FfiConverterSequenceTypeRSExpr.read(buf), + ) + } + + override fun allocationSize(value: RsYieldExpr) = + (FfiConverterTypeRSNode.allocationSize(value.`astNode`) + + FfiConverterSequenceTypeRSExpr.allocationSize(value.`expr`)) + + override fun write(value: RsYieldExpr, buf: ByteBuffer) { + FfiConverterTypeRSNode.write(value.`astNode`, buf) + FfiConverterSequenceTypeRSExpr.write(value.`expr`, buf) + } +} + +sealed class RsAdt { + + data class Enum(val v1: RsEnum) : RsAdt() { + + companion object + } + + data class Struct(val v1: RsStruct) : RsAdt() { + + companion object + } + + data class Union(val v1: RsUnion) : RsAdt() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAdt : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAdt { + return when (buf.getInt()) { + 1 -> RsAdt.Enum(FfiConverterTypeRSEnum.read(buf)) + 2 -> RsAdt.Struct(FfiConverterTypeRSStruct.read(buf)) + 3 -> RsAdt.Union(FfiConverterTypeRSUnion.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsAdt) = + when (value) { + is RsAdt.Enum -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSEnum.allocationSize(value.v1)) + } + is RsAdt.Struct -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSStruct.allocationSize(value.v1)) + } + is RsAdt.Union -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSUnion.allocationSize(value.v1)) + } + } + + override fun write(value: RsAdt, buf: ByteBuffer) { + when (value) { + is RsAdt.Enum -> { + buf.putInt(1) + FfiConverterTypeRSEnum.write(value.v1, buf) + Unit + } + is RsAdt.Struct -> { + buf.putInt(2) + FfiConverterTypeRSStruct.write(value.v1, buf) + Unit + } + is RsAdt.Union -> { + buf.putInt(3) + FfiConverterTypeRSUnion.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsAsmOperand { + + data class AsmConst(val v1: RsAsmConst) : RsAsmOperand() { + + companion object + } + + data class AsmLabel(val v1: RsAsmLabel) : RsAsmOperand() { + + companion object + } + + data class AsmRegOperand(val v1: RsAsmRegOperand) : RsAsmOperand() { + + companion object + } + + data class AsmSym(val v1: RsAsmSym) : RsAsmOperand() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmOperand : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmOperand { + return when (buf.getInt()) { + 1 -> RsAsmOperand.AsmConst(FfiConverterTypeRSAsmConst.read(buf)) + 2 -> RsAsmOperand.AsmLabel(FfiConverterTypeRSAsmLabel.read(buf)) + 3 -> RsAsmOperand.AsmRegOperand(FfiConverterTypeRSAsmRegOperand.read(buf)) + 4 -> RsAsmOperand.AsmSym(FfiConverterTypeRSAsmSym.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsAsmOperand) = + when (value) { + is RsAsmOperand.AsmConst -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmConst.allocationSize(value.v1)) + } + is RsAsmOperand.AsmLabel -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmLabel.allocationSize(value.v1)) + } + is RsAsmOperand.AsmRegOperand -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmRegOperand.allocationSize(value.v1)) + } + is RsAsmOperand.AsmSym -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmSym.allocationSize(value.v1)) + } + } + + override fun write(value: RsAsmOperand, buf: ByteBuffer) { + when (value) { + is RsAsmOperand.AsmConst -> { + buf.putInt(1) + FfiConverterTypeRSAsmConst.write(value.v1, buf) + Unit + } + is RsAsmOperand.AsmLabel -> { + buf.putInt(2) + FfiConverterTypeRSAsmLabel.write(value.v1, buf) + Unit + } + is RsAsmOperand.AsmRegOperand -> { + buf.putInt(3) + FfiConverterTypeRSAsmRegOperand.write(value.v1, buf) + Unit + } + is RsAsmOperand.AsmSym -> { + buf.putInt(4) + FfiConverterTypeRSAsmSym.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsAsmPiece { + + data class AsmClobberAbi(val v1: RsAsmClobberAbi) : RsAsmPiece() { + + companion object + } + + data class AsmOperandNamed(val v1: RsAsmOperandNamed) : RsAsmPiece() { + + companion object + } + + data class AsmOptions(val v1: RsAsmOptions) : RsAsmPiece() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAsmPiece : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAsmPiece { + return when (buf.getInt()) { + 1 -> RsAsmPiece.AsmClobberAbi(FfiConverterTypeRSAsmClobberAbi.read(buf)) + 2 -> RsAsmPiece.AsmOperandNamed(FfiConverterTypeRSAsmOperandNamed.read(buf)) + 3 -> RsAsmPiece.AsmOptions(FfiConverterTypeRSAsmOptions.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsAsmPiece) = + when (value) { + is RsAsmPiece.AsmClobberAbi -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmClobberAbi.allocationSize(value.v1)) + } + is RsAsmPiece.AsmOperandNamed -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmOperandNamed.allocationSize(value.v1)) + } + is RsAsmPiece.AsmOptions -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmOptions.allocationSize(value.v1)) + } + } + + override fun write(value: RsAsmPiece, buf: ByteBuffer) { + when (value) { + is RsAsmPiece.AsmClobberAbi -> { + buf.putInt(1) + FfiConverterTypeRSAsmClobberAbi.write(value.v1, buf) + Unit + } + is RsAsmPiece.AsmOperandNamed -> { + buf.putInt(2) + FfiConverterTypeRSAsmOperandNamed.write(value.v1, buf) + Unit + } + is RsAsmPiece.AsmOptions -> { + buf.putInt(3) + FfiConverterTypeRSAsmOptions.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsAssocItem { + + data class Const(val v1: RsConst) : RsAssocItem() { + + companion object + } + + data class Fn(val v1: RsFn) : RsAssocItem() { + + companion object + } + + data class MacroCall(val v1: RsMacroCall) : RsAssocItem() { + + companion object + } + + data class TypeAlias(val v1: RsTypeAlias) : RsAssocItem() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAssocItem : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAssocItem { + return when (buf.getInt()) { + 1 -> RsAssocItem.Const(FfiConverterTypeRSConst.read(buf)) + 2 -> RsAssocItem.Fn(FfiConverterTypeRSFn.read(buf)) + 3 -> RsAssocItem.MacroCall(FfiConverterTypeRSMacroCall.read(buf)) + 4 -> RsAssocItem.TypeAlias(FfiConverterTypeRSTypeAlias.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsAssocItem) = + when (value) { + is RsAssocItem.Const -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSConst.allocationSize(value.v1)) + } + is RsAssocItem.Fn -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSFn.allocationSize(value.v1)) + } + is RsAssocItem.MacroCall -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMacroCall.allocationSize(value.v1)) + } + is RsAssocItem.TypeAlias -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTypeAlias.allocationSize(value.v1)) + } + } + + override fun write(value: RsAssocItem, buf: ByteBuffer) { + when (value) { + is RsAssocItem.Const -> { + buf.putInt(1) + FfiConverterTypeRSConst.write(value.v1, buf) + Unit + } + is RsAssocItem.Fn -> { + buf.putInt(2) + FfiConverterTypeRSFn.write(value.v1, buf) + Unit + } + is RsAssocItem.MacroCall -> { + buf.putInt(3) + FfiConverterTypeRSMacroCall.write(value.v1, buf) + Unit + } + is RsAssocItem.TypeAlias -> { + buf.putInt(4) + FfiConverterTypeRSTypeAlias.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +/** Creating a common root node for all AST nodes */ +sealed class RsAst { + + data class RustItem(val v1: RsItem) : RsAst() { + + companion object + } + + data class RustExpr(val v1: RsExpr) : RsAst() { + + companion object + } + + data class RustStmt(val v1: RsStmt) : RsAst() { + + companion object + } + + data class RustType(val v1: RsType) : RsAst() { + + companion object + } + + data class RustAbi(val v1: RsAbi) : RsAst() { + + companion object + } + + data class RustProblem(val v1: RsProblem) : RsAst() { + + companion object + } + + data class RustUseTree(val v1: RsUseTree) : RsAst() { + + companion object + } + + data class RustPat(val v1: RsPat) : RsAst() { + + companion object + } + + data class RustVariant(val v1: RsVariant) : RsAst() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSAst : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAst { + return when (buf.getInt()) { + 1 -> RsAst.RustItem(FfiConverterTypeRSItem.read(buf)) + 2 -> RsAst.RustExpr(FfiConverterTypeRSExpr.read(buf)) + 3 -> RsAst.RustStmt(FfiConverterTypeRSStmt.read(buf)) + 4 -> RsAst.RustType(FfiConverterTypeRSType.read(buf)) + 5 -> RsAst.RustAbi(FfiConverterTypeRSAbi.read(buf)) + 6 -> RsAst.RustProblem(FfiConverterTypeRSProblem.read(buf)) + 7 -> RsAst.RustUseTree(FfiConverterTypeRSUseTree.read(buf)) + 8 -> RsAst.RustPat(FfiConverterTypeRSPat.read(buf)) + 9 -> RsAst.RustVariant(FfiConverterTypeRSVariant.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsAst) = + when (value) { + is RsAst.RustItem -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSItem.allocationSize(value.v1)) + } + is RsAst.RustExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSExpr.allocationSize(value.v1)) + } + is RsAst.RustStmt -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSStmt.allocationSize(value.v1)) + } + is RsAst.RustType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSType.allocationSize(value.v1)) + } + is RsAst.RustAbi -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAbi.allocationSize(value.v1)) + } + is RsAst.RustProblem -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSProblem.allocationSize(value.v1)) + } + is RsAst.RustUseTree -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSUseTree.allocationSize(value.v1)) + } + is RsAst.RustPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSPat.allocationSize(value.v1)) + } + is RsAst.RustVariant -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSVariant.allocationSize(value.v1)) + } + } + + override fun write(value: RsAst, buf: ByteBuffer) { + when (value) { + is RsAst.RustItem -> { + buf.putInt(1) + FfiConverterTypeRSItem.write(value.v1, buf) + Unit + } + is RsAst.RustExpr -> { + buf.putInt(2) + FfiConverterTypeRSExpr.write(value.v1, buf) + Unit + } + is RsAst.RustStmt -> { + buf.putInt(3) + FfiConverterTypeRSStmt.write(value.v1, buf) + Unit + } + is RsAst.RustType -> { + buf.putInt(4) + FfiConverterTypeRSType.write(value.v1, buf) + Unit + } + is RsAst.RustAbi -> { + buf.putInt(5) + FfiConverterTypeRSAbi.write(value.v1, buf) + Unit + } + is RsAst.RustProblem -> { + buf.putInt(6) + FfiConverterTypeRSProblem.write(value.v1, buf) + Unit + } + is RsAst.RustUseTree -> { + buf.putInt(7) + FfiConverterTypeRSUseTree.write(value.v1, buf) + Unit + } + is RsAst.RustPat -> { + buf.putInt(8) + FfiConverterTypeRSPat.write(value.v1, buf) + Unit + } + is RsAst.RustVariant -> { + buf.putInt(9) + FfiConverterTypeRSVariant.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsExpr { + + data class ArrayExpr(val v1: RsArrayExpr) : RsExpr() { + + companion object + } + + data class AsmExpr(val v1: RsAsmExpr) : RsExpr() { + + companion object + } + + data class AwaitExpr(val v1: RsAwaitExpr) : RsExpr() { + + companion object + } + + data class BecomeExpr(val v1: RsBecomeExpr) : RsExpr() { + + companion object + } + + data class BinExpr(val v1: RsBinExpr) : RsExpr() { + + companion object + } + + data class BlockExpr(val v1: RsBlockExpr) : RsExpr() { + + companion object + } + + data class BreakExpr(val v1: RsBreakExpr) : RsExpr() { + + companion object + } + + data class CallExpr(val v1: RsCallExpr) : RsExpr() { + + companion object + } + + data class CastExpr(val v1: RsCastExpr) : RsExpr() { + + companion object + } + + data class ClosureExpr(val v1: RsClosureExpr) : RsExpr() { + + companion object + } + + data class ContinueExpr(val v1: RsContinueExpr) : RsExpr() { + + companion object + } + + data class FieldExpr(val v1: RsFieldExpr) : RsExpr() { + + companion object + } + + data class ForExpr(val v1: RsForExpr) : RsExpr() { + + companion object + } + + data class FormatArgsExpr(val v1: RsFormatArgsExpr) : RsExpr() { + + companion object + } + + data class IfExpr(val v1: RsIfExpr) : RsExpr() { + + companion object + } + + data class IndexExpr(val v1: RsIndexExpr) : RsExpr() { + + companion object + } + + data class LetExpr(val v1: RsLetExpr) : RsExpr() { + + companion object + } + + data class Literal(val v1: RsLiteral) : RsExpr() { + + companion object + } + + data class LoopExpr(val v1: RsLoopExpr) : RsExpr() { + + companion object + } + + data class MacroExpr(val v1: RsMacroExpr) : RsExpr() { + + companion object + } + + data class MatchExpr(val v1: RsMatchExpr) : RsExpr() { + + companion object + } + + data class MatchArm(val v1: RsMatchArm) : RsExpr() { + + companion object + } + + data class MethodCallExpr(val v1: RsMethodCallExpr) : RsExpr() { + + companion object + } + + data class OffsetOfExpr(val v1: RsOffsetOfExpr) : RsExpr() { + + companion object + } + + data class ParenExpr(val v1: RsParenExpr) : RsExpr() { + + companion object + } + + data class PathExpr(val v1: RsPathExpr) : RsExpr() { + + companion object + } + + data class PrefixExpr(val v1: RsPrefixExpr) : RsExpr() { + + companion object + } + + data class RangeExpr(val v1: RsRangeExpr) : RsExpr() { + + companion object + } + + data class RecordExpr(val v1: RsRecordExpr) : RsExpr() { + + companion object + } + + data class RefExpr(val v1: RsRefExpr) : RsExpr() { + + companion object + } + + data class ReturnExpr(val v1: RsReturnExpr) : RsExpr() { + + companion object + } + + data class TryExpr(val v1: RsTryExpr) : RsExpr() { + + companion object + } + + data class TupleExpr(val v1: RsTupleExpr) : RsExpr() { + + companion object + } + + data class UnderscoreExpr(val v1: RsUnderscoreExpr) : RsExpr() { + + companion object + } + + data class WhileExpr(val v1: RsWhileExpr) : RsExpr() { + + companion object + } + + data class YeetExpr(val v1: RsYeetExpr) : RsExpr() { + + companion object + } + + data class YieldExpr(val v1: RsYieldExpr) : RsExpr() { + + companion object + } + + data class Path(val v1: RsPath) : RsExpr() { + + companion object + } + + data class PathSegment(val v1: RsPathSegment) : RsExpr() { + + companion object + } + + data class NameRef(val v1: RsNameRef) : RsExpr() { + + companion object + } + + data class RecordExprField(val v1: RsRecordExprField) : RsExpr() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsExpr { + return when (buf.getInt()) { + 1 -> RsExpr.ArrayExpr(FfiConverterTypeRSArrayExpr.read(buf)) + 2 -> RsExpr.AsmExpr(FfiConverterTypeRSAsmExpr.read(buf)) + 3 -> RsExpr.AwaitExpr(FfiConverterTypeRSAwaitExpr.read(buf)) + 4 -> RsExpr.BecomeExpr(FfiConverterTypeRSBecomeExpr.read(buf)) + 5 -> RsExpr.BinExpr(FfiConverterTypeRSBinExpr.read(buf)) + 6 -> RsExpr.BlockExpr(FfiConverterTypeRSBlockExpr.read(buf)) + 7 -> RsExpr.BreakExpr(FfiConverterTypeRSBreakExpr.read(buf)) + 8 -> RsExpr.CallExpr(FfiConverterTypeRSCallExpr.read(buf)) + 9 -> RsExpr.CastExpr(FfiConverterTypeRSCastExpr.read(buf)) + 10 -> RsExpr.ClosureExpr(FfiConverterTypeRSClosureExpr.read(buf)) + 11 -> RsExpr.ContinueExpr(FfiConverterTypeRSContinueExpr.read(buf)) + 12 -> RsExpr.FieldExpr(FfiConverterTypeRSFieldExpr.read(buf)) + 13 -> RsExpr.ForExpr(FfiConverterTypeRSForExpr.read(buf)) + 14 -> RsExpr.FormatArgsExpr(FfiConverterTypeRSFormatArgsExpr.read(buf)) + 15 -> RsExpr.IfExpr(FfiConverterTypeRSIfExpr.read(buf)) + 16 -> RsExpr.IndexExpr(FfiConverterTypeRSIndexExpr.read(buf)) + 17 -> RsExpr.LetExpr(FfiConverterTypeRSLetExpr.read(buf)) + 18 -> RsExpr.Literal(FfiConverterTypeRSLiteral.read(buf)) + 19 -> RsExpr.LoopExpr(FfiConverterTypeRSLoopExpr.read(buf)) + 20 -> RsExpr.MacroExpr(FfiConverterTypeRSMacroExpr.read(buf)) + 21 -> RsExpr.MatchExpr(FfiConverterTypeRSMatchExpr.read(buf)) + 22 -> RsExpr.MatchArm(FfiConverterTypeRSMatchArm.read(buf)) + 23 -> RsExpr.MethodCallExpr(FfiConverterTypeRSMethodCallExpr.read(buf)) + 24 -> RsExpr.OffsetOfExpr(FfiConverterTypeRSOffsetOfExpr.read(buf)) + 25 -> RsExpr.ParenExpr(FfiConverterTypeRSParenExpr.read(buf)) + 26 -> RsExpr.PathExpr(FfiConverterTypeRSPathExpr.read(buf)) + 27 -> RsExpr.PrefixExpr(FfiConverterTypeRSPrefixExpr.read(buf)) + 28 -> RsExpr.RangeExpr(FfiConverterTypeRSRangeExpr.read(buf)) + 29 -> RsExpr.RecordExpr(FfiConverterTypeRSRecordExpr.read(buf)) + 30 -> RsExpr.RefExpr(FfiConverterTypeRSRefExpr.read(buf)) + 31 -> RsExpr.ReturnExpr(FfiConverterTypeRSReturnExpr.read(buf)) + 32 -> RsExpr.TryExpr(FfiConverterTypeRSTryExpr.read(buf)) + 33 -> RsExpr.TupleExpr(FfiConverterTypeRSTupleExpr.read(buf)) + 34 -> RsExpr.UnderscoreExpr(FfiConverterTypeRSUnderscoreExpr.read(buf)) + 35 -> RsExpr.WhileExpr(FfiConverterTypeRSWhileExpr.read(buf)) + 36 -> RsExpr.YeetExpr(FfiConverterTypeRSYeetExpr.read(buf)) + 37 -> RsExpr.YieldExpr(FfiConverterTypeRSYieldExpr.read(buf)) + 38 -> RsExpr.Path(FfiConverterTypeRSPath.read(buf)) + 39 -> RsExpr.PathSegment(FfiConverterTypeRSPathSegment.read(buf)) + 40 -> RsExpr.NameRef(FfiConverterTypeRSNameRef.read(buf)) + 41 -> RsExpr.RecordExprField(FfiConverterTypeRSRecordExprField.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsExpr) = + when (value) { + is RsExpr.ArrayExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSArrayExpr.allocationSize(value.v1)) + } + is RsExpr.AsmExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmExpr.allocationSize(value.v1)) + } + is RsExpr.AwaitExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAwaitExpr.allocationSize(value.v1)) + } + is RsExpr.BecomeExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSBecomeExpr.allocationSize(value.v1)) + } + is RsExpr.BinExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSBinExpr.allocationSize(value.v1)) + } + is RsExpr.BlockExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSBlockExpr.allocationSize(value.v1)) + } + is RsExpr.BreakExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSBreakExpr.allocationSize(value.v1)) + } + is RsExpr.CallExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSCallExpr.allocationSize(value.v1)) + } + is RsExpr.CastExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSCastExpr.allocationSize(value.v1)) + } + is RsExpr.ClosureExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSClosureExpr.allocationSize(value.v1)) + } + is RsExpr.ContinueExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSContinueExpr.allocationSize(value.v1)) + } + is RsExpr.FieldExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSFieldExpr.allocationSize(value.v1)) + } + is RsExpr.ForExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSForExpr.allocationSize(value.v1)) + } + is RsExpr.FormatArgsExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSFormatArgsExpr.allocationSize(value.v1)) + } + is RsExpr.IfExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSIfExpr.allocationSize(value.v1)) + } + is RsExpr.IndexExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSIndexExpr.allocationSize(value.v1)) + } + is RsExpr.LetExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSLetExpr.allocationSize(value.v1)) + } + is RsExpr.Literal -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSLiteral.allocationSize(value.v1)) + } + is RsExpr.LoopExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSLoopExpr.allocationSize(value.v1)) + } + is RsExpr.MacroExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMacroExpr.allocationSize(value.v1)) + } + is RsExpr.MatchExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMatchExpr.allocationSize(value.v1)) + } + is RsExpr.MatchArm -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMatchArm.allocationSize(value.v1)) + } + is RsExpr.MethodCallExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMethodCallExpr.allocationSize(value.v1)) + } + is RsExpr.OffsetOfExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSOffsetOfExpr.allocationSize(value.v1)) + } + is RsExpr.ParenExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSParenExpr.allocationSize(value.v1)) + } + is RsExpr.PathExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSPathExpr.allocationSize(value.v1)) + } + is RsExpr.PrefixExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSPrefixExpr.allocationSize(value.v1)) + } + is RsExpr.RangeExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRangeExpr.allocationSize(value.v1)) + } + is RsExpr.RecordExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRecordExpr.allocationSize(value.v1)) + } + is RsExpr.RefExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRefExpr.allocationSize(value.v1)) + } + is RsExpr.ReturnExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSReturnExpr.allocationSize(value.v1)) + } + is RsExpr.TryExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTryExpr.allocationSize(value.v1)) + } + is RsExpr.TupleExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTupleExpr.allocationSize(value.v1)) + } + is RsExpr.UnderscoreExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSUnderscoreExpr.allocationSize(value.v1)) + } + is RsExpr.WhileExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSWhileExpr.allocationSize(value.v1)) + } + is RsExpr.YeetExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSYeetExpr.allocationSize(value.v1)) + } + is RsExpr.YieldExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSYieldExpr.allocationSize(value.v1)) + } + is RsExpr.Path -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSPath.allocationSize(value.v1)) + } + is RsExpr.PathSegment -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSPathSegment.allocationSize(value.v1)) + } + is RsExpr.NameRef -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSNameRef.allocationSize(value.v1)) + } + is RsExpr.RecordExprField -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRecordExprField.allocationSize(value.v1)) + } + } + + override fun write(value: RsExpr, buf: ByteBuffer) { + when (value) { + is RsExpr.ArrayExpr -> { + buf.putInt(1) + FfiConverterTypeRSArrayExpr.write(value.v1, buf) + Unit + } + is RsExpr.AsmExpr -> { + buf.putInt(2) + FfiConverterTypeRSAsmExpr.write(value.v1, buf) + Unit + } + is RsExpr.AwaitExpr -> { + buf.putInt(3) + FfiConverterTypeRSAwaitExpr.write(value.v1, buf) + Unit + } + is RsExpr.BecomeExpr -> { + buf.putInt(4) + FfiConverterTypeRSBecomeExpr.write(value.v1, buf) + Unit + } + is RsExpr.BinExpr -> { + buf.putInt(5) + FfiConverterTypeRSBinExpr.write(value.v1, buf) + Unit + } + is RsExpr.BlockExpr -> { + buf.putInt(6) + FfiConverterTypeRSBlockExpr.write(value.v1, buf) + Unit + } + is RsExpr.BreakExpr -> { + buf.putInt(7) + FfiConverterTypeRSBreakExpr.write(value.v1, buf) + Unit + } + is RsExpr.CallExpr -> { + buf.putInt(8) + FfiConverterTypeRSCallExpr.write(value.v1, buf) + Unit + } + is RsExpr.CastExpr -> { + buf.putInt(9) + FfiConverterTypeRSCastExpr.write(value.v1, buf) + Unit + } + is RsExpr.ClosureExpr -> { + buf.putInt(10) + FfiConverterTypeRSClosureExpr.write(value.v1, buf) + Unit + } + is RsExpr.ContinueExpr -> { + buf.putInt(11) + FfiConverterTypeRSContinueExpr.write(value.v1, buf) + Unit + } + is RsExpr.FieldExpr -> { + buf.putInt(12) + FfiConverterTypeRSFieldExpr.write(value.v1, buf) + Unit + } + is RsExpr.ForExpr -> { + buf.putInt(13) + FfiConverterTypeRSForExpr.write(value.v1, buf) + Unit + } + is RsExpr.FormatArgsExpr -> { + buf.putInt(14) + FfiConverterTypeRSFormatArgsExpr.write(value.v1, buf) + Unit + } + is RsExpr.IfExpr -> { + buf.putInt(15) + FfiConverterTypeRSIfExpr.write(value.v1, buf) + Unit + } + is RsExpr.IndexExpr -> { + buf.putInt(16) + FfiConverterTypeRSIndexExpr.write(value.v1, buf) + Unit + } + is RsExpr.LetExpr -> { + buf.putInt(17) + FfiConverterTypeRSLetExpr.write(value.v1, buf) + Unit + } + is RsExpr.Literal -> { + buf.putInt(18) + FfiConverterTypeRSLiteral.write(value.v1, buf) + Unit + } + is RsExpr.LoopExpr -> { + buf.putInt(19) + FfiConverterTypeRSLoopExpr.write(value.v1, buf) + Unit + } + is RsExpr.MacroExpr -> { + buf.putInt(20) + FfiConverterTypeRSMacroExpr.write(value.v1, buf) + Unit + } + is RsExpr.MatchExpr -> { + buf.putInt(21) + FfiConverterTypeRSMatchExpr.write(value.v1, buf) + Unit + } + is RsExpr.MatchArm -> { + buf.putInt(22) + FfiConverterTypeRSMatchArm.write(value.v1, buf) + Unit + } + is RsExpr.MethodCallExpr -> { + buf.putInt(23) + FfiConverterTypeRSMethodCallExpr.write(value.v1, buf) + Unit + } + is RsExpr.OffsetOfExpr -> { + buf.putInt(24) + FfiConverterTypeRSOffsetOfExpr.write(value.v1, buf) + Unit + } + is RsExpr.ParenExpr -> { + buf.putInt(25) + FfiConverterTypeRSParenExpr.write(value.v1, buf) + Unit + } + is RsExpr.PathExpr -> { + buf.putInt(26) + FfiConverterTypeRSPathExpr.write(value.v1, buf) + Unit + } + is RsExpr.PrefixExpr -> { + buf.putInt(27) + FfiConverterTypeRSPrefixExpr.write(value.v1, buf) + Unit + } + is RsExpr.RangeExpr -> { + buf.putInt(28) + FfiConverterTypeRSRangeExpr.write(value.v1, buf) + Unit + } + is RsExpr.RecordExpr -> { + buf.putInt(29) + FfiConverterTypeRSRecordExpr.write(value.v1, buf) + Unit + } + is RsExpr.RefExpr -> { + buf.putInt(30) + FfiConverterTypeRSRefExpr.write(value.v1, buf) + Unit + } + is RsExpr.ReturnExpr -> { + buf.putInt(31) + FfiConverterTypeRSReturnExpr.write(value.v1, buf) + Unit + } + is RsExpr.TryExpr -> { + buf.putInt(32) + FfiConverterTypeRSTryExpr.write(value.v1, buf) + Unit + } + is RsExpr.TupleExpr -> { + buf.putInt(33) + FfiConverterTypeRSTupleExpr.write(value.v1, buf) + Unit + } + is RsExpr.UnderscoreExpr -> { + buf.putInt(34) + FfiConverterTypeRSUnderscoreExpr.write(value.v1, buf) + Unit + } + is RsExpr.WhileExpr -> { + buf.putInt(35) + FfiConverterTypeRSWhileExpr.write(value.v1, buf) + Unit + } + is RsExpr.YeetExpr -> { + buf.putInt(36) + FfiConverterTypeRSYeetExpr.write(value.v1, buf) + Unit + } + is RsExpr.YieldExpr -> { + buf.putInt(37) + FfiConverterTypeRSYieldExpr.write(value.v1, buf) + Unit + } + is RsExpr.Path -> { + buf.putInt(38) + FfiConverterTypeRSPath.write(value.v1, buf) + Unit + } + is RsExpr.PathSegment -> { + buf.putInt(39) + FfiConverterTypeRSPathSegment.write(value.v1, buf) + Unit + } + is RsExpr.NameRef -> { + buf.putInt(40) + FfiConverterTypeRSNameRef.write(value.v1, buf) + Unit + } + is RsExpr.RecordExprField -> { + buf.putInt(41) + FfiConverterTypeRSRecordExprField.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsExternItem { + + data class Fn(val v1: RsFn) : RsExternItem() { + + companion object + } + + data class MacroCall(val v1: RsMacroCall) : RsExternItem() { + + companion object + } + + data class Static(val v1: RsStatic) : RsExternItem() { + + companion object + } + + data class TypeAlias(val v1: RsTypeAlias) : RsExternItem() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSExternItem : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsExternItem { + return when (buf.getInt()) { + 1 -> RsExternItem.Fn(FfiConverterTypeRSFn.read(buf)) + 2 -> RsExternItem.MacroCall(FfiConverterTypeRSMacroCall.read(buf)) + 3 -> RsExternItem.Static(FfiConverterTypeRSStatic.read(buf)) + 4 -> RsExternItem.TypeAlias(FfiConverterTypeRSTypeAlias.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsExternItem) = + when (value) { + is RsExternItem.Fn -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSFn.allocationSize(value.v1)) + } + is RsExternItem.MacroCall -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMacroCall.allocationSize(value.v1)) + } + is RsExternItem.Static -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSStatic.allocationSize(value.v1)) + } + is RsExternItem.TypeAlias -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTypeAlias.allocationSize(value.v1)) + } + } + + override fun write(value: RsExternItem, buf: ByteBuffer) { + when (value) { + is RsExternItem.Fn -> { + buf.putInt(1) + FfiConverterTypeRSFn.write(value.v1, buf) + Unit + } + is RsExternItem.MacroCall -> { + buf.putInt(2) + FfiConverterTypeRSMacroCall.write(value.v1, buf) + Unit + } + is RsExternItem.Static -> { + buf.putInt(3) + FfiConverterTypeRSStatic.write(value.v1, buf) + Unit + } + is RsExternItem.TypeAlias -> { + buf.putInt(4) + FfiConverterTypeRSTypeAlias.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsFieldList { + + data class RecordFieldList(val v1: RsRecordFieldList) : RsFieldList() { + + companion object + } + + data class TupleFieldList(val v1: RsTupleFieldList) : RsFieldList() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSFieldList : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsFieldList { + return when (buf.getInt()) { + 1 -> RsFieldList.RecordFieldList(FfiConverterTypeRSRecordFieldList.read(buf)) + 2 -> RsFieldList.TupleFieldList(FfiConverterTypeRSTupleFieldList.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsFieldList) = + when (value) { + is RsFieldList.RecordFieldList -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRecordFieldList.allocationSize(value.v1)) + } + is RsFieldList.TupleFieldList -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTupleFieldList.allocationSize(value.v1)) + } + } + + override fun write(value: RsFieldList, buf: ByteBuffer) { + when (value) { + is RsFieldList.RecordFieldList -> { + buf.putInt(1) + FfiConverterTypeRSRecordFieldList.write(value.v1, buf) + Unit + } + is RsFieldList.TupleFieldList -> { + buf.putInt(2) + FfiConverterTypeRSTupleFieldList.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsGenericArg { + + data class AssocTypeArg(val v1: RsAssocTypeArg) : RsGenericArg() { + + companion object + } + + data class ConstArg(val v1: RsConstArg) : RsGenericArg() { + + companion object + } + + data class LifetimeArg(val v1: RsLifetimeArg) : RsGenericArg() { + + companion object + } + + data class TypeArg(val v1: RsTypeArg) : RsGenericArg() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSGenericArg : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsGenericArg { + return when (buf.getInt()) { + 1 -> RsGenericArg.AssocTypeArg(FfiConverterTypeRSAssocTypeArg.read(buf)) + 2 -> RsGenericArg.ConstArg(FfiConverterTypeRSConstArg.read(buf)) + 3 -> RsGenericArg.LifetimeArg(FfiConverterTypeRSLifetimeArg.read(buf)) + 4 -> RsGenericArg.TypeArg(FfiConverterTypeRSTypeArg.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsGenericArg) = + when (value) { + is RsGenericArg.AssocTypeArg -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAssocTypeArg.allocationSize(value.v1)) + } + is RsGenericArg.ConstArg -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSConstArg.allocationSize(value.v1)) + } + is RsGenericArg.LifetimeArg -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSLifetimeArg.allocationSize(value.v1)) + } + is RsGenericArg.TypeArg -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTypeArg.allocationSize(value.v1)) + } + } + + override fun write(value: RsGenericArg, buf: ByteBuffer) { + when (value) { + is RsGenericArg.AssocTypeArg -> { + buf.putInt(1) + FfiConverterTypeRSAssocTypeArg.write(value.v1, buf) + Unit + } + is RsGenericArg.ConstArg -> { + buf.putInt(2) + FfiConverterTypeRSConstArg.write(value.v1, buf) + Unit + } + is RsGenericArg.LifetimeArg -> { + buf.putInt(3) + FfiConverterTypeRSLifetimeArg.write(value.v1, buf) + Unit + } + is RsGenericArg.TypeArg -> { + buf.putInt(4) + FfiConverterTypeRSTypeArg.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsGenericParam { + + data class ConstParam(val v1: RsConstParam) : RsGenericParam() { + + companion object + } + + data class LifetimeParam(val v1: RsLifetimeParam) : RsGenericParam() { + + companion object + } + + data class TypeParam(val v1: RsTypeParam) : RsGenericParam() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSGenericParam : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsGenericParam { + return when (buf.getInt()) { + 1 -> RsGenericParam.ConstParam(FfiConverterTypeRSConstParam.read(buf)) + 2 -> RsGenericParam.LifetimeParam(FfiConverterTypeRSLifetimeParam.read(buf)) + 3 -> RsGenericParam.TypeParam(FfiConverterTypeRSTypeParam.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsGenericParam) = + when (value) { + is RsGenericParam.ConstParam -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSConstParam.allocationSize(value.v1)) + } + is RsGenericParam.LifetimeParam -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSLifetimeParam.allocationSize(value.v1)) + } + is RsGenericParam.TypeParam -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTypeParam.allocationSize(value.v1)) + } + } + + override fun write(value: RsGenericParam, buf: ByteBuffer) { + when (value) { + is RsGenericParam.ConstParam -> { + buf.putInt(1) + FfiConverterTypeRSConstParam.write(value.v1, buf) + Unit + } + is RsGenericParam.LifetimeParam -> { + buf.putInt(2) + FfiConverterTypeRSLifetimeParam.write(value.v1, buf) + Unit + } + is RsGenericParam.TypeParam -> { + buf.putInt(3) + FfiConverterTypeRSTypeParam.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsItem { + + data class AsmExpr(val v1: RsAsmExpr) : RsItem() { + + companion object + } + + data class Const(val v1: RsConst) : RsItem() { + + companion object + } + + data class Enum(val v1: RsEnum) : RsItem() { + + companion object + } + + data class ExternBlock(val v1: RsExternBlock) : RsItem() { + + companion object + } + + data class ExternCrate(val v1: RsExternCrate) : RsItem() { + + companion object + } + + data class Fn(val v1: RsFn) : RsItem() { + + companion object + } + + data class Impl(val v1: RsImpl) : RsItem() { + + companion object + } + + data class MacroCall(val v1: RsMacroCall) : RsItem() { + + companion object + } + + data class MacroDef(val v1: RsMacroDef) : RsItem() { + + companion object + } + + data class MacroRules(val v1: RsMacroRules) : RsItem() { + + companion object + } + + data class Module(val v1: RsModule) : RsItem() { + + companion object + } + + data class Static(val v1: RsStatic) : RsItem() { + + companion object + } + + data class Struct(val v1: RsStruct) : RsItem() { + + companion object + } + + data class Trait(val v1: RsTrait) : RsItem() { + + companion object + } + + data class TypeAlias(val v1: RsTypeAlias) : RsItem() { + + companion object + } + + data class Union(val v1: RsUnion) : RsItem() { + + companion object + } + + data class Use(val v1: RsUse) : RsItem() { + + companion object + } + + data class Param(val v1: RsParam) : RsItem() { + + companion object + } + + data class SelfParam(val v1: RsSelfParam) : RsItem() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSItem : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsItem { + return when (buf.getInt()) { + 1 -> RsItem.AsmExpr(FfiConverterTypeRSAsmExpr.read(buf)) + 2 -> RsItem.Const(FfiConverterTypeRSConst.read(buf)) + 3 -> RsItem.Enum(FfiConverterTypeRSEnum.read(buf)) + 4 -> RsItem.ExternBlock(FfiConverterTypeRSExternBlock.read(buf)) + 5 -> RsItem.ExternCrate(FfiConverterTypeRSExternCrate.read(buf)) + 6 -> RsItem.Fn(FfiConverterTypeRSFn.read(buf)) + 7 -> RsItem.Impl(FfiConverterTypeRSImpl.read(buf)) + 8 -> RsItem.MacroCall(FfiConverterTypeRSMacroCall.read(buf)) + 9 -> RsItem.MacroDef(FfiConverterTypeRSMacroDef.read(buf)) + 10 -> RsItem.MacroRules(FfiConverterTypeRSMacroRules.read(buf)) + 11 -> RsItem.Module(FfiConverterTypeRSModule.read(buf)) + 12 -> RsItem.Static(FfiConverterTypeRSStatic.read(buf)) + 13 -> RsItem.Struct(FfiConverterTypeRSStruct.read(buf)) + 14 -> RsItem.Trait(FfiConverterTypeRSTrait.read(buf)) + 15 -> RsItem.TypeAlias(FfiConverterTypeRSTypeAlias.read(buf)) + 16 -> RsItem.Union(FfiConverterTypeRSUnion.read(buf)) + 17 -> RsItem.Use(FfiConverterTypeRSUse.read(buf)) + 18 -> RsItem.Param(FfiConverterTypeRSParam.read(buf)) + 19 -> RsItem.SelfParam(FfiConverterTypeRSSelfParam.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsItem) = + when (value) { + is RsItem.AsmExpr -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSAsmExpr.allocationSize(value.v1)) + } + is RsItem.Const -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSConst.allocationSize(value.v1)) + } + is RsItem.Enum -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSEnum.allocationSize(value.v1)) + } + is RsItem.ExternBlock -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSExternBlock.allocationSize(value.v1)) + } + is RsItem.ExternCrate -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSExternCrate.allocationSize(value.v1)) + } + is RsItem.Fn -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSFn.allocationSize(value.v1)) + } + is RsItem.Impl -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSImpl.allocationSize(value.v1)) + } + is RsItem.MacroCall -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMacroCall.allocationSize(value.v1)) + } + is RsItem.MacroDef -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMacroDef.allocationSize(value.v1)) + } + is RsItem.MacroRules -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMacroRules.allocationSize(value.v1)) + } + is RsItem.Module -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSModule.allocationSize(value.v1)) + } + is RsItem.Static -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSStatic.allocationSize(value.v1)) + } + is RsItem.Struct -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSStruct.allocationSize(value.v1)) + } + is RsItem.Trait -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTrait.allocationSize(value.v1)) + } + is RsItem.TypeAlias -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTypeAlias.allocationSize(value.v1)) + } + is RsItem.Union -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSUnion.allocationSize(value.v1)) + } + is RsItem.Use -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSUse.allocationSize(value.v1)) + } + is RsItem.Param -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSParam.allocationSize(value.v1)) + } + is RsItem.SelfParam -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSSelfParam.allocationSize(value.v1)) + } + } + + override fun write(value: RsItem, buf: ByteBuffer) { + when (value) { + is RsItem.AsmExpr -> { + buf.putInt(1) + FfiConverterTypeRSAsmExpr.write(value.v1, buf) + Unit + } + is RsItem.Const -> { + buf.putInt(2) + FfiConverterTypeRSConst.write(value.v1, buf) + Unit + } + is RsItem.Enum -> { + buf.putInt(3) + FfiConverterTypeRSEnum.write(value.v1, buf) + Unit + } + is RsItem.ExternBlock -> { + buf.putInt(4) + FfiConverterTypeRSExternBlock.write(value.v1, buf) + Unit + } + is RsItem.ExternCrate -> { + buf.putInt(5) + FfiConverterTypeRSExternCrate.write(value.v1, buf) + Unit + } + is RsItem.Fn -> { + buf.putInt(6) + FfiConverterTypeRSFn.write(value.v1, buf) + Unit + } + is RsItem.Impl -> { + buf.putInt(7) + FfiConverterTypeRSImpl.write(value.v1, buf) + Unit + } + is RsItem.MacroCall -> { + buf.putInt(8) + FfiConverterTypeRSMacroCall.write(value.v1, buf) + Unit + } + is RsItem.MacroDef -> { + buf.putInt(9) + FfiConverterTypeRSMacroDef.write(value.v1, buf) + Unit + } + is RsItem.MacroRules -> { + buf.putInt(10) + FfiConverterTypeRSMacroRules.write(value.v1, buf) + Unit + } + is RsItem.Module -> { + buf.putInt(11) + FfiConverterTypeRSModule.write(value.v1, buf) + Unit + } + is RsItem.Static -> { + buf.putInt(12) + FfiConverterTypeRSStatic.write(value.v1, buf) + Unit + } + is RsItem.Struct -> { + buf.putInt(13) + FfiConverterTypeRSStruct.write(value.v1, buf) + Unit + } + is RsItem.Trait -> { + buf.putInt(14) + FfiConverterTypeRSTrait.write(value.v1, buf) + Unit + } + is RsItem.TypeAlias -> { + buf.putInt(15) + FfiConverterTypeRSTypeAlias.write(value.v1, buf) + Unit + } + is RsItem.Union -> { + buf.putInt(16) + FfiConverterTypeRSUnion.write(value.v1, buf) + Unit + } + is RsItem.Use -> { + buf.putInt(17) + FfiConverterTypeRSUse.write(value.v1, buf) + Unit + } + is RsItem.Param -> { + buf.putInt(18) + FfiConverterTypeRSParam.write(value.v1, buf) + Unit + } + is RsItem.SelfParam -> { + buf.putInt(19) + FfiConverterTypeRSSelfParam.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class RsLiteralType { + + BYTE_L, + BYTE_STRING_L, + CHAR_L, + C_STRING_L, + FLOAT_NUMBER_L, + INT_NUMBER_L, + STRING_L, + UNKNOWN_L; + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSLiteralType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + RsLiteralType.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: RsLiteralType) = 4UL + + override fun write(value: RsLiteralType, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class RsPat { + + data class BoxPat(val v1: RsBoxPat) : RsPat() { + + companion object + } + + data class ConstBlockPat(val v1: RsConstBlockPat) : RsPat() { + + companion object + } + + data class IdentPat(val v1: RsIdentPat) : RsPat() { + + companion object + } + + data class LiteralPat(val v1: RsLiteralPat) : RsPat() { + + companion object + } + + data class MacroPat(val v1: RsMacroPat) : RsPat() { + + companion object + } + + data class OrPat(val v1: RsOrPat) : RsPat() { + + companion object + } + + data class ParenPat(val v1: RsParenPat) : RsPat() { + + companion object + } + + data class PathPat(val v1: RsPathPat) : RsPat() { + + companion object + } + + data class RangePat(val v1: RsRangePat) : RsPat() { + + companion object + } + + data class RecordPat(val v1: RsRecordPat) : RsPat() { + + companion object + } + + data class RefPat(val v1: RsRefPat) : RsPat() { + + companion object + } + + data class RestPat(val v1: RsRestPat) : RsPat() { + + companion object + } + + data class SlicePat(val v1: RsSlicePat) : RsPat() { + + companion object + } + + data class TuplePat(val v1: RsTuplePat) : RsPat() { + + companion object + } + + data class TupleStructPat(val v1: RsTupleStructPat) : RsPat() { + + companion object + } + + data class WildcardPat(val v1: RsWildcardPat) : RsPat() { + + companion object + } + + data class RecordPatField(val v1: RsRecordPatField) : RsPat() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPat { + return when (buf.getInt()) { + 1 -> RsPat.BoxPat(FfiConverterTypeRSBoxPat.read(buf)) + 2 -> RsPat.ConstBlockPat(FfiConverterTypeRSConstBlockPat.read(buf)) + 3 -> RsPat.IdentPat(FfiConverterTypeRSIdentPat.read(buf)) + 4 -> RsPat.LiteralPat(FfiConverterTypeRSLiteralPat.read(buf)) + 5 -> RsPat.MacroPat(FfiConverterTypeRSMacroPat.read(buf)) + 6 -> RsPat.OrPat(FfiConverterTypeRSOrPat.read(buf)) + 7 -> RsPat.ParenPat(FfiConverterTypeRSParenPat.read(buf)) + 8 -> RsPat.PathPat(FfiConverterTypeRSPathPat.read(buf)) + 9 -> RsPat.RangePat(FfiConverterTypeRSRangePat.read(buf)) + 10 -> RsPat.RecordPat(FfiConverterTypeRSRecordPat.read(buf)) + 11 -> RsPat.RefPat(FfiConverterTypeRSRefPat.read(buf)) + 12 -> RsPat.RestPat(FfiConverterTypeRSRestPat.read(buf)) + 13 -> RsPat.SlicePat(FfiConverterTypeRSSlicePat.read(buf)) + 14 -> RsPat.TuplePat(FfiConverterTypeRSTuplePat.read(buf)) + 15 -> RsPat.TupleStructPat(FfiConverterTypeRSTupleStructPat.read(buf)) + 16 -> RsPat.WildcardPat(FfiConverterTypeRSWildcardPat.read(buf)) + 17 -> RsPat.RecordPatField(FfiConverterTypeRSRecordPatField.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsPat) = + when (value) { + is RsPat.BoxPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSBoxPat.allocationSize(value.v1)) + } + is RsPat.ConstBlockPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSConstBlockPat.allocationSize(value.v1)) + } + is RsPat.IdentPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSIdentPat.allocationSize(value.v1)) + } + is RsPat.LiteralPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSLiteralPat.allocationSize(value.v1)) + } + is RsPat.MacroPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMacroPat.allocationSize(value.v1)) + } + is RsPat.OrPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSOrPat.allocationSize(value.v1)) + } + is RsPat.ParenPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSParenPat.allocationSize(value.v1)) + } + is RsPat.PathPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSPathPat.allocationSize(value.v1)) + } + is RsPat.RangePat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRangePat.allocationSize(value.v1)) + } + is RsPat.RecordPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRecordPat.allocationSize(value.v1)) + } + is RsPat.RefPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRefPat.allocationSize(value.v1)) + } + is RsPat.RestPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRestPat.allocationSize(value.v1)) + } + is RsPat.SlicePat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSSlicePat.allocationSize(value.v1)) + } + is RsPat.TuplePat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTuplePat.allocationSize(value.v1)) + } + is RsPat.TupleStructPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTupleStructPat.allocationSize(value.v1)) + } + is RsPat.WildcardPat -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSWildcardPat.allocationSize(value.v1)) + } + is RsPat.RecordPatField -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRecordPatField.allocationSize(value.v1)) + } + } + + override fun write(value: RsPat, buf: ByteBuffer) { + when (value) { + is RsPat.BoxPat -> { + buf.putInt(1) + FfiConverterTypeRSBoxPat.write(value.v1, buf) + Unit + } + is RsPat.ConstBlockPat -> { + buf.putInt(2) + FfiConverterTypeRSConstBlockPat.write(value.v1, buf) + Unit + } + is RsPat.IdentPat -> { + buf.putInt(3) + FfiConverterTypeRSIdentPat.write(value.v1, buf) + Unit + } + is RsPat.LiteralPat -> { + buf.putInt(4) + FfiConverterTypeRSLiteralPat.write(value.v1, buf) + Unit + } + is RsPat.MacroPat -> { + buf.putInt(5) + FfiConverterTypeRSMacroPat.write(value.v1, buf) + Unit + } + is RsPat.OrPat -> { + buf.putInt(6) + FfiConverterTypeRSOrPat.write(value.v1, buf) + Unit + } + is RsPat.ParenPat -> { + buf.putInt(7) + FfiConverterTypeRSParenPat.write(value.v1, buf) + Unit + } + is RsPat.PathPat -> { + buf.putInt(8) + FfiConverterTypeRSPathPat.write(value.v1, buf) + Unit + } + is RsPat.RangePat -> { + buf.putInt(9) + FfiConverterTypeRSRangePat.write(value.v1, buf) + Unit + } + is RsPat.RecordPat -> { + buf.putInt(10) + FfiConverterTypeRSRecordPat.write(value.v1, buf) + Unit + } + is RsPat.RefPat -> { + buf.putInt(11) + FfiConverterTypeRSRefPat.write(value.v1, buf) + Unit + } + is RsPat.RestPat -> { + buf.putInt(12) + FfiConverterTypeRSRestPat.write(value.v1, buf) + Unit + } + is RsPat.SlicePat -> { + buf.putInt(13) + FfiConverterTypeRSSlicePat.write(value.v1, buf) + Unit + } + is RsPat.TuplePat -> { + buf.putInt(14) + FfiConverterTypeRSTuplePat.write(value.v1, buf) + Unit + } + is RsPat.TupleStructPat -> { + buf.putInt(15) + FfiConverterTypeRSTupleStructPat.write(value.v1, buf) + Unit + } + is RsPat.WildcardPat -> { + buf.putInt(16) + FfiConverterTypeRSWildcardPat.write(value.v1, buf) + Unit + } + is RsPat.RecordPatField -> { + buf.putInt(17) + FfiConverterTypeRSRecordPatField.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsStmt { + + data class ExprStmt(val v1: RsExprStmt) : RsStmt() { + + companion object + } + + data class Item(val v1: RsItem) : RsStmt() { + + companion object + } + + data class LetStmt(val v1: RsLetStmt) : RsStmt() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSStmt : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsStmt { + return when (buf.getInt()) { + 1 -> RsStmt.ExprStmt(FfiConverterTypeRSExprStmt.read(buf)) + 2 -> RsStmt.Item(FfiConverterTypeRSItem.read(buf)) + 3 -> RsStmt.LetStmt(FfiConverterTypeRSLetStmt.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsStmt) = + when (value) { + is RsStmt.ExprStmt -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSExprStmt.allocationSize(value.v1)) + } + is RsStmt.Item -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSItem.allocationSize(value.v1)) + } + is RsStmt.LetStmt -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSLetStmt.allocationSize(value.v1)) + } + } + + override fun write(value: RsStmt, buf: ByteBuffer) { + when (value) { + is RsStmt.ExprStmt -> { + buf.putInt(1) + FfiConverterTypeRSExprStmt.write(value.v1, buf) + Unit + } + is RsStmt.Item -> { + buf.putInt(2) + FfiConverterTypeRSItem.write(value.v1, buf) + Unit + } + is RsStmt.LetStmt -> { + buf.putInt(3) + FfiConverterTypeRSLetStmt.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsType { + + data class ArrayType(val v1: RsArrayType) : RsType() { + + companion object + } + + data class DynTraitType(val v1: RsDynTraitType) : RsType() { + + companion object + } + + data class FnPtrType(val v1: RsFnPtrType) : RsType() { + + companion object + } + + data class ForType(val v1: RsForType) : RsType() { + + companion object + } + + data class ImplTraitType(val v1: RsImplTraitType) : RsType() { + + companion object + } + + data class InferType(val v1: RsInferType) : RsType() { + + companion object + } + + data class MacroType(val v1: RsMacroType) : RsType() { + + companion object + } + + data class NeverType(val v1: RsNeverType) : RsType() { + + companion object + } + + data class ParenType(val v1: RsParenType) : RsType() { + + companion object + } + + data class PathType(val v1: RsPathType) : RsType() { + + companion object + } + + data class PtrType(val v1: RsPtrType) : RsType() { + + companion object + } + + data class RefType(val v1: RsRefType) : RsType() { + + companion object + } + + data class SliceType(val v1: RsSliceType) : RsType() { + + companion object + } + + data class TupleType(val v1: RsTupleType) : RsType() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsType { + return when (buf.getInt()) { + 1 -> RsType.ArrayType(FfiConverterTypeRSArrayType.read(buf)) + 2 -> RsType.DynTraitType(FfiConverterTypeRSDynTraitType.read(buf)) + 3 -> RsType.FnPtrType(FfiConverterTypeRSFnPtrType.read(buf)) + 4 -> RsType.ForType(FfiConverterTypeRSForType.read(buf)) + 5 -> RsType.ImplTraitType(FfiConverterTypeRSImplTraitType.read(buf)) + 6 -> RsType.InferType(FfiConverterTypeRSInferType.read(buf)) + 7 -> RsType.MacroType(FfiConverterTypeRSMacroType.read(buf)) + 8 -> RsType.NeverType(FfiConverterTypeRSNeverType.read(buf)) + 9 -> RsType.ParenType(FfiConverterTypeRSParenType.read(buf)) + 10 -> RsType.PathType(FfiConverterTypeRSPathType.read(buf)) + 11 -> RsType.PtrType(FfiConverterTypeRSPtrType.read(buf)) + 12 -> RsType.RefType(FfiConverterTypeRSRefType.read(buf)) + 13 -> RsType.SliceType(FfiConverterTypeRSSliceType.read(buf)) + 14 -> RsType.TupleType(FfiConverterTypeRSTupleType.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsType) = + when (value) { + is RsType.ArrayType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSArrayType.allocationSize(value.v1)) + } + is RsType.DynTraitType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSDynTraitType.allocationSize(value.v1)) + } + is RsType.FnPtrType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSFnPtrType.allocationSize(value.v1)) + } + is RsType.ForType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSForType.allocationSize(value.v1)) + } + is RsType.ImplTraitType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSImplTraitType.allocationSize(value.v1)) + } + is RsType.InferType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSInferType.allocationSize(value.v1)) + } + is RsType.MacroType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSMacroType.allocationSize(value.v1)) + } + is RsType.NeverType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSNeverType.allocationSize(value.v1)) + } + is RsType.ParenType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSParenType.allocationSize(value.v1)) + } + is RsType.PathType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSPathType.allocationSize(value.v1)) + } + is RsType.PtrType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSPtrType.allocationSize(value.v1)) + } + is RsType.RefType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSRefType.allocationSize(value.v1)) + } + is RsType.SliceType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSSliceType.allocationSize(value.v1)) + } + is RsType.TupleType -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSTupleType.allocationSize(value.v1)) + } + } + + override fun write(value: RsType, buf: ByteBuffer) { + when (value) { + is RsType.ArrayType -> { + buf.putInt(1) + FfiConverterTypeRSArrayType.write(value.v1, buf) + Unit + } + is RsType.DynTraitType -> { + buf.putInt(2) + FfiConverterTypeRSDynTraitType.write(value.v1, buf) + Unit + } + is RsType.FnPtrType -> { + buf.putInt(3) + FfiConverterTypeRSFnPtrType.write(value.v1, buf) + Unit + } + is RsType.ForType -> { + buf.putInt(4) + FfiConverterTypeRSForType.write(value.v1, buf) + Unit + } + is RsType.ImplTraitType -> { + buf.putInt(5) + FfiConverterTypeRSImplTraitType.write(value.v1, buf) + Unit + } + is RsType.InferType -> { + buf.putInt(6) + FfiConverterTypeRSInferType.write(value.v1, buf) + Unit + } + is RsType.MacroType -> { + buf.putInt(7) + FfiConverterTypeRSMacroType.write(value.v1, buf) + Unit + } + is RsType.NeverType -> { + buf.putInt(8) + FfiConverterTypeRSNeverType.write(value.v1, buf) + Unit + } + is RsType.ParenType -> { + buf.putInt(9) + FfiConverterTypeRSParenType.write(value.v1, buf) + Unit + } + is RsType.PathType -> { + buf.putInt(10) + FfiConverterTypeRSPathType.write(value.v1, buf) + Unit + } + is RsType.PtrType -> { + buf.putInt(11) + FfiConverterTypeRSPtrType.write(value.v1, buf) + Unit + } + is RsType.RefType -> { + buf.putInt(12) + FfiConverterTypeRSRefType.write(value.v1, buf) + Unit + } + is RsType.SliceType -> { + buf.putInt(13) + FfiConverterTypeRSSliceType.write(value.v1, buf) + Unit + } + is RsType.TupleType -> { + buf.putInt(14) + FfiConverterTypeRSTupleType.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsUseBoundGenericArg { + + data class Lifetime(val v1: RsLifetime) : RsUseBoundGenericArg() { + + companion object + } + + data class NameRef(val v1: RsNameRef) : RsUseBoundGenericArg() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSUseBoundGenericArg : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsUseBoundGenericArg { + return when (buf.getInt()) { + 1 -> RsUseBoundGenericArg.Lifetime(FfiConverterTypeRSLifetime.read(buf)) + 2 -> RsUseBoundGenericArg.NameRef(FfiConverterTypeRSNameRef.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsUseBoundGenericArg) = + when (value) { + is RsUseBoundGenericArg.Lifetime -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSLifetime.allocationSize(value.v1)) + } + is RsUseBoundGenericArg.NameRef -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSNameRef.allocationSize(value.v1)) + } + } + + override fun write(value: RsUseBoundGenericArg, buf: ByteBuffer) { + when (value) { + is RsUseBoundGenericArg.Lifetime -> { + buf.putInt(1) + FfiConverterTypeRSLifetime.write(value.v1, buf) + Unit + } + is RsUseBoundGenericArg.NameRef -> { + buf.putInt(2) + FfiConverterTypeRSNameRef.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class RsVariantDef { + + data class Struct(val v1: RsStruct) : RsVariantDef() { + + companion object + } + + data class Union(val v1: RsUnion) : RsVariantDef() { + + companion object + } + + data class Variant(val v1: RsVariant) : RsVariantDef() { + + companion object + } + + companion object +} + +/** @suppress */ +public object FfiConverterTypeRSVariantDef : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsVariantDef { + return when (buf.getInt()) { + 1 -> RsVariantDef.Struct(FfiConverterTypeRSStruct.read(buf)) + 2 -> RsVariantDef.Union(FfiConverterTypeRSUnion.read(buf)) + 3 -> RsVariantDef.Variant(FfiConverterTypeRSVariant.read(buf)) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: RsVariantDef) = + when (value) { + is RsVariantDef.Struct -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSStruct.allocationSize(value.v1)) + } + is RsVariantDef.Union -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSUnion.allocationSize(value.v1)) + } + is RsVariantDef.Variant -> { + // Add the size for the Int that specifies the variant plus the size needed for all + // fields + (4UL + FfiConverterTypeRSVariant.allocationSize(value.v1)) + } + } + + override fun write(value: RsVariantDef, buf: ByteBuffer) { + when (value) { + is RsVariantDef.Struct -> { + buf.putInt(1) + FfiConverterTypeRSStruct.write(value.v1, buf) + Unit + } + is RsVariantDef.Union -> { + buf.putInt(2) + FfiConverterTypeRSUnion.write(value.v1, buf) + Unit + } + is RsVariantDef.Variant -> { + buf.putInt(3) + FfiConverterTypeRSVariant.write(value.v1, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +/** @suppress */ +public object FfiConverterOptionalString : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.String? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterString.read(buf) + } + + override fun allocationSize(value: kotlin.String?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterString.allocationSize(value) + } + } + + override fun write(value: kotlin.String?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterString.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSAbi : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsAbi? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSAbi.read(buf) + } + + override fun allocationSize(value: RsAbi?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSAbi.allocationSize(value) + } + } + + override fun write(value: RsAbi?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSAbi.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSBlockExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsBlockExpr? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSBlockExpr.read(buf) + } + + override fun allocationSize(value: RsBlockExpr?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSBlockExpr.allocationSize(value) + } + } + + override fun write(value: RsBlockExpr?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSBlockExpr.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSConstArg : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsConstArg? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSConstArg.read(buf) + } + + override fun allocationSize(value: RsConstArg?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSConstArg.allocationSize(value) + } + } + + override fun write(value: RsConstArg?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSConstArg.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSLifetime : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLifetime? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSLifetime.read(buf) + } + + override fun allocationSize(value: RsLifetime?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSLifetime.allocationSize(value) + } + } + + override fun write(value: RsLifetime?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSLifetime.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSLiteral : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsLiteral? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSLiteral.read(buf) + } + + override fun allocationSize(value: RsLiteral?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSLiteral.allocationSize(value) + } + } + + override fun write(value: RsLiteral?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSLiteral.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSMacroCall : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsMacroCall? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSMacroCall.read(buf) + } + + override fun allocationSize(value: RsMacroCall?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSMacroCall.allocationSize(value) + } + } + + override fun write(value: RsMacroCall?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSMacroCall.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSNameRef : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsNameRef? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSNameRef.read(buf) + } + + override fun allocationSize(value: RsNameRef?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSNameRef.allocationSize(value) + } + } + + override fun write(value: RsNameRef?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSNameRef.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSParamList : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsParamList? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSParamList.read(buf) + } + + override fun allocationSize(value: RsParamList?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSParamList.allocationSize(value) + } + } + + override fun write(value: RsParamList?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSParamList.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSPath : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPath? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSPath.read(buf) + } + + override fun allocationSize(value: RsPath?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSPath.allocationSize(value) + } + } + + override fun write(value: RsPath?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSPath.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSPathSegment : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPathSegment? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSPathSegment.read(buf) + } + + override fun allocationSize(value: RsPathSegment?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSPathSegment.allocationSize(value) + } + } + + override fun write(value: RsPathSegment?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSPathSegment.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSRecordFieldList : + FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsRecordFieldList? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSRecordFieldList.read(buf) + } + + override fun allocationSize(value: RsRecordFieldList?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSRecordFieldList.allocationSize(value) + } + } + + override fun write(value: RsRecordFieldList?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSRecordFieldList.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSReturnTypeSyntax : + FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsReturnTypeSyntax? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSReturnTypeSyntax.read(buf) + } + + override fun allocationSize(value: RsReturnTypeSyntax?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSReturnTypeSyntax.allocationSize(value) + } + } + + override fun write(value: RsReturnTypeSyntax?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSReturnTypeSyntax.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSSelfParam : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsSelfParam? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSSelfParam.read(buf) + } + + override fun allocationSize(value: RsSelfParam?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSSelfParam.allocationSize(value) + } + } + + override fun write(value: RsSelfParam?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSSelfParam.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSSourceFile : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsSourceFile? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSSourceFile.read(buf) + } + + override fun allocationSize(value: RsSourceFile?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSSourceFile.allocationSize(value) + } + } + + override fun write(value: RsSourceFile?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSSourceFile.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSTypeAnchor : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsTypeAnchor? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSTypeAnchor.read(buf) + } + + override fun allocationSize(value: RsTypeAnchor?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSTypeAnchor.allocationSize(value) + } + } + + override fun write(value: RsTypeAnchor?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSTypeAnchor.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSUseTree : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsUseTree? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSUseTree.read(buf) + } + + override fun allocationSize(value: RsUseTree?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSUseTree.allocationSize(value) + } + } + + override fun write(value: RsUseTree?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSUseTree.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSExpr : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsExpr? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSExpr.read(buf) + } + + override fun allocationSize(value: RsExpr?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSExpr.allocationSize(value) + } + } + + override fun write(value: RsExpr?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSExpr.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSFieldList : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsFieldList? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSFieldList.read(buf) + } + + override fun allocationSize(value: RsFieldList?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSFieldList.allocationSize(value) + } + } + + override fun write(value: RsFieldList?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSFieldList.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSPat : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsPat? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSPat.read(buf) + } + + override fun allocationSize(value: RsPat?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSPat.allocationSize(value) + } + } + + override fun write(value: RsPat?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSPat.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterOptionalTypeRSType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RsType? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRSType.read(buf) + } + + override fun allocationSize(value: RsType?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRSType.allocationSize(value) + } + } + + override fun write(value: RsType?, buf: ByteBuffer) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRSType.write(value, buf) + } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSBlockExpr : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSBlockExpr.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSBlockExpr.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSBlockExpr.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSMatchArm : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSMatchArm.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSMatchArm.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSMatchArm.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSNameRef : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSNameRef.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSNameRef.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSNameRef.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSParam : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSParam.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSParam.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSParam.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSParamList : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSParamList.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSParamList.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSParamList.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSPath : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSPath.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSPath.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSPath.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSPathType : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSPathType.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSPathType.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSPathType.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSRecordExprField : + FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSRecordExprField.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSRecordExprField.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSRecordExprField.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSRecordField : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSRecordField.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSRecordField.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSRecordField.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSRecordPatField : + FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSRecordPatField.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSRecordPatField.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSRecordPatField.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSTupleField : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSTupleField.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSTupleField.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSTupleField.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSTypeBound : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSTypeBound.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSTypeBound.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSTypeBound.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSUseTree : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSUseTree.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSUseTree.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSUseTree.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSVariant : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSVariant.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSVariant.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSVariant.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSAssocItem : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSAssocItem.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSAssocItem.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSAssocItem.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSAst : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSAst.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSAst.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSAst.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSExpr : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSExpr.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSExpr.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSExpr.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSExternItem : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSExternItem.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSExternItem.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSExternItem.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSFieldList : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSFieldList.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSFieldList.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSFieldList.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSGenericArg : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSGenericArg.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSGenericArg.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSGenericArg.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSGenericParam : + FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSGenericParam.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSGenericParam.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSGenericParam.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSItem : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSItem.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSItem.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSItem.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSPat : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSPat.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSPat.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSPat.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSStmt : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSStmt.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSStmt.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSStmt.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSType : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSType.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRSType.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSType.write(it, buf) } + } +} + +/** @suppress */ +public object FfiConverterSequenceTypeRSUseBoundGenericArg : + FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { FfiConverterTypeRSUseBoundGenericArg.read(buf) } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = + value.map { FfiConverterTypeRSUseBoundGenericArg.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write(value: List, buf: ByteBuffer) { + buf.putInt(value.size) + value.iterator().forEach { FfiConverterTypeRSUseBoundGenericArg.write(it, buf) } + } +} + +fun `parseRustCode`(`source`: kotlin.String): RsSourceFile? { + return FfiConverterOptionalTypeRSSourceFile.lift( + uniffiRustCall() { _status -> + UniffiLib.uniffi_rustast_fn_func_parse_rust_code( + FfiConverterString.lower(`source`), + _status, + ) + } + ) +} diff --git a/cpg-language-rust/src/test/kotlin/de/fraunhoder/aisec/cpg/frontends/rust/ControlFlowTest.kt b/cpg-language-rust/src/test/kotlin/de/fraunhoder/aisec/cpg/frontends/rust/ControlFlowTest.kt new file mode 100644 index 00000000000..dcffea7e44a --- /dev/null +++ b/cpg-language-rust/src/test/kotlin/de/fraunhoder/aisec/cpg/frontends/rust/ControlFlowTest.kt @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhoder.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.frontends.rust.RustLanguage +import de.fraunhofer.aisec.cpg.graph.collectAllPrevDFGPaths +import de.fraunhofer.aisec.cpg.graph.declarations.Parameter +import de.fraunhofer.aisec.cpg.graph.expressions.Assign +import de.fraunhofer.aisec.cpg.graph.expressions.BinaryOperator +import de.fraunhofer.aisec.cpg.graph.expressions.Block +import de.fraunhofer.aisec.cpg.graph.expressions.Break +import de.fraunhofer.aisec.cpg.graph.expressions.Call +import de.fraunhofer.aisec.cpg.graph.expressions.Case +import de.fraunhofer.aisec.cpg.graph.expressions.Deconstruction +import de.fraunhofer.aisec.cpg.graph.expressions.Empty +import de.fraunhofer.aisec.cpg.graph.expressions.IfElse +import de.fraunhofer.aisec.cpg.graph.expressions.Literal +import de.fraunhofer.aisec.cpg.graph.expressions.MemberCall +import de.fraunhofer.aisec.cpg.graph.expressions.ObjectDeconstruction +import de.fraunhofer.aisec.cpg.graph.expressions.Range +import de.fraunhofer.aisec.cpg.graph.expressions.Reference +import de.fraunhofer.aisec.cpg.graph.forEachLoops +import de.fraunhofer.aisec.cpg.graph.functions +import de.fraunhofer.aisec.cpg.graph.get +import de.fraunhofer.aisec.cpg.graph.refs +import de.fraunhofer.aisec.cpg.graph.statements +import de.fraunhofer.aisec.cpg.graph.switches +import de.fraunhofer.aisec.cpg.graph.variables +import de.fraunhofer.aisec.cpg.graph.whileLoops +import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker +import de.fraunhofer.aisec.cpg.test.analyzeAndGetFirstTU +import java.nio.file.Path +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertIs +import kotlin.test.assertNotEquals +import kotlin.test.assertNotNull +import kotlin.test.assertTrue +import org.junit.jupiter.api.assertInstanceOf +import org.junit.jupiter.api.assertNull + +class ControlFlowTest { + + @Test + fun testWhile() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU( + listOf(topLevel.resolve("cfstructures.rs").toFile()), + topLevel, + true, + ) { + it.registerLanguage() + } + assertNotNull(tu) + + val function = tu.functions["while_examples"] + assertNotNull(function) + + val whiles = function.whileLoops + + assertEquals(whiles.size, 2) + + val while1 = whiles[0] + + assertInstanceOf(while1.condition) + + var body = while1.statement + + assertNotNull(body) + + assertInstanceOf(body) + + assertEquals(body.statements.size, 2) + + val while2 = whiles[1] + + assertInstanceOf(while2.condition) + + body = while2.statement + + assertNotNull(body) + + assertInstanceOf(body) + + assertEquals(body.statements.size, 3) + } + + @Test + fun testWhileLet() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU( + listOf(topLevel.resolve("cfstructures.rs").toFile()), + topLevel, + true, + ) { + it.registerLanguage() + } + assertNotNull(tu) + + val function = tu.functions["while_let_examples"] + assertNotNull(function) + + val whiles = function.whileLoops + + // 2 while let statements in while_let_examples + assertEquals(whiles.size, 2) + + val whileLet1 = whiles[0] + + assertInstanceOf(whileLet1.condition) + + var body = whileLet1.statement + assertNotNull(body) + assertInstanceOf(body) + assertEquals(body.statements.size, 1) + + var variable = whileLet1.variables.firstOrNull() + assertNotNull(variable) + assertEquals(variable.name.toString(), "v") + + val whileLet2 = whiles[1] + assertInstanceOf(whileLet2.condition) + body = whileLet2.statement + assertNotNull(body) + assertInstanceOf(body) + assertEquals(body.statements.size, 1) + assertNotNull(whileLet2.variables["item"]) + } + + @Test + fun testLoop() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU( + listOf(topLevel.resolve("cfstructures.rs").toFile()), + topLevel, + true, + ) { + it.registerLanguage() + } + assertNotNull(tu) + + val function = tu.functions["loop_examples"] + assertNotNull(function) + + val loops = function.whileLoops + + // 2 loop statements (loop is translated to while with true condition) in loop_examples + assertEquals(loops.size, 2) + + val loop1 = loops[0] + assertInstanceOf>(loop1.condition) + var body = loop1.statement + assertNotNull(body) + assertInstanceOf(body) + assertEquals(body.statements.size, 3) + + val loop2 = loops[1] + body = loop2.statement + assertNotNull(body) + assertInstanceOf(body) + assertEquals(body.statements.size, 3) + } + + @Test + fun testIf() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU( + listOf(topLevel.resolve("cfstructures.rs").toFile()), + topLevel, + true, + ) { + it.registerLanguage() + } + assertNotNull(tu) + + val function = tu.functions["if_examples"] + assertNotNull(function) + + val ifs = SubgraphWalker.flattenAST(function).filterIsInstance() + + // 5 if statements in if_examples: if without else, if with else, if/else if/else, nested + // if, if as expression + assertEquals(ifs.size, 7) + + val if1 = ifs[0] + assertInstanceOf(if1.condition) + var then = if1.thenStatement + assertNotNull(then) + assertInstanceOf(then) + assertEquals(then.statements.size, 1) + + var elseStmt = if1.elseStatement + assertNull(elseStmt) + + val if2 = ifs[1] + + assertInstanceOf(if2.condition) + then = if2.thenStatement + assertNotNull(then) + assertInstanceOf(then) + assertEquals(then.statements.size, 1) + + elseStmt = if2.elseStatement + assertNotNull(elseStmt) + assertInstanceOf(elseStmt) + assertEquals(elseStmt.statements.size, 1) + + val if3 = ifs[2] + + assertInstanceOf(if3.condition) + then = if3.thenStatement + assertNotNull(then) + assertInstanceOf(then) + assertEquals(then.statements.size, 1) + + elseStmt = if3.elseStatement + assertNotNull(elseStmt) + assertEquals(elseStmt, ifs[3]) + + val if5 = ifs[4] + + assertInstanceOf(if5.condition) + then = if5.thenStatement + assertNotNull(then) + assertInstanceOf(then) + assertEquals(then.statements.size, 2) + + assertTrue(then.statements[1] is IfElse) + + elseStmt = if5.elseStatement + assertNotNull(elseStmt) + assertInstanceOf(elseStmt) + assertEquals(elseStmt.statements.size, 1) + + val if7 = ifs[6] + + assertInstanceOf(if7.condition) + then = if7.thenStatement + assertNotNull(then) + assertInstanceOf(then) + assertEquals(then.statements.size, 2) + + elseStmt = if7.elseStatement + assertNotNull(elseStmt) + assertInstanceOf(elseStmt) + assertEquals(elseStmt.statements.size, 2) + + assertTrue(if7.prevDFG.flatMap { it.prevDFG }.contains(then.statements.last())) + assertTrue(if7.prevDFG.flatMap { it.prevDFG }.contains(elseStmt.statements.last())) + } + + @Test + fun testIfLet() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU( + listOf(topLevel.resolve("cfstructures.rs").toFile()), + topLevel, + true, + ) { + it.registerLanguage() + } + assertNotNull(tu) + + val function = tu.functions["if_let_examples"] + assertNotNull(function) + + val ifLets = SubgraphWalker.flattenAST(function).filterIsInstance() + + // 3 if let statements in if_let_examples: if let without else, if let with else, chained if + // let + assertEquals(ifLets.size, 1) + + val ifLet = ifLets[0] + assertInstanceOf(ifLet.condition) + var then = ifLet.thenStatement + assertNotNull(then) + assertInstanceOf(then) + assertEquals(then.statements.size, 1) + } + + @Ignore + @Test + fun testLetElse() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU( + listOf(topLevel.resolve("cfstructures.rs").toFile()), + topLevel, + true, + ) { + it.registerLanguage() + } + assertNotNull(tu) + + val function = tu.functions["let_else_example"] + assertNotNull(function) + + val switches = function.switches + + // 1 let else statement in let_else_example + assertEquals(switches.size, 1) + + val letElse1 = function.switches[0] + assertNotNull(letElse1) + assertIs(letElse1.selector) + var ref = letElse1.selector as Reference + assertEquals(ref.name.toString(), "opt") + + val block = letElse1.statement as Block + assertNotNull(block) + + val statements = block.statements + + assertEquals(4, statements.size) + + val case = statements.first() as Case + assertInstanceOf(case.caseExpression) + + assertInstanceOf(statements[1]) + + val breakStmt = statements[1] as Break + assertNotNull(breakStmt.expr) + + breakStmt.expr.refs.forEach { assertTrue(case.variables.contains(it.refersTo)) } + + assertInstanceOf(letElse1.astParent) + + val assign = letElse1.astParent as Assign + assertInstanceOf(assign.lhs.first()) + + val oDec = assign.lhs.first() as ObjectDeconstruction + assertEquals(oDec.variables.size, 1) + assertEquals(oDec.variables.first().name.toString(), "value") + + // Collect all literals reachable from the reference after the let else + val reference = function.body?.astChildren?.filterIsInstance()?.firstOrNull() + assertNotNull(reference) + val reachableDFG = + reference + .collectAllPrevDFGPaths() + .flatMap { it.nodes } + .filterIsInstance() + .toSet() + assertNotEquals(0, reachableDFG.size) + } + + @Test + fun testMatch() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU( + listOf(topLevel.resolve("cfstructures.rs").toFile()), + topLevel, + true, + ) { + it.registerLanguage() + } + assertNotNull(tu) + + val function = tu.functions["match_examples"] + assertNotNull(function) + + val switches = function.switches + + // 4 match statements in match_examples: simple match, match with ranges, match with guard, + // match on enum-like + assertEquals(switches.size, 4) + + val match1 = function.switches[0] + assertNotNull(match1) + assertIs(match1.selector) + var ref = match1.selector as Reference + assertEquals(ref.name.toString(), "value") + + var children = match1.statement?.astChildren ?: emptyList() + var cases = children.filterIsInstance() + var others = children.filter { !cases.contains(it) } + + others.forEach { + assertInstanceOf(it) + assertInstanceOf(it.astChildren.first()) + } + + assertInstanceOf>(cases[0].caseExpression) + var literal = cases[0].caseExpression as Literal + assertEquals("0", literal.value.toString()) + + assertInstanceOf>(cases[1].caseExpression) + literal = cases[1].caseExpression as Literal + assertEquals("1", literal.value.toString()) + + assertInstanceOf(cases[2].caseExpression) + + val match2 = function.switches[1] + assertNotNull(match2) + assertIs(match2.selector) + ref = match2.selector as Reference + assertEquals(ref.name.toString(), "value") + + children = match2.statement?.astChildren ?: emptyList() + cases = children.filterIsInstance() + others = children.filter { !cases.contains(it) } + + others.forEach { + assertInstanceOf(it) + assertInstanceOf(it.astChildren.first()) + } + + assertInstanceOf(cases[0].caseExpression) + var range = cases[0].caseExpression as Range + assertEquals("0", (range.floor as Literal<*>).value.toString()) + assertEquals("10", (range.ceiling as Literal<*>).value.toString()) + + assertInstanceOf(cases[1].caseExpression) + range = cases[1].caseExpression as Range + assertEquals("11", (range.floor as Literal<*>).value.toString()) + assertEquals("100", (range.ceiling as Literal<*>).value.toString()) + + assertInstanceOf(cases[2].caseExpression) + + val match3 = function.switches[2] + + assertNotNull(match3) + assertIs(match3.selector) + ref = match3.selector as Reference + assertEquals(ref.name.toString(), "value") + + children = match3.statement?.astChildren ?: emptyList() + cases = children.filterIsInstance() + others = children.filter { !cases.contains(it) } + + others.dropLast(1).forEach { + assertInstanceOf(it) + assertInstanceOf(it.thenStatement?.astChildren?.first()) + } + + val match4 = function.switches[3] + + assertNotNull(match4) + assertIs(match4.selector) + ref = match4.selector as Reference + assertEquals(ref.name.toString(), "opt") + + children = match4.statement?.astChildren ?: emptyList() + cases = children.filterIsInstance() + + assertInstanceOf(cases[0].caseExpression) + // assertInstanceOf(cases[0].caseExpression) + + } + + @Test + fun testFor() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU( + listOf(topLevel.resolve("cfstructures.rs").toFile()), + topLevel, + true, + ) { + it.registerLanguage() + } + assertNotNull(tu) + + val function = tu.functions["for_examples"] + assertNotNull(function) + + val forLoops = function.forEachLoops + + // 3 for loops in for_examples: for over range, for over iterator, for with enumerate + assertEquals(forLoops.size, 3) + + val for1 = forLoops[0] + + assertEquals("i", for1.variable.variables.first().name.toString()) + + assertInstanceOf(for1.iterable) + + assertInstanceOf(for1.statement) + + assertInstanceOf(for1.statement?.astChildren?.first()) + + val for2 = forLoops[1] + assertEquals("item", for2.variable.variables.first().name.toString()) + assertInstanceOf(for2.iterable) + assertInstanceOf(for2.statement) + assertInstanceOf(for2.statement?.astChildren?.first()) + + val for3 = forLoops[2] + + assertInstanceOf(for3.variable) + + assertEquals("index", for3.variable.variables.first().name.toString()) + assertEquals("value", for3.variable.variables.last().name.toString()) + + assertInstanceOf(for3.iterable) + + assertInstanceOf(for3.statement) + + assertInstanceOf(for3.statement?.astChildren?.first()) + } +} diff --git a/cpg-language-rust/src/test/kotlin/de/fraunhoder/aisec/cpg/frontends/rust/RustLanguageFrontendTest.kt b/cpg-language-rust/src/test/kotlin/de/fraunhoder/aisec/cpg/frontends/rust/RustLanguageFrontendTest.kt new file mode 100644 index 00000000000..a144286583a --- /dev/null +++ b/cpg-language-rust/src/test/kotlin/de/fraunhoder/aisec/cpg/frontends/rust/RustLanguageFrontendTest.kt @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2026, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhoder.aisec.cpg.frontends.rust + +import de.fraunhofer.aisec.cpg.frontends.rust.RustLanguage +import de.fraunhofer.aisec.cpg.graph.calls +import de.fraunhofer.aisec.cpg.graph.collectAllPrevDFGPaths +import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnit +import de.fraunhofer.aisec.cpg.graph.declarations.Variable +import de.fraunhofer.aisec.cpg.graph.expressions.Literal +import de.fraunhofer.aisec.cpg.graph.expressions.Switch +import de.fraunhofer.aisec.cpg.graph.functions +import de.fraunhofer.aisec.cpg.graph.get +import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker +import de.fraunhofer.aisec.cpg.test.analyzeAndGetFirstTU +import java.nio.file.Path +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + +class RustLanguageFrontendTest { + @Test + fun testFunctionResolutionWithUse() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU(listOf(topLevel.resolve("use.rs").toFile()), topLevel, true) { + it.registerLanguage() + } + assertNotNull(tu) + + // Assert functions exist and are not inferred + val add = tu.functions["math::basic::add"] + assertNotNull(add) + assert(!add.isInferred) + + val sub = tu.functions["math::basic::sub"] + assertNotNull(sub) + assert(!sub.isInferred) + + val mul = tu.functions["math::advanced::mul"] + assertNotNull(mul) + assert(!mul.isInferred) + + val div = tu.functions["math::advanced::div"] + assertNotNull(div) + assert(!div.isInferred) + + val utilsHelper = tu.functions["utils::helper"] + assertNotNull(utilsHelper) + assert(!utilsHelper.isInferred) + + val innerHelper = tu.functions["utils::inner::helper"] + assertNotNull(innerHelper) + assert(!innerHelper.isInferred) + + val foo = tu.functions["extra::foo"] + assertNotNull(foo) + assert(!foo.isInferred) + + val bar = tu.functions["extra::bar"] + assertNotNull(bar) + assert(!bar.isInferred) + + val local = tu.functions["nested::local"] + assertNotNull(local) + assert(!local.isInferred) + + val nestedChildCall = tu.functions["nested::child::call"] + assertNotNull(nestedChildCall) + assert(!nestedChildCall.isInferred) + + // Assert calls exist and invoke the correct functions + val addFnCall = tu.calls["add_fn"] + assertNotNull(addFnCall) + assert(addFnCall.invokes.contains(add)) + + val subFnCall = tu.calls["sub_fn"] + assertNotNull(subFnCall) + assert(subFnCall.invokes.contains(sub)) + + val mulFnCall = tu.calls["mul_fn"] + assertNotNull(mulFnCall) + assert(mulFnCall.invokes.contains(mul)) + + val divFnCall = tu.calls["div_fn"] + assertNotNull(divFnCall) + assert(divFnCall.invokes.contains(div)) + + val fooCall = tu.calls["foo"] + assertNotNull(fooCall) + assert(fooCall.invokes.contains(foo)) + + val barCall = tu.calls["bar"] + assertNotNull(barCall) + assert(barCall.invokes.contains(bar)) + + val rootHelperCall = tu.calls["root_helper"] + assertNotNull(rootHelperCall) + assert(rootHelperCall.invokes.contains(utilsHelper)) + + val innerHelperFnCall = tu.calls["inner_helper_fn"] + assertNotNull(innerHelperFnCall) + assert(innerHelperFnCall.invokes.contains(innerHelper)) + + val addLocalCall = tu.calls["add_local"] + assertNotNull(addLocalCall) + assert(addLocalCall.invokes.contains(add)) + + val subLocalCall = tu.calls["sub_local"] + assertNotNull(subLocalCall) + assert(subLocalCall.invokes.contains(sub)) + + val mulLocalCall = tu.calls["mul_local"] + assertNotNull(mulLocalCall) + assert(mulLocalCall.invokes.contains(mul)) + + val parentLocal = tu.calls["parent_local"] + assertNotNull(parentLocal) + assert(parentLocal.invokes.contains(local)) + + // For helper calls, since multiple with same name, filter and check + val helperCalls = tu.calls.filter { it.name.localName == "helper" } + assert(helperCalls.size == 5) + + // Assuming order: line 101, 106, 109, 117, 121 + assert(helperCalls[0].invokes.contains(utilsHelper)) // line 101 + assert(helperCalls[1].invokes.contains(innerHelper)) // line 106 + assert(helperCalls[2].invokes.contains(utilsHelper)) // line 109 + assert(helperCalls[3].invokes.contains(utilsHelper)) // line 117 + assert(helperCalls[4].invokes.contains(innerHelper)) // line 121 + + // For the call to nested::child::call + val callCall = tu.calls["call"] + assertNotNull(callCall) + assert(callCall.invokes.contains(nestedChildCall)) + } + + @Test + fun testDFandMatchDeconstruction() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU(listOf(topLevel.resolve("match.rs").toFile()), topLevel, true) { + it.registerLanguage() + } + assertNotNull(tu) + + // Test match in handle_wrap function + // 1st match: possible results: 1,2,3 + testMatchStatement(tu, "handle_wrap", 0, listOf("1", "2", "3")) + + // Test match in handle_tuple function + // 1st match: possible results: 4,5 + testMatchStatement(tu, "handle_tuple", 0, listOf("4", "5")) + + // Test match in handle_alternative function + // 1st match: possible results: 4,5 + testMatchStatement(tu, "handle_alternative", 0, listOf("4", "5")) + + // Test match in handle_deep function + // 1st match: possible results: 7,8,9 + testMatchStatement(tu, "handle_deep", 0, listOf("7", "8")) + + // 2nd match in handle_deep: possible results: 7,9 + testMatchStatement(tu, "handle_deep", 1, listOf("7", "9")) + + // Test match in process_all function + // 1st match: possible results: 10,11,13,14,15 + testMatchStatement(tu, "process_all", 0, listOf("10", "11", "13", "14", "15")) + } + + private fun testMatchStatement( + tu: TranslationUnit, + functionName: String, + matchIndex: Int, + expectedLiterals: List, + ) { + // Get the translation unit as a proper type to access functions + val function = tu.functions[functionName] + + assertNotNull(function, "Function '$functionName' should exist") + + // Get all switch statements in the function + val switchStatements = SubgraphWalker.flattenAST(function).filterIsInstance() + assertTrue( + switchStatements.size > matchIndex, + "Function '$functionName' should have at least ${matchIndex + 1} match statement(s). Found: ${switchStatements.size}", + ) + + val switchStatement = switchStatements[matchIndex] + + // Collect all literals reachable from the switch through DFG using built-in function + val reachableLiterals = + switchStatement + .collectAllPrevDFGPaths() + .flatMap { it.nodes } + .filterIsInstance>() + .map { it.value.toString() } + .toSet() + + // Verify all expected literals are reachable + for (expectedLiteral in expectedLiterals) { + assertTrue( + reachableLiterals.contains(expectedLiteral), + "Match #$matchIndex in function '$functionName' should have DFG path to literal '$expectedLiteral'. Found: $reachableLiterals", + ) + } + } + + @Ignore + @Test + fun testDFInLetStatements() { + val topLevel = Path.of("src", "test", "resources") + val tu = + analyzeAndGetFirstTU(listOf(topLevel.resolve("let.rs").toFile()), topLevel, true) { + it.registerLanguage() + } + assertNotNull(tu) + + val mainFunction = tu.functions["main"] + assertNotNull(mainFunction, "main function should exist") + + // Test simple binding: let alpha = 77; + testLetVariableDFG(tu, "alpha", listOf("77")) + + // Test tuple destructuring: let (beta, gamma) = (11, 22); + + testLetVariableDFG(tu, "beta", listOf("11")) + testLetVariableDFG(tu, "gamma", listOf("22")) + + // Test nested tuple destructuring: let ((delta, epsilon), zeta) = ((33, 44), 55); + testLetVariableDFG(tu, "delta", listOf("33")) + testLetVariableDFG(tu, "epsilon", listOf("44")) + testLetVariableDFG(tu, "zeta", listOf("55")) + + // Test struct destructuring: let Coord { a1, b1 } = c1; (where c1 = Coord { a1: 100, b1: + // 200 }) + testLetVariableDFG(tu, "a1", listOf("100")) + testLetVariableDFG(tu, "b1", listOf("200")) + + // Test struct destructuring with renaming: let Coord { a1: left_val, b1: _ } = c2; (where + // c2 = Coord { a1: 300, b1: 400 }) + testLetVariableDFG(tu, "left_val", listOf("300")) + + // Test array destructuring: let [first_val, second_val, ..] = data_arr; (where data_arr = + // [9, 8, 7, 6]) + testLetVariableDFG(tu, "first_val", listOf("9")) + testLetVariableDFG(tu, "second_val", listOf("8")) + + // Test ref binding: let ref greet_ref = greeting; (where greeting = "world") + testLetVariableDFG(tu, "greet_ref", listOf("\"world\"")) + + // Test ref mut binding: let ref mut counter_ref = counter; (where counter = 12) + testLetVariableDFG(tu, "counter_ref", listOf("12")) + + // Test enum destructuring: let Signal::Shift { dx, dy } = sig; (where sig = Signal::Shift { + // dx: 70, dy: 90 }) + testLetVariableDFG(tu, "dx", listOf("70")) + testLetVariableDFG(tu, "dy", listOf("90")) + + // Test if let: if let Some(found) = maybe_num { ... } (where maybe_num = Some(999)) + testLetVariableDFG(tu, "found", listOf("999")) + + // Test while let: while let Some(elem) = series[idx] { ... } (where series = [Some(5), + // Some(6), Some(7), None]) + testLetVariableDFG(tu, "elem", listOf("5", "6", "7")) + + // Test let-else: let Some(extracted) = maybe_text else { ... } (where maybe_text = + // Some("Pattern")) + testLetVariableDFG(tu, "extracted", listOf("\"Pattern\"")) + + // Test @ binding: let bound_val @ 5..=15 = value_check; (where value_check = 8) + testLetVariableDFG(tu, "bound_val", listOf("8")) + + // Test OR pattern: let 3 | 4 | 5 = choice; (where choice = 3) + testLetVariableDFG(tu, "choice", listOf("3")) + + // Test reference destructuring: let &(left_side, right_side) = ref_tuple; (where ref_tuple + // = &(111, 222)) + testLetVariableDFG(tu, "left_side", listOf("111")) + testLetVariableDFG(tu, "right_side", listOf("222")) + + // Test ignoring values: let (keep_a, _, keep_c) = (13, 14, 15); + testLetVariableDFG(tu, "keep_a", listOf("13")) + testLetVariableDFG(tu, "keep_c", listOf("15")) + + // Test slice pattern: let (start_val, .., end_val) = large_tuple; (where large_tuple = (21, + // 22, 23, 24, 25)) + testLetVariableDFG(tu, "start_val", listOf("21")) + testLetVariableDFG(tu, "end_val", listOf("25")) + } + + private fun testLetVariableDFG( + tu: TranslationUnit, + variableName: String, + expectedLiterals: List, + ) { + // Find the variable declaration in the main function + val mainFunction = tu.functions["main"] + assertNotNull(mainFunction, "main function should exist") + + // Find all variable declarations with the given name + val variables = + SubgraphWalker.flattenAST(mainFunction).filterIsInstance().filter { + it.name.localName == variableName + } + + assertTrue(variables.isNotEmpty(), "Variable '$variableName' should exist in main function") + + // For simplicity, take the first one (in case of multiple declarations with same name) + val variable = variables.first() + + // Collect all literals reachable to this variable through DFG + val reachableLiterals = + variable + .collectAllPrevDFGPaths() + .flatMap { it.nodes } + .filterIsInstance>() + .map { it.value.toString() } + .toSet() + + // Verify all expected literals are reachable + for (expectedLiteral in expectedLiterals) { + assertTrue( + reachableLiterals.contains(expectedLiteral), + "Variable '$variableName' should have DFG path to literal '$expectedLiteral'. Found: $reachableLiterals", + ) + } + } +} diff --git a/cpg-language-rust/src/test/resources/cfstructures.rs b/cpg-language-rust/src/test/resources/cfstructures.rs new file mode 100644 index 00000000000..616f4248c6e --- /dev/null +++ b/cpg-language-rust/src/test/resources/cfstructures.rs @@ -0,0 +1,221 @@ +fn mark(point: &str) { + println!("{point}"); +} + +fn if_examples(value: i32) { + // if without else + if value > 0 { + mark("if_without_else_true"); + } + + // if with else + if value % 2 == 0 { + mark("if_with_else_true"); + } else { + mark("if_with_else_false"); + } + + // if / else if / else + if value < 0 { + mark("if_else_if_negative"); + } else if value == 0 { + mark("if_else_if_zero"); + } else { + mark("if_else_if_positive"); + } + + // nested if + if value >= 0 { + mark("nested_if_outer_true"); + + if value > 10 { + mark("nested_if_inner_true"); + } else { + mark("nested_if_inner_false"); + } + } else { + mark("nested_if_outer_false"); + } + + // if as expression + let result = if value > 100 { + mark("if_expression_true"); + "large" + } else { + mark("if_expression_false"); + "small" + }; + + println!("result = {result}"); +} + +fn if_let_examples(opt: Option) { + // if let without else + if let Some(v) = opt { + mark("if_let_without_else_some"); + } + +} + +fn match_examples(value: i32, opt: Option) { + // simple match + match value { + 0 => mark("match_zero"), + 1 => mark("match_one"), + _ => mark("match_default"), + } + + // match with ranges + match value { + 0..=10 => mark("match_range_small"), + 11..=100 => mark("match_range_medium"), + _ => mark("match_range_large"), + } + + // match with guard + match value { + x if x < 0 => mark("match_guard_negative"), + x if x % 2 == 0 => mark("match_guard_even"), + _ => mark("match_guard_other"), + } + + // match on enum-like structure + match opt { + Some(v) => { + mark("match_option_some"); + } + None => { + mark("match_option_none"); + } + } +} + +fn loop_examples() { + // infinite loop with break + let mut counter = 0; + + loop { + if counter >= 2 { + mark("loop_break"); + break; + } + + mark("loop_iteration"); + counter += 1; + } + + // loop with value + let mut x = 0; + + let result = loop { + x += 1; + + if x == 3 { + mark("loop_break_with_value"); + break x * 10; + } + + mark("loop_continue_iteration"); + }; + + println!("loop result = {result}"); +} + +fn while_examples() { + // standard while + let mut count = 0; + + while count < 3 { + mark("while_iteration"); + count += 1; + } + + // while with continue + let mut n = 0; + + while n < 5 { + n += 1; + + if n % 2 == 0 { + mark("while_continue"); + continue; + } + + mark("while_non_continue"); + } +} + +fn while_let_examples() { + // while let with Some + let mut values = vec![1, 2, 3]; + + while let Some(v) = values.pop() { + mark("while_let_some"); + } + + // while let with Result + let mut results = vec![Ok(1), Ok(2), Err("stop")]; + + while let Some(item) = results.pop() { + match item { + Ok(v) => { + mark("while_let_result_ok"); + } + Err(e) => { + mark("while_let_result_err"); + break; + } + } + } +} + +fn for_examples() { + // for over range + for i in 0..3 { + mark("for_range"); + } + + // for over iterator + let items = ["a", "b", "c"]; + + for item in items { + mark("for_iterator"); + } + + // for with enumerate + for (index, value) in items.iter().enumerate() { + mark("for_enumerate"); + } +} + +fn let_else_example(opt: Option<&str>) { + let Some(value) = opt else { + mark("let_else_none"); + return; + }; + value; + + mark("let_else_some"); +} + +fn main() { + if_examples(12); + if_examples(-1); + + if_let_examples(Some(10)); + if_let_examples(None); + + match_examples(5, Some(42)); + match_examples(-2, None); + + loop_examples(); + + while_examples(); + + while_let_examples(); + + for_examples(); + + let_else_example(Some("hello")); + let_else_example(None); +} diff --git a/cpg-language-rust/src/test/resources/let.rs b/cpg-language-rust/src/test/resources/let.rs new file mode 100644 index 00000000000..204aabe1f88 --- /dev/null +++ b/cpg-language-rust/src/test/resources/let.rs @@ -0,0 +1,150 @@ +#[derive(Debug)] +struct Coord { + a1: i32, + b1: i32, +} + +#[derive(Debug)] +enum Signal { + Stop, + Shift { dx: i32, dy: i32 }, + Note(&'static str), + Tint(i32, i32, i32), +} + +// -------------------------------------------------- +// Output helpers (hide println! here) +// -------------------------------------------------- + +fn print_i32(tag: &str, num: i32) { + println!("{} = {}", tag, num); +} + +fn print_pair(tag: &str, p: i32, q: i32) { + println!("{} = ({}, {})", tag, p, q); +} + +fn print_str(tag: &str, txt: &str) { + println!("{} = {}", tag, txt); +} + +// -------------------------------------------------- +// Main demonstrating let-pattern usage +// -------------------------------------------------- + +fn main() { + // -------------------------------------------------- + // 1. Simple binding + // -------------------------------------------------- + let alpha = 77; + print_i32("alpha", alpha); // prints: "alpha = 77" + + // -------------------------------------------------- + // 2. Tuple destructuring + // -------------------------------------------------- + let (beta, gamma) = (11, 22); + print_pair("tuple (beta,gamma)", beta, gamma); // prints: "tuple (beta,gamma) = (11, 22)" + + let ((delta, epsilon), zeta) = ((33, 44), 55); + print_i32("delta", delta); // prints: "delta = 33" + print_i32("epsilon", epsilon); // prints: "epsilon = 44" + print_i32("zeta", zeta); // prints: "zeta = 55" + + // -------------------------------------------------- + // 3. Struct destructuring + // -------------------------------------------------- + let c1 = Coord { a1: 100, b1: 200 }; + let Coord { a1, b1 } = c1; + print_pair("Coord", a1, b1); // prints: "Coord = (100, 200)" + + let c2 = Coord { a1: 300, b1: 400 }; + let Coord { a1: left_val, b1: _ } = c2; + print_i32("left_val", left_val); // prints: "left_val = 300" + + // -------------------------------------------------- + // 4. Array destructuring (no vec!) + // -------------------------------------------------- + let data_arr = [9, 8, 7, 6]; + let [first_val, second_val, ..] = data_arr; + print_pair("array first two", first_val, second_val); // prints: "array first two = (9, 8)" + + // -------------------------------------------------- + // 5. ref / mut in patterns + // -------------------------------------------------- + let greeting = "world"; + let ref greet_ref = greeting; + print_str("ref binding", greet_ref); // prints: "ref binding = world" + + let mut counter = 12; + let ref mut counter_ref = counter; + *counter_ref += 5; + print_i32("mut via pattern", counter); // prints: "mut via pattern = 17" + + // -------------------------------------------------- + // 6. Enum destructuring + // -------------------------------------------------- + let sig = Signal::Shift { dx: 70, dy: 90 }; + let Signal::Shift { dx, dy } = sig; + print_pair("Shift", dx, dy); // prints: "Shift = (70, 90)" + + // -------------------------------------------------- + // 7. if let (refutable pattern) + // -------------------------------------------------- + let maybe_num = Some(999); + + if let Some(found) = maybe_num { + print_i32("if let matched", found); // prints: "if let matched = 999" + } + + // -------------------------------------------------- + // 8. while let (no vec!) + // -------------------------------------------------- + let mut series = [Some(5), Some(6), Some(7), None]; + let mut idx = 0; + + while let Some(elem) = series[idx] { + print_i32("while let value", elem); // prints: "while let value = 5", then 6, then 7 + idx += 1; + } + + // -------------------------------------------------- + // 9. let-else + // -------------------------------------------------- + let maybe_text = Some("Pattern"); + + let Some(extracted) = maybe_text else { + panic!("Expected value"); + }; + print_str("let-else", extracted); // prints: "let-else = Pattern" + + // -------------------------------------------------- + // 10. @ binding + // -------------------------------------------------- + let value_check = 8; + let bound_val @ 5..=15 = value_check; + print_i32("range binding", bound_val); // prints: "range binding = 8" + + // -------------------------------------------------- + // 11. OR patterns + // -------------------------------------------------- + let choice = 3; + let 3 | 4 | 5 = choice; + print_i32("matched 3|4|5", choice); // prints: "matched 3|4|5 = 3" + + // -------------------------------------------------- + // 12. Reference destructuring + // -------------------------------------------------- + let ref_tuple = &(111, 222); + let &(left_side, right_side) = ref_tuple; + print_pair("destructured ref", left_side, right_side); // prints: "destructured ref = (111, 222)" + + // -------------------------------------------------- + // 13. Ignoring values + // -------------------------------------------------- + let (keep_a, _, keep_c) = (13, 14, 15); + print_pair("ignore middle", keep_a, keep_c); // prints: "ignore middle = (13, 15)" + + let large_tuple = (21, 22, 23, 24, 25); + let (start_val, .., end_val) = large_tuple; + print_pair("first/last", start_val, end_val); // prints: "first/last = (21, 25)" +} \ No newline at end of file diff --git a/cpg-language-rust/src/test/resources/match.rs b/cpg-language-rust/src/test/resources/match.rs new file mode 100644 index 00000000000..2244b5cf074 --- /dev/null +++ b/cpg-language-rust/src/test/resources/match.rs @@ -0,0 +1,168 @@ +#[derive(Debug, Clone)] +pub enum Wrap { + One(i32), + Pair(i32, i32), + Nested(Option>), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Event { + Value(i32), +} + +pub trait Sink { + fn push(&mut self, e: Event); +} + +#[derive(Default)] +pub struct VecSink { + pub events: Vec, +} + +impl Sink for VecSink { + fn push(&mut self, e: Event) { + self.events.push(e); + } +} + +pub fn send(sink: &mut S, value: i32) { + sink.push(Event::Value(value)); +} + +/// Match with bindings + literals + wildcard +pub fn handle_wrap(sink: &mut S) { + let input = Wrap::Pair(1, 2); // constructed literals: 1,2 + + let out = match input { + Wrap::One(x) => x, + // uses: x (could be any constructed literal from One) + + Wrap::Pair(a, 2) => a, + // uses: 2 (pattern), a (binding → could be 1) + + Wrap::Pair(_, b) => b, + // uses: wildcard ignores first, b (binding → could be 2) + + Wrap::Nested(Some(Ok(v))) => v, + // uses: v (binding) + + Wrap::Nested(Some(Err(e))) => e, + // uses: e (binding) + + Wrap::Nested(None) => 3, + // uses: literal 3 + }; + // possible results: 1,2,3 (depending on path) + + send(sink, out); +} + +/// Tuple match with mixed patterns +pub fn handle_tuple(sink: &mut S) { + let value = (4, 5); // constructed literals: 4,5 + + let out = match value { + (4, x) => x, + // uses: 4 (pattern), x (binding → 5) + + (y, 6) => y, + // uses: 6 (pattern), y (binding) + + (_, z) => z, + // uses: wildcard, z (binding → 5) + }; + // possible results: 5 or any y if second arm matched + + send(sink, out); +} + +/// Tuple match with mixed patterns +pub fn handle_alternative(sink: &mut S) { + let value = (4, 5); // constructed literals: 4,5 + + let out = match value { + (4, x) | (x, 3)=> x, + // uses: 4 (pattern), x (binding → 5) or 3 (pattern), x (binding → 4) + (_, z) => z, + // uses: wildcard, z (binding → 5) + }; + // possible results: 4 or 5 + + send(sink, out); +} + +/// Deep nesting with real decomposition +pub fn handle_deep(sink: &mut S) { + let value = Some(Wrap::Nested(Some(Ok(7)))); + // constructed literals: 7 + + let out = match value { + None => 8, + // uses: literal 8 + + Some(Wrap::One(x)) => x, + // uses: x + + Some(Wrap::Pair(a, b)) => a + b, + // uses: a,b (could be any literals) + + Some(Wrap::Nested(inner)) => match inner { + Some(Ok(v)) => v, + // uses: v (7) + + Some(Err(e)) => e, + // uses: e + + None => 9, + // uses: literal 9 + }, + // possible inner results: 7,9 or e + }; + // possible results: 7,8,9 or sums from Pair + + send(sink, out); +} + +/// Sequence with constructed inputs inside function +pub fn process_all(sink: &mut S) { + let items = [ + Wrap::One(10), // literal 10 + Wrap::Pair(11, 12), // literals 11,12 + Wrap::Nested(Some(Ok(13))), // literal 13 + Wrap::Nested(Some(Err(14))), // literal 14 + Wrap::Nested(None), // no literal + ]; + + for item in items { + let out = match item { + Wrap::One(x) => x, + // uses: x (10) + + Wrap::Pair(a, _) => a, + // uses: a (11), wildcard ignores 12 + + Wrap::Nested(Some(Ok(v))) => v, + // uses: v (13) + + Wrap::Nested(Some(Err(e))) => e, + // uses: e (14) + + Wrap::Nested(None) => 15, + // uses: literal 15 + }; + // possible results: 10,11,13,14,15 + + send(sink, out); + } +} + +fn main() { + let mut sink = VecSink::default(); + + handle_wrap(&mut sink); + handle_tuple(&mut sink); + handle_deep(&mut sink); + process_all(&mut sink); + + let _ = sink; +} \ No newline at end of file diff --git a/cpg-language-rust/src/test/resources/use.rs b/cpg-language-rust/src/test/resources/use.rs new file mode 100644 index 00000000000..b63947bfb55 --- /dev/null +++ b/cpg-language-rust/src/test/resources/use.rs @@ -0,0 +1,129 @@ +#![allow(dead_code)] +#![allow(unused_imports)] + +/* + ===== Module definitions ===== +*/ + +mod math { + pub mod basic { + pub fn add() { println!("math::basic::add"); } // LINE 9 + pub fn sub() { println!("math::basic::sub"); } // LINE 10 + } + + pub mod advanced { + pub fn mul() { println!("math::advanced::mul"); } // LINE 14 + pub fn div() { println!("math::advanced::div"); } // LINE 15 + } +} + +mod utils { + pub fn helper() { println!("utils::helper"); } // LINE 21 + + pub mod inner { + pub fn helper() { println!("utils::inner::helper"); } // LINE 24 + } +} + +mod extra { + pub fn foo() { println!("extra::foo"); } // LINE 29 + pub fn bar() { println!("extra::bar"); } // LINE 30 +} + +/* + ===== Top-level uses ===== +*/ + +use crate::math::basic::add as add_fn; +use crate::math::basic::{sub as sub_fn}; +use crate::math::{ + advanced::{mul as mul_fn, div as div_fn}, +}; +use crate::extra::*; +use crate::utils::{self as utils_mod}; +use crate::utils::helper as root_helper; + +/* + ===== Nested module to test `super` ===== +*/ + +mod nested { + pub fn local() { println!("nested::local"); } // LINE 46 + + pub mod child { + use super::local as parent_local; + + pub fn call() { + parent_local(); // resolves to LINE 46 (nested::local) + } + } +} + +/* + ===== Main function ===== +*/ + +fn main() { + println!("--- top-level uses ---"); + + add_fn(); // resolves to LINE 9 (math::basic::add) + sub_fn(); // resolves to LINE 10 (math::basic::sub) + mul_fn(); // resolves to LINE 14 (math::advanced::mul) + div_fn(); // resolves to LINE 15 (math::advanced::div) + + foo(); // resolves to LINE 29 (extra::foo via glob import) + bar(); // resolves to LINE 30 (extra::bar via glob import) + + root_helper(); // resolves to LINE 21 (utils::helper) + + println!("--- function-local use (shadowing + nesting) ---"); + + { + use crate::utils::inner::helper as inner_helper_fn; + + inner_helper_fn(); // resolves to LINE 24 (utils::inner::helper) + + use crate::math::{ + basic::{add as add_local, sub as sub_local}, + advanced::{mul as mul_local}, + }; + + add_local(); // resolves to LINE 9 (math::basic::add) + sub_local(); // resolves to LINE 10 (math::basic::sub) + mul_local(); // resolves to LINE 14 (math::advanced::mul) + } + + println!("--- shadowing test ---"); + + { + use crate::utils::helper as helper; + + helper(); // resolves to LINE 21 (utils::helper) + + { + use crate::utils::inner::helper as helper; + + helper(); // resolves to LINE 24 (utils::inner::helper) [shadowed] + } + + helper(); // resolves to LINE 21 (utils::helper) [shadow restored] + } + + println!("--- self + module alias ---"); + + { + use crate::utils as u; + + u::helper(); // resolves to LINE 21 (utils::helper) + + use crate::utils::inner as inner_mod; + + inner_mod::helper(); // resolves to LINE 24 (utils::inner::helper) + } + + println!("--- super test ---"); + + nested::child::call(); // calls parent_local() → LINE 46 (nested::local) + + println!("--- done ---"); +} \ No newline at end of file diff --git a/cpg-language-rust/src/test/resources/variantWrapped.rs b/cpg-language-rust/src/test/resources/variantWrapped.rs new file mode 100644 index 00000000000..1fc92702cb7 --- /dev/null +++ b/cpg-language-rust/src/test/resources/variantWrapped.rs @@ -0,0 +1,19 @@ +struct Foo { + x: i32, +} + +enum E { + Foo(Foo), // variant name == struct name +} + +fn main() { + let foo = Foo { x: 42 }; + + let e = E::Foo(foo); + + match e { + E::Foo(inner) => { + println!("{}", inner.x); + } + } +} \ No newline at end of file diff --git a/cpg-mcp/build.gradle.kts b/cpg-mcp/build.gradle.kts index 9bb6f360335..389ec0219b0 100644 --- a/cpg-mcp/build.gradle.kts +++ b/cpg-mcp/build.gradle.kts @@ -65,7 +65,7 @@ mavenPublishing { dependencies { implementation(libs.mcp) - implementation(libs.ktor.server.cio) + api(libs.ktor.server.cio) implementation(libs.ktor.serialization.kotlinx.json) implementation(libs.ktor.server.cors) implementation(libs.ktor.server.content.negotiation) diff --git a/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt b/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt index d27873eb60e..2165e4382d9 100644 --- a/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt +++ b/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt @@ -309,6 +309,7 @@ class Application : Callable { .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.python.PythonLanguage") .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.typescript.TypeScriptLanguage") .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.ruby.RubyLanguage") + .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.rust.RustLanguage") .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.jvm.JVMLanguage") .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.ini.IniFileLanguage") .loadIncludes(loadIncludes) diff --git a/gradle.properties.example b/gradle.properties.example index 9250e5fe481..a7c9665375f 100644 --- a/gradle.properties.example +++ b/gradle.properties.example @@ -10,6 +10,7 @@ enableTypeScriptFrontend=true enableRubyFrontend=true enableJVMFrontend=true enableINIFrontend=true +enableRustFrontend=true enableMCPModule=true org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3126f72f634..ce0f974e01e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ slf4j = "2.0.16" clikt = "5.1.0" kaml = "0.104.0" sarif4k = "0.7.0" -ktor = "3.5.0" +ktor = "3.3.3" node = "22.14.0" deno-plugin = "0.1.5" @@ -51,6 +51,7 @@ picocli-codegen = { module = "info.picocli:picocli-codegen", version = "4.7.0"} jep = { module = "org.ninia:jep", version = "4.3.1" } # build.yml uses grep to extract the jep verison number for CI/CD purposes llvm = { module = "org.bytedeco:llvm-platform", version = "16.0.4-1.5.9"} jruby = { module = "org.jruby:jruby-core", version = "9.4.3.0" } +jna = { module = "net.java.dev.jna:jna", version = "5.13.0" } ini4j = { module = "org.ini4j:ini4j", version = "0.5.4" } clikt = { module = "com.github.ajalt.clikt:clikt", version.ref = "clikt" } kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "kaml" } diff --git a/settings.gradle.kts b/settings.gradle.kts index c47988d97ad..2d6ed9563ac 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -34,6 +34,10 @@ val enablePythonFrontend: Boolean by extra { val enablePythonFrontend: String? by settings enablePythonFrontend.toBoolean() } +val enableRustFrontend: Boolean by extra { + val enableRustFrontend: String? by settings + enableRustFrontend.toBoolean() +} val enableLLVMFrontend: Boolean by extra { val enableLLVMFrontend: String? by settings enableLLVMFrontend.toBoolean() @@ -64,6 +68,7 @@ if (enableCXXFrontend) include(":cpg-language-cxx") if (enableGoFrontend) include(":cpg-language-go") if (enableLLVMFrontend) include(":cpg-language-llvm") if (enablePythonFrontend) include(":cpg-language-python") +if (enableRustFrontend) include(":cpg-language-rust") if (enableTypeScriptFrontend) include(":cpg-language-typescript") if (enableRubyFrontend) include(":cpg-language-ruby") if (enableJVMFrontend) include(":cpg-language-jvm")