Skip to content

Commit

Permalink
fix(c#): strings code generation test
Browse files Browse the repository at this point in the history
Signed-off-by: James Sturtevant <[email protected]>
  • Loading branch information
jsturtevant committed Nov 20, 2023
1 parent b3da31d commit 902e0e1
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 32 deletions.
123 changes: 91 additions & 32 deletions crates/csharp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,42 @@ impl WorldGenerator for CSharp {
gen.import(&resolve.name_world_key(key), func);
}

let mut ret_struct_type = String::new();
if gen.gen.return_area_size > 0 {
uwrite!(
ret_struct_type,
r#"
private unsafe struct ReturnArea
{{
private int GetS32(IntPtr ptr, int offset)
{{
var span = new Span<byte>((void*)ptr, {});
return BitConverter.ToInt32(span.Slice(offset, 4));
}}
public string GetUTF8String(IntPtr ptr)
{{
return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
}}
}}
[ThreadStatic]
[FixedAddressValueType]
private static ReturnArea returnArea;
"#,
gen.gen.return_area_size
);
}

uwrite!(
gen.csharp_interop_src,
r#"
{ret_struct_type}
"#
);

gen.add_interface_fragment(false);
}

Expand Down Expand Up @@ -181,6 +217,59 @@ impl WorldGenerator for CSharp {
gen.export(func, Some(key));
}

// Declare a statically-allocated return area, if needed. We only do
// this for export bindings, because import bindings allocate their
// return-area on the stack.
if gen.gen.return_area_size > 0 {
let mut ret_area_str = String::new();

uwrite!(
ret_area_str,
"
[InlineArray({})]
[StructLayout(LayoutKind.Sequential, Pack = {})]
private struct ReturnArea
{{
private byte buffer;
private int GetS32(int offset)
{{
ReadOnlySpan<byte> span = this;
return BitConverter.ToInt32(span.Slice(offset, 4));
}}
public void SetS32(int offset, int value)
{{
Span<byte> span = this;
BitConverter.TryWriteBytes(span.Slice(offset), value);
}}
internal unsafe int AddrOfBuffer()
{{
fixed(byte* ptr = &buffer)
{{
return (int)ptr;
}}
}}
public unsafe string GetUTF8String(int p0, int p1)
{{
return Encoding.UTF8.GetString((byte*)p0, p1);
}}
}}
[ThreadStatic]
private static ReturnArea returnArea = default;
",
gen.gen.return_area_size,
gen.gen.return_area_align,
);

gen.csharp_interop_src.push_str(&ret_area_str);
}

gen.add_interface_fragment(true);
Ok(())
}
Expand Down Expand Up @@ -675,39 +764,9 @@ impl InterfaceGenerator<'_> {
"#
);

let mut ret_struct_type = String::new();
if self.gen.return_area_size > 0 {
uwrite!(
ret_struct_type,
r#"
private unsafe struct ReturnArea
{{
private int GetS32(IntPtr ptr, int offset)
{{
var span = new Span<byte>((void*)ptr, {});
return BitConverter.ToInt32(span.Slice(offset, 4));
}}
public string GetUTF8String(IntPtr ptr)
{{
return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
}}
}}
[ThreadStatic]
[FixedAddressValueType]
private static ReturnArea returnArea;
"#,
self.gen.return_area_size
);
}

uwrite!(
self.csharp_interop_src,
r#"
{ret_struct_type}
internal static unsafe {result_type} {camel_name}({params})
{{
{src}
Expand Down Expand Up @@ -1458,7 +1517,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
self.src,
"
var {result_var} = {op};
IntPtr {interop_string} = InteropString.FromString({result_var}, out int length);"
IntPtr {interop_string} = InteropString.FromString({result_var}, out int length{result_var});"
);

//TODO: Oppertunity to optimize and not reallocate every call
Expand All @@ -1467,7 +1526,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
} else {
results.push(format!("{interop_string}.ToInt32()"));
}
results.push(format!("length"));
results.push(format!("length{result_var}"));

self.gen.gen.needs_interop_string = true;
}
Expand Down
1 change: 1 addition & 0 deletions crates/csharp/tests/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ macro_rules! codegen_test {
"simple-lists",
"small-anonymous",
"strings",
"smoke-default",
"unused-import",
"use-across-interfaces",
"variants",
Expand Down

0 comments on commit 902e0e1

Please sign in to comment.