summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-07-17 10:38:43 +0100
committerMichael Williamson <mike@zwobble.org>2026-07-17 10:38:43 +0100
commit59db18c7d8ea0fdce8ff25eef5a13e59e1af4c58 (patch)
tree7cfc386f386103c63fa1ce7f589d204cd01f4c42
parentd14b7d028aec3d491d9f162fc84aa8f4e51ec814 (diff)
Generate separate functions for primitive encode/decode
-rw-r--r--examples/10-transient-0/output/rust/src/gen/data/transient_0.rs94
-rw-r--r--examples/10-transient-0/output/rust/src/gen/transient_0.rs38
-rw-r--r--examples/10-transient-0/output/rust/src/lib.rs1
-rw-r--r--examples/10-transient-0/output/rust/src/transient_0.rs1
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java228
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPath.java4
6 files changed, 257 insertions, 109 deletions
diff --git a/examples/10-transient-0/output/rust/src/gen/data/transient_0.rs b/examples/10-transient-0/output/rust/src/gen/data/transient_0.rs
index e899c4c..2945bdc 100644
--- a/examples/10-transient-0/output/rust/src/gen/data/transient_0.rs
+++ b/examples/10-transient-0/output/rust/src/gen/data/transient_0.rs
@@ -1,103 +1,68 @@
// Generated by hobgoblin.
pub fn encode_struct_with_bool(value: &crate::data::StructWithBool, writer: &mut impl std::io::Write) {
- todo!();
- todo!();
+ crate::transient_0::encode_bool(&value.a, writer);
+ crate::transient_0::encode_bool(&value.b, writer);
}
pub fn decode_struct_with_bool(reader: &mut impl std::io::Read) -> crate::data::StructWithBool {
- let a = todo!();
- let b = todo!();
+ let a = crate::transient_0::decode_bool(reader);
+ let b = crate::transient_0::decode_bool(reader);
crate::data::StructWithBool { a: a, b: b }
}
pub fn encode_struct_with_int_32(value: &crate::data::StructWithInt32, writer: &mut impl std::io::Write) {
- writer.write_all(&value.a.to_le_bytes());
- writer.write_all(&value.b.to_le_bytes());
+ crate::transient_0::encode_int_32(&value.a, writer);
+ crate::transient_0::encode_int_32(&value.b, writer);
}
pub fn decode_struct_with_int_32(reader: &mut impl std::io::Read) -> crate::data::StructWithInt32 {
- let a = {
- let bytes = {
- let mut bytes = [0; 4];
- reader.read_exact(&mut bytes);
- bytes
- };
- i32::from_le_bytes(bytes)
- };
- let b = {
- let bytes = {
- let mut bytes = [0; 4];
- reader.read_exact(&mut bytes);
- bytes
- };
- i32::from_le_bytes(bytes)
- };
+ let a = crate::transient_0::decode_int_32(reader);
+ let b = crate::transient_0::decode_int_32(reader);
crate::data::StructWithInt32 { a: a, b: b }
}
pub fn encode_struct_with_int_64(value: &crate::data::StructWithInt64, writer: &mut impl std::io::Write) {
- todo!();
- todo!();
+ crate::transient_0::encode_int_64(&value.a, writer);
+ crate::transient_0::encode_int_64(&value.b, writer);
}
pub fn decode_struct_with_int_64(reader: &mut impl std::io::Read) -> crate::data::StructWithInt64 {
- let a = todo!();
- let b = todo!();
+ let a = crate::transient_0::decode_int_64(reader);
+ let b = crate::transient_0::decode_int_64(reader);
crate::data::StructWithInt64 { a: a, b: b }
}
pub fn encode_struct_with_string(value: &crate::data::StructWithString, writer: &mut impl std::io::Write) {
- todo!();
- todo!();
+ crate::transient_0::encode_string(&value.a, writer);
+ crate::transient_0::encode_string(&value.b, writer);
}
pub fn decode_struct_with_string(reader: &mut impl std::io::Read) -> crate::data::StructWithString {
- let a = todo!();
- let b = todo!();
+ let a = crate::transient_0::decode_string(reader);
+ let b = crate::transient_0::decode_string(reader);
crate::data::StructWithString { a: a, b: b }
}
pub fn encode_outer_struct(value: &crate::data::OuterStruct, writer: &mut impl std::io::Write) {
todo!();
- writer.write_all(&value.c.to_le_bytes());
+ crate::transient_0::encode_int_32(&value.c, writer);
}
pub fn decode_outer_struct(reader: &mut impl std::io::Read) -> crate::data::OuterStruct {
let inner = todo!();
- let c = {
- let bytes = {
- let mut bytes = [0; 4];
- reader.read_exact(&mut bytes);
- bytes
- };
- i32::from_le_bytes(bytes)
- };
+ let c = crate::transient_0::decode_int_32(reader);
crate::data::OuterStruct { inner: inner, c: c }
}
pub fn encode_inner_struct(value: &crate::data::InnerStruct, writer: &mut impl std::io::Write) {
- writer.write_all(&value.a.to_le_bytes());
- writer.write_all(&value.b.to_le_bytes());
+ crate::transient_0::encode_int_32(&value.a, writer);
+ crate::transient_0::encode_int_32(&value.b, writer);
}
pub fn decode_inner_struct(reader: &mut impl std::io::Read) -> crate::data::InnerStruct {
- let a = {
- let bytes = {
- let mut bytes = [0; 4];
- reader.read_exact(&mut bytes);
- bytes
- };
- i32::from_le_bytes(bytes)
- };
- let b = {
- let bytes = {
- let mut bytes = [0; 4];
- reader.read_exact(&mut bytes);
- bytes
- };
- i32::from_le_bytes(bytes)
- };
+ let a = crate::transient_0::decode_int_32(reader);
+ let b = crate::transient_0::decode_int_32(reader);
crate::data::InnerStruct { a: a, b: b }
}
@@ -124,26 +89,19 @@ pub fn decode_struct_with_option(reader: &mut impl std::io::Read) -> crate::data
}
pub fn encode_variant_one(value: &crate::data::VariantOne, writer: &mut impl std::io::Write) {
- writer.write_all(&value.a.to_le_bytes());
+ crate::transient_0::encode_int_32(&value.a, writer);
}
pub fn decode_variant_one(reader: &mut impl std::io::Read) -> crate::data::VariantOne {
- let a = {
- let bytes = {
- let mut bytes = [0; 4];
- reader.read_exact(&mut bytes);
- bytes
- };
- i32::from_le_bytes(bytes)
- };
+ let a = crate::transient_0::decode_int_32(reader);
crate::data::VariantOne { a: a }
}
pub fn encode_variant_two(value: &crate::data::VariantTwo, writer: &mut impl std::io::Write) {
- todo!();
+ crate::transient_0::encode_int_64(&value.a, writer);
}
pub fn decode_variant_two(reader: &mut impl std::io::Read) -> crate::data::VariantTwo {
- let a = todo!();
+ let a = crate::transient_0::decode_int_64(reader);
crate::data::VariantTwo { a: a }
}
diff --git a/examples/10-transient-0/output/rust/src/gen/transient_0.rs b/examples/10-transient-0/output/rust/src/gen/transient_0.rs
new file mode 100644
index 0000000..18a605c
--- /dev/null
+++ b/examples/10-transient-0/output/rust/src/gen/transient_0.rs
@@ -0,0 +1,38 @@
+// Generated by hobgoblin.
+
+pub fn encode_bool(value: &::core::primitive::bool, writer: &mut impl std::io::Write) {
+ todo!();
+}
+
+pub fn decode_bool(reader: &mut impl std::io::Read) -> ::core::primitive::bool {
+ todo!()
+}
+
+pub fn encode_int_32(value: &::core::primitive::i32, writer: &mut impl std::io::Write) {
+ writer.write_all(&value.to_le_bytes());
+}
+
+pub fn decode_int_32(reader: &mut impl std::io::Read) -> ::core::primitive::i32 {
+ let bytes = {
+ let mut bytes = [0; 4];
+ reader.read_exact(&mut bytes);
+ bytes
+ };
+ i32::from_le_bytes(bytes)
+}
+
+pub fn encode_int_64(value: &::core::primitive::i64, writer: &mut impl std::io::Write) {
+ todo!();
+}
+
+pub fn decode_int_64(reader: &mut impl std::io::Read) -> ::core::primitive::i64 {
+ todo!()
+}
+
+pub fn encode_string(value: &::std::string::String, writer: &mut impl std::io::Write) {
+ todo!();
+}
+
+pub fn decode_string(reader: &mut impl std::io::Read) -> ::std::string::String {
+ todo!()
+}
diff --git a/examples/10-transient-0/output/rust/src/lib.rs b/examples/10-transient-0/output/rust/src/lib.rs
index 865555e..56be8ca 100644
--- a/examples/10-transient-0/output/rust/src/lib.rs
+++ b/examples/10-transient-0/output/rust/src/lib.rs
@@ -1,4 +1,5 @@
pub mod data;
+pub mod transient_0;
#[cfg(test)]
mod test {
diff --git a/examples/10-transient-0/output/rust/src/transient_0.rs b/examples/10-transient-0/output/rust/src/transient_0.rs
new file mode 100644
index 0000000..8b2b800
--- /dev/null
+++ b/examples/10-transient-0/output/rust/src/transient_0.rs
@@ -0,0 +1 @@
+include!("./gen/transient_0.rs");
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
index d67ccd6..46ebb20 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
@@ -8,6 +8,8 @@ import org.zwobble.hobgoblin.compiler.output.generators.rust.RustGenerator;
import org.zwobble.hobgoblin.compiler.output.generators.rust.RustGeneratorConfig;
import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.*;
import org.zwobble.hobgoblin.compiler.typechecker.TypesInfo;
+import org.zwobble.hobgoblin.compiler.types.NamespaceName;
+import org.zwobble.hobgoblin.compiler.types.SimpleNativeType;
import org.zwobble.hobgoblin.compiler.types.Type;
import org.zwobble.json5.reader.Json5ObjectReader;
@@ -52,6 +54,8 @@ public class RustTransient0Generator implements Generator {
@Override
public void generate(List<TypedNamespaceNode> namespaces, TypesInfo typesInfo) throws IOException {
+ generateBuiltins();
+
for (var namespace : namespaces) {
var rustModule = generateNamespace(namespace);
@@ -59,9 +63,138 @@ public class RustTransient0Generator implements Generator {
}
}
+ private void generateBuiltins() throws IOException {
+ var rustModuleName = this.generateTransient0ModuleName(NamespaceName.of());
+ var rustModule = new RustModule(
+ rustModuleName,
+ List.of(
+ generateEncodeBoolFunction(),
+ generateDecodeBoolFunction(),
+ generateEncodeInt32Function(),
+ generateDecodeInt32Function(),
+ generateEncodeInt64Function(),
+ generateDecodeInt64Function(),
+ generateEncodeStringFunction(),
+ generateDecodeStringFunction()
+ )
+ );
+
+ this.rustGenerator.write(rustModule);
+ }
+
+ private RustItem generateEncodeBoolFunction() {
+ return generateEncodeFunction(
+ NativeTypes.BOOL,
+ new RustBlockExpression(
+ List.of(
+ new RustExpressionStatement(generateTodo())
+ ),
+ Optional.empty()
+ )
+ );
+ }
+
+ private RustItem generateDecodeBoolFunction() {
+ return generateDecodeFunction(
+ NativeTypes.BOOL,
+ new RustBlockExpression(
+ List.of(),
+ Optional.of(generateTodo())
+ )
+ );
+ }
+
+ private RustItem generateEncodeInt32Function() {
+ return generateEncodeFunction(
+ NativeTypes.INT_32,
+ new RustBlockExpression(
+ List.of(
+ new RustExpressionStatement(
+ generateWriterWrite(new RustPrefixExpression(
+ RustPrefixOperator.BORROW,
+ new RustCallExpression(
+ new RustFieldExpression(
+ RustPath.of(VALUE_NAME),
+ RustIdentifier.of("to_le_bytes")
+ ),
+ List.of()
+ )
+ ))
+ )
+ ),
+ Optional.empty()
+ )
+ );
+ }
+
+ private RustItem generateDecodeInt32Function() {
+ var bytes = RustIdentifier.of("bytes");
+
+ return generateDecodeFunction(
+ NativeTypes.INT_32,
+ new RustBlockExpression(
+ List.of(
+ new RustLetStatement(
+ bytes,
+ false,
+ generateReaderReadExact(4)
+ )
+ ),
+ Optional.of(new RustCallExpression(
+ RustPath.of("i32", "from_le_bytes"),
+ List.of(RustPath.of(bytes))
+ ))
+ )
+ );
+ }
+
+ private RustItem generateEncodeInt64Function() {
+ return generateEncodeFunction(
+ NativeTypes.INT_64,
+ new RustBlockExpression(
+ List.of(
+ new RustExpressionStatement(generateTodo())
+ ),
+ Optional.empty()
+ )
+ );
+ }
+
+ private RustItem generateDecodeInt64Function() {
+ return generateDecodeFunction(
+ NativeTypes.INT_64,
+ new RustBlockExpression(
+ List.of(),
+ Optional.of(generateTodo())
+ )
+ );
+ }
+
+ private RustItem generateEncodeStringFunction() {
+ return generateEncodeFunction(
+ NativeTypes.STRING,
+ new RustBlockExpression(
+ List.of(
+ new RustExpressionStatement(generateTodo())
+ ),
+ Optional.empty()
+ )
+ );
+ }
+
+ private RustItem generateDecodeStringFunction() {
+ return generateDecodeFunction(
+ NativeTypes.STRING,
+ new RustBlockExpression(
+ List.of(),
+ Optional.of(generateTodo())
+ )
+ );
+ }
+
private RustModule generateNamespace(TypedNamespaceNode namespace) {
- var moduleName = new ArrayList<>(this.rustGenerator.namespaceNameToRustCrateModulePath(namespace.namespaceName()));
- moduleName.add(RustIdentifier.of("transient_0"));
+ var namespaceName = namespace.namespaceName();
+ var moduleName = generateTransient0ModuleName(namespaceName);
return new RustModule(
moduleName,
@@ -71,6 +204,12 @@ public class RustTransient0Generator implements Generator {
);
}
+ private ArrayList<RustIdentifier> generateTransient0ModuleName(NamespaceName namespaceName) {
+ var moduleName = new ArrayList<>(this.rustGenerator.namespaceNameToRustCrateModulePath(namespaceName));
+ moduleName.add(RustIdentifier.of("transient_0"));
+ return moduleName;
+ }
+
private Stream<RustItem> generateNamespaceStatement(
TypedNamespaceStatementNode statement
) {
@@ -84,7 +223,6 @@ public class RustTransient0Generator implements Generator {
}
case TypedStructDefinitionNode structDefinition -> {
- // TODO: remove cast
var rustType = this.rustGenerator.generateRustTypeExpression(structDefinition.type());
yield Stream.of(
@@ -93,9 +231,12 @@ public class RustTransient0Generator implements Generator {
new RustBlockExpression(
structDefinition.fields().stream()
.flatMap(field -> generateEncode(
- new RustFieldExpression(
- RustPath.of(VALUE_NAME),
- this.rustGenerator.generateFieldName(field.name())
+ new RustPrefixExpression(
+ RustPrefixOperator.BORROW,
+ new RustFieldExpression(
+ RustPath.of(VALUE_NAME),
+ this.rustGenerator.generateFieldName(field.name())
+ )
),
field.type().value()
).stream())
@@ -169,45 +310,50 @@ public class RustTransient0Generator implements Generator {
}
private List<RustStatement> generateEncode(RustExpression value, Type type) {
- if (type.equals(NativeTypes.INT_32)) {
- return List.of(
- new RustExpressionStatement(
- generateWriterWrite(new RustPrefixExpression(
- RustPrefixOperator.BORROW,
- new RustCallExpression(
- new RustFieldExpression(
- value,
- RustIdentifier.of("to_le_bytes")
- ),
- List.of()
- )
+ return switch (type) {
+ case SimpleNativeType nativeType -> {
+ var rustEncodeFunctionPathSegments = new ArrayList<>(
+ this.generateTransient0ModuleName(nativeType.namespaceName())
+ );
+ rustEncodeFunctionPathSegments.add(encodeMethodName(nativeType));
+ var rustEncodeFunctionPath = RustPath.crate(
+ rustEncodeFunctionPathSegments
+ );
+
+ yield List.of(
+ new RustExpressionStatement(new RustCallExpression(
+ rustEncodeFunctionPath,
+ List.of(value, RustPath.of(WRITER_NAME))
))
- )
- );
- } else {
- return List.of(new RustExpressionStatement(generateTodo()));
- }
+ );
+ }
+ default -> {
+ yield List.of(new RustExpressionStatement(generateTodo()));
+ }
+ };
}
private RustExpression generateDecode(Type type) {
- if (type.equals(NativeTypes.INT_32)) {
- var bytes = RustIdentifier.of("bytes");
- return new RustBlockExpression(
- List.of(
- new RustLetStatement(
- bytes,
- false,
- generateReaderReadExact(4)
- )
- ),
- Optional.of(new RustCallExpression(
- RustPath.of("i32", "from_le_bytes"),
- List.of(RustPath.of(bytes))
- ))
- );
- } else {
- return generateTodo();
- }
+ return switch (type) {
+ case SimpleNativeType nativeType -> {
+ var rustDecodeFunctionPathSegments = new ArrayList<>(
+ this.generateTransient0ModuleName(nativeType.namespaceName())
+ );
+ rustDecodeFunctionPathSegments.add(decodeMethodName(nativeType));
+ var rustDecodeFunctionPath = RustPath.crate(
+ rustDecodeFunctionPathSegments
+ );
+
+ yield new RustCallExpression(
+ rustDecodeFunctionPath,
+ List.of(RustPath.of(READER_NAME))
+ );
+ }
+
+ default -> {
+ yield generateTodo();
+ }
+ };
}
private RustExpression generateWriterWrite(RustExpression valueToWrite) {
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPath.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPath.java
index 315271b..137df41 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPath.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPath.java
@@ -73,6 +73,10 @@ public record RustPath(java.util.List<org.zwobble.hobgoblin.compiler.output.lang
return qualified(RustPathSegment.global(), names);
}
+ public static RustPath crate(List<RustIdentifier> names) {
+ return qualified(RustPathSegment.crate(), names.toArray(new RustIdentifier[0]));
+ }
+
public static RustPath selfType() {
return qualified(RustPathSegment.selfType(), new String[0]);
}