diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/UntypedRecord.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/UntypedRecord.cs index 6e1cdb80c..d613ec8b9 100644 --- a/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/UntypedRecord.cs +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/UntypedRecord.cs @@ -18,6 +18,7 @@ public RenderableReturnType Convert(GirModel.ReturnType returnType) { { Transfer: Transfer.Full } => Model.TypedRecord.GetFullyQuallifiedOwnedHandle(type), { Transfer: Transfer.None } => Model.TypedRecord.GetFullyQuallifiedUnownedHandle(type), + { Transfer: Transfer.Container } => Model.UntypedRecord.GetFullyQuallifiedOwnedHandle(type), _ => throw new Exception($"Unsupported transfer type {returnType.Transfer} for untyped record {type.Name}") }; diff --git a/src/Generation/Generator/Renderer/Public/ReturnType/Converter/UntypedRecord.cs b/src/Generation/Generator/Renderer/Public/ReturnType/Converter/UntypedRecord.cs index 538759d2e..b1c96ebb4 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnType/Converter/UntypedRecord.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnType/Converter/UntypedRecord.cs @@ -6,9 +6,6 @@ internal class UntypedRecord : ReturnTypeConverter { public RenderableReturnType Create(GirModel.ReturnType returnType) { - if (returnType.Transfer == GirModel.Transfer.Container) - throw new NotSupportedException($"Can't return untyped record {returnType} with transfer mode container"); - var typeName = ComplexType.GetFullyQualified((GirModel.Record) returnType.AnyType.AsT0); return new RenderableReturnType(typeName + Nullable.Render(returnType)); diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UntypedRecord.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UntypedRecord.cs index d1c53597d..e9ac6384c 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UntypedRecord.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UntypedRecord.cs @@ -20,6 +20,7 @@ public void Initialize(ReturnTypeToManagedData data, IEnumerable fromVariableName, { Transfer: Transfer.None } => $"{fromVariableName}.Copy()", + { Transfer: Transfer.Container } => fromVariableName, _ => throw new NotImplementedException($"Unsupported transfer type '{returnType.Transfer}' for untyped record {record.Name}") }; diff --git a/src/Native/GirTestLib/girtest-typed-record-tester.c b/src/Native/GirTestLib/girtest-typed-record-tester.c index faeae1164..49ce2deca 100644 --- a/src/Native/GirTestLib/girtest-typed-record-tester.c +++ b/src/Native/GirTestLib/girtest-typed-record-tester.c @@ -2,6 +2,11 @@ G_DEFINE_BOXED_TYPE (GirTestTypedRecordTester, girtest_typed_record_tester, girtest_typed_record_tester_ref, girtest_typed_record_tester_unref) +/* Static elements for girtest_typed_record_tester_get_static_list. + The ref_count starts at 1 so the elements are never freed. */ +static GirTestTypedRecordTester static_list_element_1 = { 1, TYPED_RECORD_TESTER_ENUM_A, TYPED_RECORD_TESTER_ZERO, NULL, 0 }; +static GirTestTypedRecordTester static_list_element_2 = { 1, TYPED_RECORD_TESTER_ENUM_B, TYPED_RECORD_TESTER_ONE, NULL, 0 }; + /** * girtest_typed_record_tester_new: (constructor) * @@ -359,6 +364,40 @@ GirTestTypedRecordTester * girtest_typed_record_tester_run_callback_create_null return *ptr; } +/** + * girtest_typed_record_tester_get_static_list: + * + * Obtains a list of two static elements. The caller owns the + * container but not the elements. This mirrors the behaviour of + * gdk_pixbuf_get_formats(). + * + * Returns: (transfer container) (element-type GirTestTypedRecordTester): A list of static elements. + **/ +GSList * +girtest_typed_record_tester_get_static_list () +{ + GSList *list = NULL; + + list = g_slist_prepend (list, &static_list_element_2); + list = g_slist_prepend (list, &static_list_element_1); + + return list; +} + +/** + * girtest_typed_record_tester_get_static_list_element: + * @list: (element-type GirTestTypedRecordTester): a list obtained via girtest_typed_record_tester_get_static_list() + * @n: the position of the element + * + * Returns: (transfer none) (nullable): the element at position @n, or %NULL + * if the position is off the end of @list + **/ +GirTestTypedRecordTester * +girtest_typed_record_tester_get_static_list_element (GSList *list, guint n) +{ + return g_slist_nth_data (list, n); +} + /** * girtest_typed_record_tester_equals: * @self: An instance diff --git a/src/Native/GirTestLib/girtest-typed-record-tester.h b/src/Native/GirTestLib/girtest-typed-record-tester.h index acd768f06..99bf84e83 100644 --- a/src/Native/GirTestLib/girtest-typed-record-tester.h +++ b/src/Native/GirTestLib/girtest-typed-record-tester.h @@ -130,5 +130,7 @@ void girtest_typed_record_tester_run_callback_parameter_full_ownership_transfer_ void girtest_typed_record_tester_run_callback_parameter_no_ownership_transfer(GirTestGetTypedRecordTesterNoOwnershipTransfer callback, GirTestTypedRecordTester *data); void girtest_typed_record_tester_run_callback_parameter_no_ownership_transfer_nullable(GirTestGetTypedRecordTesterNoOwnershipTransferNullable callback, GirTestTypedRecordTester *data); GirTestTypedRecordTester * girtest_typed_record_tester_run_callback_create_nullable_full_ownership_transfer_out(GirTestCreateNullableTypedRecordTesterFullOwnershipTransferInCallback callback); +GSList * girtest_typed_record_tester_get_static_list(); +GirTestTypedRecordTester * girtest_typed_record_tester_get_static_list_element(GSList *list, guint n); gboolean girtest_typed_record_tester_equals(GirTestTypedRecordTester *self, GirTestTypedRecordTester *other); G_END_DECLS diff --git a/src/Tests/Libs/GirTest-0.1.Tests/TypedRecordTest.cs b/src/Tests/Libs/GirTest-0.1.Tests/TypedRecordTest.cs index 8c910c551..87eb56e99 100644 --- a/src/Tests/Libs/GirTest-0.1.Tests/TypedRecordTest.cs +++ b/src/Tests/Libs/GirTest-0.1.Tests/TypedRecordTest.cs @@ -81,6 +81,25 @@ public void SupportsReturnValueNullableTransferFull() recordTester3.Should().BeNull(); } + [TestMethod] + public void SupportsReturnValueTransferContainer() + { + // The ownership of the list is transferred, but the ownership + // of the static elements inside the list is not. + var list = TypedRecordTester.GetStaticList(); + + var element1 = TypedRecordTester.GetStaticListElement(list, 0); + element1!.CustomEnum.Should().Be(TypedRecordTesterEnum.A); + element1.CustomBitfield.Should().Be(TypedRecordTesterBitfield.Zero); + + var element2 = TypedRecordTester.GetStaticListElement(list, 1); + element2!.CustomEnum.Should().Be(TypedRecordTesterEnum.B); + element2.CustomBitfield.Should().Be(TypedRecordTesterBitfield.One); + + var element3 = TypedRecordTester.GetStaticListElement(list, 2); + element3.Should().BeNull(); + } + [TestMethod] public void SupportsInstanceParameterTransferNone() {