summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-07-18 19:32:20 +0100
committerMichael Williamson <mike@zwobble.org>2026-07-18 19:33:56 +0100
commit7eed843944a247a99e48bdb6f9dc3aac17d983c5 (patch)
tree4ffc89b2d33785445809440685fa3e59faed1229
parent68b0b81149138dba9fb166c8574fc6d892215a81 (diff)
Support options in rust-transient-0
-rw-r--r--examples/10-transient-0/output/rust/src/gen/data/transient_0.rs40
-rw-r--r--examples/10-transient-0/output/rust/src/lib.rs30
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java74
3 files changed, 139 insertions, 5 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 f8e9be0..1d65042 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
@@ -109,14 +109,46 @@ pub fn decode_struct_with_list(reader: &mut impl std::io::Read) -> ::std::io::Re
}
pub fn encode_struct_with_option(value: &crate::data::StructWithOption, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> {
- todo!();
- todo!();
+ if (&value.a).is_some() {
+ {
+ crate::transient_0::encode_bool(&true, writer)?;
+ };
+ {
+ crate::transient_0::encode_int_64(&((&value.a).as_ref()).unwrap(), writer)?;
+ };
+ } else {
+ crate::transient_0::encode_bool(&false, writer)?;
+ };
+ if (&value.b).is_some() {
+ {
+ crate::transient_0::encode_bool(&true, writer)?;
+ };
+ {
+ crate::data::transient_0::encode_inner_struct(&((&value.b).as_ref()).unwrap(), writer)?;
+ };
+ } else {
+ crate::transient_0::encode_bool(&false, writer)?;
+ };
::std::io::Result::Ok(())
}
pub fn decode_struct_with_option(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithOption> {
- let a = todo!();
- let b = todo!();
+ let a = {
+ let is_some = crate::transient_0::decode_bool(reader)?;
+ if is_some {
+ ::std::option::Option::Some(crate::transient_0::decode_int_64(reader)?)
+ } else {
+ ::std::option::Option::None
+ }
+ };
+ let b = {
+ let is_some = crate::transient_0::decode_bool(reader)?;
+ if is_some {
+ ::std::option::Option::Some(crate::data::transient_0::decode_inner_struct(reader)?)
+ } else {
+ ::std::option::Option::None
+ }
+ };
std::io::Result::Ok(crate::data::StructWithOption { a: a, b: b })
}
diff --git a/examples/10-transient-0/output/rust/src/lib.rs b/examples/10-transient-0/output/rust/src/lib.rs
index a06f73e..3de2597 100644
--- a/examples/10-transient-0/output/rust/src/lib.rs
+++ b/examples/10-transient-0/output/rust/src/lib.rs
@@ -4,7 +4,7 @@ pub mod transient_0;
#[cfg(test)]
mod test {
use std::io::Cursor;
- use super::data::{InnerStruct, OuterStruct, StructWithBool, StructWithInt32, StructWithInt64, StructWithList, StructWithString};
+ use super::data::{InnerStruct, OuterStruct, StructWithBool, StructWithInt32, StructWithInt64, StructWithList, StructWithOption, StructWithString};
#[test]
fn struct_with_bool() {
@@ -79,6 +79,34 @@ mod test {
);
}
+ #[test]
+ fn struct_with_option_none() {
+ let value = StructWithOption {
+ a: None,
+ b: None,
+ };
+
+ assert_round_trip_encoding(
+ value,
+ super::data::transient_0::encode_struct_with_option,
+ super::data::transient_0::decode_struct_with_option,
+ );
+ }
+
+ #[test]
+ fn struct_with_option_some() {
+ let value = StructWithOption {
+ a: Some(10),
+ b: Some(InnerStruct { a: 42, b: 47 }),
+ };
+
+ assert_round_trip_encoding(
+ value,
+ super::data::transient_0::encode_struct_with_option,
+ super::data::transient_0::decode_struct_with_option,
+ );
+ }
+
fn assert_round_trip_encoding<T: std::cmp::PartialEq + std::fmt::Debug>(
value: T,
encode: impl Fn(&T, &mut Cursor<Vec<u8>>) -> std::io::Result<()>,
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 a17ae6b..7122e54 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
@@ -405,6 +405,8 @@ public class RustTransient0Generator implements Generator {
case ConstructedNativeType constructedNativeType -> {
if (constructedNativeType.constructor().equals(NativeTypes.LIST)) {
yield generateEncodeList(value, constructedNativeType.args().getFirst());
+ } else if (constructedNativeType.constructor().equals(NativeTypes.OPTION)) {
+ yield generateEncodeOption(value, constructedNativeType.args().getFirst());
} else {
yield List.of(new RustExpressionStatement(generateTodo()));
}
@@ -441,6 +443,8 @@ public class RustTransient0Generator implements Generator {
case ConstructedNativeType constructedNativeType -> {
if (constructedNativeType.constructor().equals(NativeTypes.LIST)) {
yield generateDecodeList(constructedNativeType.args().getFirst());
+ } else if (constructedNativeType.constructor().equals(NativeTypes.OPTION)) {
+ yield generateDecodeOption(constructedNativeType.args().getFirst());
} else {
yield generateTodo();
}
@@ -560,6 +564,76 @@ public class RustTransient0Generator implements Generator {
);
}
+ private List<RustStatement> generateEncodeOption(RustExpression value, Type elementType) {
+ return List.of(
+ // TODO: pattern matching
+ new RustExpressionStatement(new RustIfExpression(
+ methodCall(value, RustIdentifier.of("is_some"), List.of()),
+ new RustBlockExpression(
+ List.of(
+ new RustExpressionStatement(new RustBlockExpression(
+ generateEncode(
+ new RustPrefixExpression(RustPrefixOperator.BORROW, new RustBoolLiteral(true)),
+ NativeTypes.BOOL
+ ),
+ Optional.empty()
+ )),
+ new RustExpressionStatement(new RustBlockExpression(
+ generateEncode(
+ new RustPrefixExpression(
+ RustPrefixOperator.BORROW,
+ methodCall(
+ methodCall(value, RustIdentifier.of("as_ref"), List.of()),
+ RustIdentifier.of("unwrap"),
+ List.of()
+ )
+ ),
+ elementType
+ ),
+ Optional.empty()
+ ))
+ ),
+ Optional.empty()
+ ),
+ new RustBlockExpression(
+ generateEncode(
+ new RustPrefixExpression(RustPrefixOperator.BORROW, new RustBoolLiteral(false)),
+ NativeTypes.BOOL
+ ),
+ Optional.empty()
+ )
+ ))
+ );
+ }
+
+ private RustExpression generateDecodeOption(Type elementType) {
+ var isSome = RustIdentifier.of("is_some");
+
+ return new RustBlockExpression(
+ List.of(
+ new RustLetStatement(isSome, false, generateDecode(NativeTypes.BOOL))
+ ),
+ Optional.of(new RustIfExpression(
+ RustPath.of(isSome),
+ new RustBlockExpression(
+ List.of(),
+ Optional.of(
+ new RustCallExpression(
+ RustPath.global("std", "option", "Option", "Some"),
+ List.of(generateDecode(elementType))
+ )
+ )
+ ),
+ new RustBlockExpression(
+ List.of(),
+ Optional.of(
+ RustPath.global("std", "option", "Option", "None")
+ )
+ )
+ ))
+ );
+ }
+
private RustExpression generateWriterWrite(RustExpression valueToWrite) {
return new RustTryPropagationExpression(new RustCallExpression(
new RustFieldExpression(