diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-07-26 00:55:32 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-07-26 00:55:32 +0100 |
| commit | f47074c2955d97c581255886b6597bbc95a4ff10 (patch) | |
| tree | b110a54e4f2f464965708d52fd8a5a749ceaadbf | |
| parent | 6925ba376ee030738d5634574b3f3e353fd19d47 (diff) | |
Implement shared values for rust-transient-0
5 files changed, 462 insertions, 139 deletions
diff --git a/examples/11-transient-0/output/rust/src/gen/data/transient_0.rs b/examples/11-transient-0/output/rust/src/gen/data/transient_0.rs index cffb318..6ee8baf 100644 --- a/examples/11-transient-0/output/rust/src/gen/data/transient_0.rs +++ b/examples/11-transient-0/output/rust/src/gen/data/transient_0.rs @@ -1,136 +1,136 @@ // Generated by hobgoblin. -pub fn encode_struct_with_bool(value: &crate::data::StructWithBool, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::transient_0::encode_bool(&value.a, writer)?; - crate::transient_0::encode_bool(&value.b, writer)?; +pub fn encode_struct_with_bool(value: &crate::data::StructWithBool, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::transient_0::encode_bool(&value.a, writer, shared_values)?; + crate::transient_0::encode_bool(&value.b, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_bool(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithBool> { - let a = crate::transient_0::decode_bool(reader)?; - let b = crate::transient_0::decode_bool(reader)?; +pub fn decode_struct_with_bool(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithBool> { + let a = crate::transient_0::decode_bool(reader, shared_values)?; + let b = crate::transient_0::decode_bool(reader, shared_values)?; std::io::Result::Ok(crate::data::StructWithBool { a: a, b: b }) } -pub fn encode_struct_with_int_32(value: &crate::data::StructWithInt32, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::transient_0::encode_int_32(&value.a, writer)?; - crate::transient_0::encode_int_32(&value.b, writer)?; +pub fn encode_struct_with_int_32(value: &crate::data::StructWithInt32, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::transient_0::encode_int_32(&value.a, writer, shared_values)?; + crate::transient_0::encode_int_32(&value.b, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_int_32(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithInt32> { - let a = crate::transient_0::decode_int_32(reader)?; - let b = crate::transient_0::decode_int_32(reader)?; +pub fn decode_struct_with_int_32(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithInt32> { + let a = crate::transient_0::decode_int_32(reader, shared_values)?; + let b = crate::transient_0::decode_int_32(reader, shared_values)?; std::io::Result::Ok(crate::data::StructWithInt32 { a: a, b: b }) } -pub fn encode_struct_with_int_64(value: &crate::data::StructWithInt64, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::transient_0::encode_int_64(&value.a, writer)?; - crate::transient_0::encode_int_64(&value.b, writer)?; +pub fn encode_struct_with_int_64(value: &crate::data::StructWithInt64, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::transient_0::encode_int_64(&value.a, writer, shared_values)?; + crate::transient_0::encode_int_64(&value.b, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_int_64(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithInt64> { - let a = crate::transient_0::decode_int_64(reader)?; - let b = crate::transient_0::decode_int_64(reader)?; +pub fn decode_struct_with_int_64(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithInt64> { + let a = crate::transient_0::decode_int_64(reader, shared_values)?; + let b = crate::transient_0::decode_int_64(reader, shared_values)?; std::io::Result::Ok(crate::data::StructWithInt64 { a: a, b: b }) } -pub fn encode_struct_with_string(value: &crate::data::StructWithString, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::transient_0::encode_string(&value.a, writer)?; - crate::transient_0::encode_string(&value.b, writer)?; +pub fn encode_struct_with_string(value: &crate::data::StructWithString, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::transient_0::encode_string(&value.a, writer, shared_values)?; + crate::transient_0::encode_string(&value.b, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_string(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithString> { - let a = crate::transient_0::decode_string(reader)?; - let b = crate::transient_0::decode_string(reader)?; +pub fn decode_struct_with_string(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithString> { + let a = crate::transient_0::decode_string(reader, shared_values)?; + let b = crate::transient_0::decode_string(reader, shared_values)?; std::io::Result::Ok(crate::data::StructWithString { a: a, b: b }) } -pub fn encode_struct_with_struct(value: &crate::data::StructWithStruct, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::data::transient_0::encode_struct_with_int_32(&value.inner, writer)?; - crate::transient_0::encode_int_32(&value.c, writer)?; +pub fn encode_struct_with_struct(value: &crate::data::StructWithStruct, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::data::transient_0::encode_struct_with_int_32(&value.inner, writer, shared_values)?; + crate::transient_0::encode_int_32(&value.c, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_struct(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithStruct> { - let inner = crate::data::transient_0::decode_struct_with_int_32(reader)?; - let c = crate::transient_0::decode_int_32(reader)?; +pub fn decode_struct_with_struct(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithStruct> { + let inner = crate::data::transient_0::decode_struct_with_int_32(reader, shared_values)?; + let c = crate::transient_0::decode_int_32(reader, shared_values)?; std::io::Result::Ok(crate::data::StructWithStruct { inner: inner, c: c }) } -pub fn encode_struct_with_list(value: &crate::data::StructWithList, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { +pub fn encode_struct_with_list(value: &crate::data::StructWithList, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { { - crate::transient_0::encode_int_64(&(((&value.a).len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?, writer)?; + crate::transient_0::encode_int_64(&(((&value.a).len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?, writer, shared_values)?; for element in &value.a { - crate::transient_0::encode_int_64(element, writer)?; + crate::transient_0::encode_int_64(element, writer, shared_values)?; }; }; { - crate::transient_0::encode_int_64(&(((&value.b).len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?, writer)?; + crate::transient_0::encode_int_64(&(((&value.b).len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?, writer, shared_values)?; for element in &value.b { - crate::data::transient_0::encode_struct_with_int_32(element, writer)?; + crate::data::transient_0::encode_struct_with_int_32(element, writer, shared_values)?; }; }; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_list(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithList> { +pub fn decode_struct_with_list(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithList> { let a = { - let len = crate::transient_0::decode_int_64(reader)?; + let len = crate::transient_0::decode_int_64(reader, shared_values)?; let mut elements = ::std::vec::Vec::with_capacity((len.try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?); for _ in 0..len { - elements.push(crate::transient_0::decode_int_64(reader)?); + elements.push(crate::transient_0::decode_int_64(reader, shared_values)?); }; elements }; let b = { - let len = crate::transient_0::decode_int_64(reader)?; + let len = crate::transient_0::decode_int_64(reader, shared_values)?; let mut elements = ::std::vec::Vec::with_capacity((len.try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?); for _ in 0..len { - elements.push(crate::data::transient_0::decode_struct_with_int_32(reader)?); + elements.push(crate::data::transient_0::decode_struct_with_int_32(reader, shared_values)?); }; elements }; std::io::Result::Ok(crate::data::StructWithList { a: a, b: b }) } -pub fn encode_struct_with_option(value: &crate::data::StructWithOption, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { +pub fn encode_struct_with_option(value: &crate::data::StructWithOption, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { match &value.a { ::std::option::Option::Some(value) => { - crate::transient_0::encode_bool(&true, writer)?; - crate::transient_0::encode_int_64(&value, writer)?; + crate::transient_0::encode_bool(&true, writer, shared_values)?; + crate::transient_0::encode_int_64(&value, writer, shared_values)?; }, ::std::option::Option::None => { - crate::transient_0::encode_bool(&false, writer)?; + crate::transient_0::encode_bool(&false, writer, shared_values)?; }, }; match &value.b { ::std::option::Option::Some(value) => { - crate::transient_0::encode_bool(&true, writer)?; - crate::data::transient_0::encode_struct_with_int_32(&value, writer)?; + crate::transient_0::encode_bool(&true, writer, shared_values)?; + crate::data::transient_0::encode_struct_with_int_32(&value, writer, shared_values)?; }, ::std::option::Option::None => { - crate::transient_0::encode_bool(&false, writer)?; + crate::transient_0::encode_bool(&false, writer, shared_values)?; }, }; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_option(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithOption> { +pub fn decode_struct_with_option(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithOption> { let a = { - let is_some = crate::transient_0::decode_bool(reader)?; + let is_some = crate::transient_0::decode_bool(reader, shared_values)?; if is_some { - ::std::option::Option::Some(crate::transient_0::decode_int_64(reader)?) + ::std::option::Option::Some(crate::transient_0::decode_int_64(reader, shared_values)?) } else { ::std::option::Option::None } }; let b = { - let is_some = crate::transient_0::decode_bool(reader)?; + let is_some = crate::transient_0::decode_bool(reader, shared_values)?; if is_some { - ::std::option::Option::Some(crate::data::transient_0::decode_struct_with_int_32(reader)?) + ::std::option::Option::Some(crate::data::transient_0::decode_struct_with_int_32(reader, shared_values)?) } else { ::std::option::Option::None } @@ -138,17 +138,17 @@ pub fn decode_struct_with_option(reader: &mut impl std::io::Read) -> ::std::io:: std::io::Result::Ok(crate::data::StructWithOption { a: a, b: b }) } -pub fn encode_enum_with_variants(value: &crate::data::EnumWithVariants, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { +pub fn encode_enum_with_variants(value: &crate::data::EnumWithVariants, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { crate::transient_0::encode_int_32(&match value { crate::data::EnumWithVariants::Zero => 0, crate::data::EnumWithVariants::One => 1, crate::data::EnumWithVariants::Two => 2, - }, writer)?; + }, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_enum_with_variants(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::EnumWithVariants> { - std::io::Result::Ok(match &crate::transient_0::decode_int_32(reader)? { +pub fn decode_enum_with_variants(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::EnumWithVariants> { + std::io::Result::Ok(match &crate::transient_0::decode_int_32(reader, shared_values)? { 0 => crate::data::EnumWithVariants::Zero, 1 => crate::data::EnumWithVariants::One, 2 => crate::data::EnumWithVariants::Two, @@ -156,116 +156,248 @@ pub fn decode_enum_with_variants(reader: &mut impl std::io::Read) -> ::std::io:: }) } -pub fn encode_struct_with_enum(value: &crate::data::StructWithEnum, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::data::transient_0::encode_enum_with_variants(&value.inner, writer)?; - crate::transient_0::encode_int_32(&value.c, writer)?; +pub fn encode_struct_with_enum(value: &crate::data::StructWithEnum, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::data::transient_0::encode_enum_with_variants(&value.inner, writer, shared_values)?; + crate::transient_0::encode_int_32(&value.c, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_enum(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithEnum> { - let inner = crate::data::transient_0::decode_enum_with_variants(reader)?; - let c = crate::transient_0::decode_int_32(reader)?; +pub fn decode_struct_with_enum(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithEnum> { + let inner = crate::data::transient_0::decode_enum_with_variants(reader, shared_values)?; + let c = crate::transient_0::decode_int_32(reader, shared_values)?; std::io::Result::Ok(crate::data::StructWithEnum { inner: inner, c: c }) } -pub fn encode_sum_with_variants(value: &crate::data::SumWithVariants, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { +pub fn encode_sum_with_variants(value: &crate::data::SumWithVariants, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { match value { crate::data::SumWithVariants::VariantOne(value) => { - crate::transient_0::encode_int_32(&0, writer)?; - crate::data::transient_0::encode_variant_one(value, writer)?; + crate::transient_0::encode_int_32(&0, writer, shared_values)?; + crate::data::transient_0::encode_variant_one(value, writer, shared_values)?; }, crate::data::SumWithVariants::VariantTwo(value) => { - crate::transient_0::encode_int_32(&1, writer)?; - crate::data::transient_0::encode_variant_two(value, writer)?; + crate::transient_0::encode_int_32(&1, writer, shared_values)?; + crate::data::transient_0::encode_variant_two(value, writer, shared_values)?; }, }; ::std::io::Result::Ok(()) } -pub fn decode_sum_with_variants(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::SumWithVariants> { - std::io::Result::Ok(match &crate::transient_0::decode_int_32(reader)? { - 0 => crate::data::SumWithVariants::VariantOne(crate::data::transient_0::decode_variant_one(reader)?), - 1 => crate::data::SumWithVariants::VariantTwo(crate::data::transient_0::decode_variant_two(reader)?), +pub fn decode_sum_with_variants(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::SumWithVariants> { + std::io::Result::Ok(match &crate::transient_0::decode_int_32(reader, shared_values)? { + 0 => crate::data::SumWithVariants::VariantOne(crate::data::transient_0::decode_variant_one(reader, shared_values)?), + 1 => crate::data::SumWithVariants::VariantTwo(crate::data::transient_0::decode_variant_two(reader, shared_values)?), _ => todo!(), }) } -pub fn encode_variant_one(value: &crate::data::VariantOne, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::transient_0::encode_int_32(&value.a, writer)?; +pub fn encode_variant_one(value: &crate::data::VariantOne, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::transient_0::encode_int_32(&value.a, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_variant_one(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::VariantOne> { - let a = crate::transient_0::decode_int_32(reader)?; +pub fn decode_variant_one(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::VariantOne> { + let a = crate::transient_0::decode_int_32(reader, shared_values)?; std::io::Result::Ok(crate::data::VariantOne { a: a }) } -pub fn encode_variant_two(value: &crate::data::VariantTwo, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::transient_0::encode_int_64(&value.a, writer)?; +pub fn encode_variant_two(value: &crate::data::VariantTwo, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::transient_0::encode_int_64(&value.a, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_variant_two(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::VariantTwo> { - let a = crate::transient_0::decode_int_64(reader)?; +pub fn decode_variant_two(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::VariantTwo> { + let a = crate::transient_0::decode_int_64(reader, shared_values)?; std::io::Result::Ok(crate::data::VariantTwo { a: a }) } -pub fn encode_struct_with_sum(value: &crate::data::StructWithSum, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::data::transient_0::encode_sum_with_variants(&value.inner, writer)?; - crate::transient_0::encode_int_32(&value.b, writer)?; +pub fn encode_struct_with_sum(value: &crate::data::StructWithSum, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::data::transient_0::encode_sum_with_variants(&value.inner, writer, shared_values)?; + crate::transient_0::encode_int_32(&value.b, writer, shared_values)?; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_sum(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithSum> { - let inner = crate::data::transient_0::decode_sum_with_variants(reader)?; - let b = crate::transient_0::decode_int_32(reader)?; +pub fn decode_struct_with_sum(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithSum> { + let inner = crate::data::transient_0::decode_sum_with_variants(reader, shared_values)?; + let b = crate::transient_0::decode_int_32(reader, shared_values)?; std::io::Result::Ok(crate::data::StructWithSum { inner: inner, b: b }) } -pub fn encode_struct_with_list_of_shared(value: &crate::data::StructWithListOfShared, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { +pub fn encode_struct_with_list_of_shared(value: &crate::data::StructWithListOfShared, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { { - crate::transient_0::encode_int_64(&(((&value.inner).len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?, writer)?; + crate::transient_0::encode_int_64(&(((&value.inner).len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?, writer, shared_values)?; for element in &value.inner { - crate::data::transient_0::encode_struct_with_int_32(element.as_ref(), writer)?; + { + let ptr = ::std::sync::Arc::as_ptr(&element) as ::core::primitive::usize; + match (shared_values.get(&ptr)).copied() { + ::std::option::Option::Some(id) => { + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + }, + ::std::option::Option::None => { + let id = ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?; + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + shared_values.insert(ptr, id); + crate::data::transient_0::encode_struct_with_int_32(element.as_ref(), writer, shared_values)?; + }, + }; + }; }; }; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_list_of_shared(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithListOfShared> { +pub fn decode_struct_with_list_of_shared(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithListOfShared> { let inner = { - let len = crate::transient_0::decode_int_64(reader)?; + let len = crate::transient_0::decode_int_64(reader, shared_values)?; let mut elements = ::std::vec::Vec::with_capacity((len.try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?); for _ in 0..len { - elements.push(::std::sync::Arc::new(crate::data::transient_0::decode_struct_with_int_32(reader)?)); + elements.push({ + let id = crate::transient_0::decode_int_64(reader, shared_values)?; + if id < ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))? { + ((::std::sync::Arc::clone(&shared_values[id as ::core::primitive::usize])).downcast()).unwrap() + } else { + let decoded_value = ::std::sync::Arc::new(crate::data::transient_0::decode_struct_with_int_32(reader, shared_values)?); + shared_values.push(::std::sync::Arc::clone(&decoded_value) as ::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>); + decoded_value + } + }); }; elements }; std::io::Result::Ok(crate::data::StructWithListOfShared { inner: inner }) } -pub fn encode_struct_with_different_shared_types(value: &crate::data::StructWithDifferentSharedTypes, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::data::transient_0::encode_struct_with_int_32((&value.a).as_ref(), writer)?; - crate::data::transient_0::encode_struct_with_int_64((&value.b).as_ref(), writer)?; - crate::data::transient_0::encode_struct_with_int_32((&value.c).as_ref(), writer)?; +pub fn encode_struct_with_different_shared_types(value: &crate::data::StructWithDifferentSharedTypes, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + { + let ptr = ::std::sync::Arc::as_ptr(&&value.a) as ::core::primitive::usize; + match (shared_values.get(&ptr)).copied() { + ::std::option::Option::Some(id) => { + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + }, + ::std::option::Option::None => { + let id = ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?; + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + shared_values.insert(ptr, id); + crate::data::transient_0::encode_struct_with_int_32((&value.a).as_ref(), writer, shared_values)?; + }, + }; + }; + { + let ptr = ::std::sync::Arc::as_ptr(&&value.b) as ::core::primitive::usize; + match (shared_values.get(&ptr)).copied() { + ::std::option::Option::Some(id) => { + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + }, + ::std::option::Option::None => { + let id = ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?; + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + shared_values.insert(ptr, id); + crate::data::transient_0::encode_struct_with_int_64((&value.b).as_ref(), writer, shared_values)?; + }, + }; + }; + { + let ptr = ::std::sync::Arc::as_ptr(&&value.c) as ::core::primitive::usize; + match (shared_values.get(&ptr)).copied() { + ::std::option::Option::Some(id) => { + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + }, + ::std::option::Option::None => { + let id = ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?; + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + shared_values.insert(ptr, id); + crate::data::transient_0::encode_struct_with_int_32((&value.c).as_ref(), writer, shared_values)?; + }, + }; + }; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_different_shared_types(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithDifferentSharedTypes> { - let a = ::std::sync::Arc::new(crate::data::transient_0::decode_struct_with_int_32(reader)?); - let b = ::std::sync::Arc::new(crate::data::transient_0::decode_struct_with_int_64(reader)?); - let c = ::std::sync::Arc::new(crate::data::transient_0::decode_struct_with_int_32(reader)?); +pub fn decode_struct_with_different_shared_types(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithDifferentSharedTypes> { + let a = { + let id = crate::transient_0::decode_int_64(reader, shared_values)?; + if id < ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))? { + ((::std::sync::Arc::clone(&shared_values[id as ::core::primitive::usize])).downcast()).unwrap() + } else { + let decoded_value = ::std::sync::Arc::new(crate::data::transient_0::decode_struct_with_int_32(reader, shared_values)?); + shared_values.push(::std::sync::Arc::clone(&decoded_value) as ::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>); + decoded_value + } + }; + let b = { + let id = crate::transient_0::decode_int_64(reader, shared_values)?; + if id < ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))? { + ((::std::sync::Arc::clone(&shared_values[id as ::core::primitive::usize])).downcast()).unwrap() + } else { + let decoded_value = ::std::sync::Arc::new(crate::data::transient_0::decode_struct_with_int_64(reader, shared_values)?); + shared_values.push(::std::sync::Arc::clone(&decoded_value) as ::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>); + decoded_value + } + }; + let c = { + let id = crate::transient_0::decode_int_64(reader, shared_values)?; + if id < ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))? { + ((::std::sync::Arc::clone(&shared_values[id as ::core::primitive::usize])).downcast()).unwrap() + } else { + let decoded_value = ::std::sync::Arc::new(crate::data::transient_0::decode_struct_with_int_32(reader, shared_values)?); + shared_values.push(::std::sync::Arc::clone(&decoded_value) as ::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>); + decoded_value + } + }; std::io::Result::Ok(crate::data::StructWithDifferentSharedTypes { a: a, b: b, c: c }) } -pub fn encode_struct_with_shared_sum_and_variant(value: &crate::data::StructWithSharedSumAndVariant, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::data::transient_0::encode_sum_with_variants((&value.a).as_ref(), writer)?; - crate::data::transient_0::encode_variant_one((&value.b).as_ref(), writer)?; +pub fn encode_struct_with_shared_sum_and_variant(value: &crate::data::StructWithSharedSumAndVariant, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + { + let ptr = ::std::sync::Arc::as_ptr(&&value.a) as ::core::primitive::usize; + match (shared_values.get(&ptr)).copied() { + ::std::option::Option::Some(id) => { + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + }, + ::std::option::Option::None => { + let id = ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?; + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + shared_values.insert(ptr, id); + crate::data::transient_0::encode_sum_with_variants((&value.a).as_ref(), writer, shared_values)?; + }, + }; + }; + { + let ptr = ::std::sync::Arc::as_ptr(&&value.b) as ::core::primitive::usize; + match (shared_values.get(&ptr)).copied() { + ::std::option::Option::Some(id) => { + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + }, + ::std::option::Option::None => { + let id = ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?; + crate::transient_0::encode_int_64(&id, writer, shared_values)?; + shared_values.insert(ptr, id); + crate::data::transient_0::encode_variant_one((&value.b).as_ref(), writer, shared_values)?; + }, + }; + }; ::std::io::Result::Ok(()) } -pub fn decode_struct_with_shared_sum_and_variant(reader: &mut impl std::io::Read) -> ::std::io::Result::<crate::data::StructWithSharedSumAndVariant> { - let a = ::std::sync::Arc::new(crate::data::transient_0::decode_sum_with_variants(reader)?); - let b = ::std::sync::Arc::new(crate::data::transient_0::decode_variant_one(reader)?); +pub fn decode_struct_with_shared_sum_and_variant(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<crate::data::StructWithSharedSumAndVariant> { + let a = { + let id = crate::transient_0::decode_int_64(reader, shared_values)?; + if id < ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))? { + ((::std::sync::Arc::clone(&shared_values[id as ::core::primitive::usize])).downcast()).unwrap() + } else { + let decoded_value = ::std::sync::Arc::new(crate::data::transient_0::decode_sum_with_variants(reader, shared_values)?); + shared_values.push(::std::sync::Arc::clone(&decoded_value) as ::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>); + decoded_value + } + }; + let b = { + let id = crate::transient_0::decode_int_64(reader, shared_values)?; + if id < ((shared_values.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))? { + ((::std::sync::Arc::clone(&shared_values[id as ::core::primitive::usize])).downcast()).unwrap() + } else { + let decoded_value = ::std::sync::Arc::new(crate::data::transient_0::decode_variant_one(reader, shared_values)?); + shared_values.push(::std::sync::Arc::clone(&decoded_value) as ::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>); + decoded_value + } + }; std::io::Result::Ok(crate::data::StructWithSharedSumAndVariant { a: a, b: b }) } diff --git a/examples/11-transient-0/output/rust/src/gen/transient_0.rs b/examples/11-transient-0/output/rust/src/gen/transient_0.rs index 560fe51..393b397 100644 --- a/examples/11-transient-0/output/rust/src/gen/transient_0.rs +++ b/examples/11-transient-0/output/rust/src/gen/transient_0.rs @@ -1,6 +1,6 @@ // Generated by hobgoblin. -pub fn encode_bool(value: &::core::primitive::bool, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { +pub fn encode_bool(value: &::core::primitive::bool, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { if *value { writer.write_all(&1u8.to_le_bytes())?; } else { @@ -9,7 +9,7 @@ pub fn encode_bool(value: &::core::primitive::bool, writer: &mut impl std::io::W ::std::io::Result::Ok(()) } -pub fn decode_bool(reader: &mut impl std::io::Read) -> ::std::io::Result::<::core::primitive::bool> { +pub fn decode_bool(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<::core::primitive::bool> { let int_value = { let bytes = { let mut bytes = [0; 1]; @@ -25,12 +25,12 @@ pub fn decode_bool(reader: &mut impl std::io::Read) -> ::std::io::Result::<::cor }) } -pub fn encode_int_32(value: &::core::primitive::i32, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { +pub fn encode_int_32(value: &::core::primitive::i32, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { writer.write_all(&value.to_le_bytes())?; ::std::io::Result::Ok(()) } -pub fn decode_int_32(reader: &mut impl std::io::Read) -> ::std::io::Result::<::core::primitive::i32> { +pub fn decode_int_32(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<::core::primitive::i32> { let bytes = { let mut bytes = [0; 4]; reader.read_exact(&mut bytes)?; @@ -39,12 +39,12 @@ pub fn decode_int_32(reader: &mut impl std::io::Read) -> ::std::io::Result::<::c std::io::Result::Ok(::core::primitive::i32::from_le_bytes(bytes)) } -pub fn encode_int_64(value: &::core::primitive::i64, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { +pub fn encode_int_64(value: &::core::primitive::i64, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { writer.write_all(&value.to_le_bytes())?; ::std::io::Result::Ok(()) } -pub fn decode_int_64(reader: &mut impl std::io::Read) -> ::std::io::Result::<::core::primitive::i64> { +pub fn decode_int_64(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<::core::primitive::i64> { let bytes = { let mut bytes = [0; 8]; reader.read_exact(&mut bytes)?; @@ -53,14 +53,14 @@ pub fn decode_int_64(reader: &mut impl std::io::Read) -> ::std::io::Result::<::c std::io::Result::Ok(::core::primitive::i64::from_le_bytes(bytes)) } -pub fn encode_string(value: &::std::string::String, writer: &mut impl std::io::Write) -> ::std::io::Result::<()> { - crate::transient_0::encode_int_64(&((value.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?, writer)?; +pub fn encode_string(value: &::std::string::String, writer: &mut impl std::io::Write, shared_values: &mut ::std::collections::HashMap::<::core::primitive::usize, ::core::primitive::i64>) -> ::std::io::Result::<()> { + crate::transient_0::encode_int_64(&((value.len()).try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?, writer, shared_values)?; writer.write_all(value.as_bytes())?; ::std::io::Result::Ok(()) } -pub fn decode_string(reader: &mut impl std::io::Read) -> ::std::io::Result::<::std::string::String> { - let len = crate::transient_0::decode_int_64(reader)?; +pub fn decode_string(reader: &mut impl std::io::Read, shared_values: &mut ::std::vec::Vec::<::std::sync::Arc::<dyn ::std::any::Any + ::std::marker::Sync + ::std::marker::Send>>) -> ::std::io::Result::<::std::string::String> { + let len = crate::transient_0::decode_int_64(reader, shared_values)?; let bytes = { let mut bytes = vec![0u8; (len.try_into()).map_err(|error| ::std::io::Error::new(::std::io::ErrorKind::InvalidData, error))?]; reader.read_exact(&mut bytes)?; diff --git a/examples/11-transient-0/output/rust/src/lib.rs b/examples/11-transient-0/output/rust/src/lib.rs index 63e7c67..63a2799 100644 --- a/examples/11-transient-0/output/rust/src/lib.rs +++ b/examples/11-transient-0/output/rust/src/lib.rs @@ -3,8 +3,10 @@ pub mod transient_0; #[cfg(test)] mod test { + use std::any::Any; use std::io::Cursor; use std::sync::Arc; + use std::collections::HashMap; use super::data::{EnumWithVariants, StructWithBool, StructWithDifferentSharedTypes, StructWithEnum, StructWithInt32, StructWithInt64, StructWithList, StructWithListOfShared, StructWithOption, StructWithSharedSumAndVariant, StructWithString, StructWithStruct, StructWithSum, SumWithVariants, VariantOne, VariantTwo }; #[test] @@ -171,17 +173,21 @@ mod test { #[test] fn struct_with_list_of_shared() { + let a = Arc::new(StructWithInt32 { a: 10, b: 25 }); + let b = Arc::new(StructWithInt32 { a: 42, b: 47 }); + let value = StructWithListOfShared { - inner: vec![ - Arc::new(StructWithInt32 { a: 10, b: 25 }), - ], + inner: vec![Arc::clone(&a), Arc::clone(&a), Arc::clone(&b), a, b], }; - assert_round_trip_encoding( + let decoded_value = assert_round_trip_encoding( value, super::data::transient_0::encode_struct_with_list_of_shared, super::data::transient_0::decode_struct_with_list_of_shared, ); + assert!(Arc::ptr_eq(&decoded_value.inner[0], &decoded_value.inner[1])); + assert!(Arc::ptr_eq(&decoded_value.inner[0], &decoded_value.inner[3])); + assert!(Arc::ptr_eq(&decoded_value.inner[2], &decoded_value.inner[4])); } #[test] @@ -215,15 +221,17 @@ mod test { 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<()>, - decode: impl Fn(&mut Cursor<Vec<u8>>) -> std::io::Result<T>, - ) { + encode: impl Fn(&T, &mut Cursor<Vec<u8>>, &mut HashMap<usize, i64>) -> std::io::Result<()>, + decode: impl Fn(&mut Cursor<Vec<u8>>, &mut Vec<Arc<dyn Any + Sync + Send>>) -> std::io::Result<T>, + ) -> T { let mut bytes = Cursor::new(Vec::new()); - encode(&value, &mut bytes).unwrap(); + encode(&value, &mut bytes, &mut HashMap::new()).unwrap(); bytes.set_position(0); - let decoded_value = decode(&mut bytes).unwrap(); + let decoded_value = decode(&mut bytes, &mut Vec::new()).unwrap(); assert_eq!(value, decoded_value); + + decoded_value } } 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 af28e96..e37a974 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 @@ -29,6 +29,7 @@ public class RustTransient0Generator implements Generator { private static final RustIdentifier VALUE_NAME = RustIdentifier.of("value"); private static final RustIdentifier READER_NAME = RustIdentifier.of("reader"); private static final RustIdentifier WRITER_NAME = RustIdentifier.of("writer"); + private static final RustIdentifier SHARED_VALUES_NAME = RustIdentifier.of("shared_values"); public static OutputConfig parseGeneratorConfig( Path projectRoot, @@ -508,7 +509,13 @@ public class RustTransient0Generator implements Generator { encodeMethodName(type), List.of( new RustFunctionParam(VALUE_NAME, new RustSharedReferenceType(rustType)), - new RustFunctionParam(WRITER_NAME, new RustMutableReferenceType(new RustImplTraitType(RustPath.of("std", "io", "Write")))) + new RustFunctionParam(WRITER_NAME, new RustMutableReferenceType(new RustImplTraitType(RustPath.of("std", "io", "Write")))), + new RustFunctionParam( + SHARED_VALUES_NAME, + new RustMutableReferenceType( + RustTypes.hashMap(RustTypes.USIZE, RustPath.primitive("i64")) + ) + ) ), Optional.of( RustPath.global("std", "io", "Result") @@ -536,7 +543,10 @@ public class RustTransient0Generator implements Generator { Optional.of(RustVisibility.PUB), decodeMethodName(type), List.of( - new RustFunctionParam(READER_NAME, new RustMutableReferenceType(new RustImplTraitType(RustPath.of("std", "io", "Read")))) + new RustFunctionParam(READER_NAME, new RustMutableReferenceType(new RustImplTraitType(RustPath.of("std", "io", "Read")))), + new RustFunctionParam(SHARED_VALUES_NAME, new RustMutableReferenceType( + RustTypes.vec(RustTypes.arc(RustTypes.dyn(RustTypes.ANY, RustTypes.SYNC, RustTypes.SEND))) + )) ), Optional.of(RustPath.global("std", "io", "Result").withArgs(List.of(rustType))), Optional.of(new RustBlockExpression( @@ -637,7 +647,7 @@ public class RustTransient0Generator implements Generator { return new RustExpressionStatement(new RustTryPropagationExpression(new RustCallExpression( rustEncodeFunctionPath, - List.of(value, RustPath.of(WRITER_NAME)) + List.of(value, RustPath.of(WRITER_NAME), RustPath.of(SHARED_VALUES_NAME)) ))); } @@ -652,7 +662,7 @@ public class RustTransient0Generator implements Generator { return new RustTryPropagationExpression(new RustCallExpression( rustDecodeFunctionPath, - List.of(RustPath.of(READER_NAME)) + List.of(RustPath.of(READER_NAME), RustPath.of(SHARED_VALUES_NAME)) )); } @@ -784,20 +794,161 @@ public class RustTransient0Generator implements Generator { } private RustStatement generateEncodeShared(RustExpression value, Type type) { - return generateEncode( - new RustCallExpression( - new RustFieldExpression(value, RustIdentifier.of("as_ref")), - List.of() + var ptr = RustIdentifier.of("ptr"); + var id = RustIdentifier.of("id"); + + return new RustExpressionStatement(new RustBlockExpression( + List.of( + new RustLetStatement( + ptr, + false, + new RustTypeCastExpression( + new RustCallExpression( + RustTypes.ARC.addSegment(RustPathSegment.of("as_ptr")), + List.of(new RustPrefixExpression(RustPrefixOperator.BORROW, value)) + ), + RustTypes.USIZE + ) + ), + new RustExpressionStatement(new RustMatchExpression( + methodCall( + methodCall( + RustPath.of(SHARED_VALUES_NAME), + RustIdentifier.of("get"), + List.of(new RustPrefixExpression(RustPrefixOperator.BORROW, RustPath.of(ptr))) + ), + RustIdentifier.of("copied"), + List.of() + ), + List.of( + new RustMatchArm( + new RustTupleStructPattern(RustTypes.SOME, List.of(new RustIdentifierPattern(id))), + new RustBlockExpression( + List.of( + generateEncode( + new RustPrefixExpression(RustPrefixOperator.BORROW, RustPath.of(id)), + NativeTypes.INT_64 + ) + ), + Optional.empty() + ) + ), + new RustMatchArm( + new RustPathPattern(RustTypes.NONE), + new RustBlockExpression( + List.of( + new RustLetStatement( + id, + false, + tryIntoOrInvalidData( + methodCall(RustPath.of(SHARED_VALUES_NAME), RustIdentifier.of("len"), List.of()) + ) + ), + generateEncode( + new RustPrefixExpression(RustPrefixOperator.BORROW, RustPath.of(id)), + NativeTypes.INT_64 + ), + new RustExpressionStatement( + methodCall( + RustPath.of(SHARED_VALUES_NAME), + RustIdentifier.of("insert"), + List.of(RustPath.of(ptr), RustPath.of(id)) + ) + ), + generateEncode( + new RustCallExpression( + new RustFieldExpression(value, RustIdentifier.of("as_ref")), + List.of() + ), + type + ) + ), + Optional.empty() + ) + ) + ) + )) ), - type - ); + Optional.empty() + )); } private RustExpression generateDecodeShared(Type type) { - var value = generateDecode(type); - return new RustCallExpression( - RustPath.global("std", "sync", "Arc", "new"), - List.of(value) + var id = RustIdentifier.of("id"); + var decodedValue = RustIdentifier.of("decoded_value"); + + return new RustBlockExpression( + List.of( + new RustLetStatement( + id, + false, + generateDecode(NativeTypes.INT_64) + ) + ), + Optional.of(new RustIfExpression( + new RustBinaryExpression( + RustBinaryOperator.LESS_THAN, + RustPath.of(id), + tryIntoOrInvalidData(methodCall( + RustPath.of(SHARED_VALUES_NAME), + RustIdentifier.of("len"), + List.of() + )) + ), + new RustBlockExpression( + List.of(), + Optional.of( + methodCall( + methodCall( + new RustCallExpression( + RustTypes.ARC.addSegment(RustPathSegment.of("clone")), + List.of( + new RustPrefixExpression(RustPrefixOperator.BORROW, new RustIndexExpression( + RustPath.of(SHARED_VALUES_NAME), + // TODO: use try_into() + new RustTypeCastExpression(RustPath.of(id), RustTypes.USIZE) + )) + ) + ), + RustIdentifier.of("downcast"), + List.of() + ), + // TODO: remove unwrap + RustIdentifier.of("unwrap"), + List.of() + ) + ) + ), + new RustBlockExpression( + List.of( + new RustLetStatement( + decodedValue, + false, + new RustCallExpression( + RustTypes.ARC.addSegment(RustPathSegment.of("new")), + List.of(generateDecode(type)) + ) + ), + new RustExpressionStatement(methodCall( + RustPath.of(SHARED_VALUES_NAME), + RustIdentifier.of("push"), + List.of( + new RustTypeCastExpression( + new RustCallExpression( + RustTypes.ARC.addSegment(RustPathSegment.of("clone")), + List.of(new RustPrefixExpression( + RustPrefixOperator.BORROW, + RustPath.of(decodedValue) + )) + ), + RustTypes.arc(RustTypes.dyn(RustTypes.ANY, RustTypes.SYNC, RustTypes.SEND)) + ) + ) + )) + ), + Optional.of(RustPath.of(decodedValue)) + ) + )) ); } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustTypes.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustTypes.java index c3d1cf0..1e43a24 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustTypes.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustTypes.java @@ -1,20 +1,52 @@ package org.zwobble.hobgoblin.compiler.output.lang.rust; import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPath; +import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTraitObjectType; import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType; +import java.util.Arrays; import java.util.List; public class RustTypes { private RustTypes() {} + public static RustType dyn(RustPath... bounds) { + return new RustTraitObjectType(Arrays.asList(bounds)); + } + public static RustPath BOOL = RustPath.primitive("bool"); public static RustPath I32 = RustPath.primitive("i32"); public static RustPath I64 = RustPath.primitive("i64"); - public static RustPath STRING = RustPath.global("std", "string", "String"); + public static RustPath USIZE = RustPath.primitive("usize"); + + public static RustPath ANY = RustPath.global("std", "any", "Any"); public static RustPath box(RustType elementType) { return RustPath.global("std", "boxed", "Box") .withArgs(List.of(elementType)); } + + public static RustPath hashMap(RustType keyType, RustType valueType) { + return RustPath.global("std", "collections", "HashMap") + .withArgs(List.of(keyType, valueType)); + } + + public static RustPath SEND = RustPath.global("std", "marker", "Send"); + public static RustPath SYNC = RustPath.global("std", "marker", "Sync"); + + public static RustPath NONE = RustPath.global("std", "option", "Option", "None"); + public static RustPath SOME = RustPath.global("std", "option", "Option", "Some"); + + public static RustPath STRING = RustPath.global("std", "string", "String"); + + public static RustPath ARC = RustPath.global("std", "sync", "Arc"); + + public static RustPath arc(RustType innerType) { + return ARC.withArgs(List.of(innerType)); + } + + public static RustPath vec(RustType elementType) { + return RustPath.global("std", "vec", "Vec") + .withArgs(List.of(elementType)); + } } |
