Skip to content
Merged
46 changes: 23 additions & 23 deletions crates/csharp/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
resource_drops: Vec::new(),
is_block: false,
fixed_statments: Vec::new(),
parameter_type: parameter_type,
parameter_type,
}
}

Expand Down Expand Up @@ -458,14 +458,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
if flags.flags.len() > 32 {
results.push(format!(
"unchecked((int)(((long){}) & uint.MaxValue))",
operands[0].to_string()
operands[0]
));
results.push(format!(
"unchecked(((int)((long){} >> 32)))",
operands[0].to_string()
operands[0]
));
} else {
results.push(format!("(int){}", operands[0].to_string()));
results.push(format!("(int){}", operands[0]));
}
}

Expand All @@ -479,8 +479,8 @@ impl Bindgen for FunctionBindgen<'_, '_> {
results.push(format!(
"({})(unchecked((uint)({})) | (ulong)(unchecked((uint)({}))) << 32)",
qualified_type_name,
operands[0].to_string(),
operands[1].to_string()
operands[0],
operands[1]
));
} else {
results.push(format!("({})({})", qualified_type_name, operands[0]))
Expand All @@ -502,7 +502,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
let mut result = format!("new {} (\n", qualified_type_name);

result.push_str(&operands.join(", "));
result.push_str(")");
result.push(')');

results.push(result);
}
Expand Down Expand Up @@ -754,7 +754,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
"
);
}
results.push(format!("(nint){ptr}"));
results.push(format!("(int){ptr}"));
results.push(format!("({list}).Length"));
}
Direction::Export => {
Expand Down Expand Up @@ -834,7 +834,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
results.push(format!("(int){str_ptr}"));
}

results.push(format!("{length}"));
results.push(length);
if FunctionKind::Freestanding == *self.kind || self.interface_gen.direction == Direction::Export {
self.interface_gen.require_interop_using("System.Text");
self.interface_gen.require_interop_using("System.Runtime.InteropServices");
Expand Down Expand Up @@ -889,13 +889,13 @@ impl Bindgen for FunctionBindgen<'_, '_> {
"
void* {address};
if (({size} * {list}.Count) < 1024) {{
var {ret_area} = stackalloc {element_type}[({array_size}*{list}.Count)+1];
{address} = (void*)(((int){ret_area}) + ({align} - 1) & -{align});
var {ret_area} = stackalloc {element_type}[{array_size}*{list}.Count];
{address} = (void*)((int){ret_area});
}}
else
{{
var {buffer_size} = {size} * (nuint){list}.Count;
{address} = NativeMemory.AlignedAlloc({buffer_size}, {align});
var {buffer_size} = {size} * {list}.Count;
{address} = NativeMemory.AlignedAlloc((nuint){buffer_size}, {align});
cleanups.Add(() => NativeMemory.AlignedFree({address}));
}}
"
Expand All @@ -905,8 +905,8 @@ impl Bindgen for FunctionBindgen<'_, '_> {
//cabi_realloc_post_return will be called to clean up this allocation
uwrite!(self.src,
"
var {buffer_size} = {size} * (nuint){list}.Count;
void* {address} = NativeMemory.AlignedAlloc({buffer_size}, {align});
var {buffer_size} = {size} * {list}.Count;
void* {address} = NativeMemory.AlignedAlloc((nuint){buffer_size}, {align});
"
);
}
Expand Down Expand Up @@ -1046,7 +1046,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}

Instruction::Return { amt, .. } => {
if self.fixed_statments.len() > 0 {
if !self.fixed_statments.is_empty() {
let fixed: String = self.fixed_statments.iter().map(|f| format!("{} = {}", f.ptr_name, f.item_to_pin)).collect::<Vec<_>>().join(", ");
self.src.insert_str(0, &format!("fixed (void* {fixed})
{{
Expand Down Expand Up @@ -1077,7 +1077,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}
}

if self.fixed_statments.len() > 0 {
if !self.fixed_statments.is_empty() {
uwriteln!(self.src, "}}");
}
}
Expand Down Expand Up @@ -1201,7 +1201,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}
}
}
results.push(format!("{handle}"));
results.push(handle);
}

Instruction::HandleLift {
Expand Down Expand Up @@ -1253,7 +1253,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}

Instruction::Flush { amt } => {
results.extend(operands.iter().take(*amt).map(|v| v.clone()));
results.extend(operands.iter().take(*amt).cloned());
}

Instruction::AsyncPostCallInterface { .. }
Expand Down Expand Up @@ -1296,7 +1296,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
",
align = align.align_wasm32()
);
format!("{ptr}")
ptr
}
Direction::Export => {
// exports need their return area to be live until the post-return call.
Expand All @@ -1319,7 +1319,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
);
self.interface_gen.csharp_gen.needs_export_return_area = true;

format!("{ptr}")
ptr
}
}
}
Expand Down Expand Up @@ -1395,8 +1395,8 @@ fn perform_cast(op: &String, cast: &Bitcast) -> String {
Bitcast::F64ToI64 => format!("BitConverter.DoubleToInt64Bits({op})"),
Bitcast::I32ToI64 => format!("(long) ({op})"),
Bitcast::I64ToI32 => format!("(int) ({op})"),
Bitcast::I64ToP64 => format!("{op}"),
Bitcast::P64ToI64 => format!("{op}"),
Bitcast::I64ToP64 => op.to_string(),
Bitcast::P64ToI64 => op.to_string(),
Bitcast::LToI64 | Bitcast::PToP64 => format!("(long) ({op})"),
Bitcast::I64ToL | Bitcast::P64ToP => format!("(int) ({op})"),
Bitcast::I32ToP
Expand Down
14 changes: 6 additions & 8 deletions crates/csharp/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,12 @@ impl InterfaceGenerator<'_> {
fn gen_import_src(
&mut self,
func: &Function,
results: &Vec<TypeId>,
results: &[TypeId],
parameter_type: ParameterType,
) -> (String, String) {
let mut bindgen = FunctionBindgen::new(
self,
&func.item_name(),
func.item_name(),
&func.kind,
func.params
.iter()
Expand All @@ -317,7 +317,7 @@ impl InterfaceGenerator<'_> {
}
})
.collect(),
results.clone(),
results.to_vec(),
parameter_type,
);

Expand Down Expand Up @@ -399,7 +399,7 @@ impl InterfaceGenerator<'_> {

let mut bindgen = FunctionBindgen::new(
self,
&func.item_name(),
func.item_name(),
&func.kind,
(0..sig.params.len()).map(|i| format!("p{i}")).collect(),
results,
Expand Down Expand Up @@ -565,9 +565,7 @@ impl InterfaceGenerator<'_> {
let ty = &self.resolve.types[*id];
match &ty.kind {
TypeDefKind::Type(ty) => self.is_primative_list(ty),
TypeDefKind::List(ty) if crate::world_generator::is_primitive(ty) => {
return true
}
TypeDefKind::List(ty) if crate::world_generator::is_primitive(ty) => true,
_ => false,
}
}
Expand Down Expand Up @@ -791,7 +789,7 @@ impl InterfaceGenerator<'_> {
Direction::Export => {
let prefix = key
.map(|s| format!("{}#", self.resolve.name_world_key(s)))
.unwrap_or_else(String::new);
.unwrap_or_default();

self.require_interop_using("System.Runtime.InteropServices");
uwrite!(
Expand Down
52 changes: 24 additions & 28 deletions crates/csharp/src/world_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ impl WorldGenerator for CSharp {
let world = &resolve.worlds[id];
let world_namespace = self.qualifier();
let world_namespace = world_namespace.strip_suffix(".").unwrap();
let namespace = format!("{world_namespace}");
let namespace = world_namespace;
let name = world.name.to_upper_camel_case();

let version = env!("CARGO_PKG_VERSION");
Expand Down Expand Up @@ -521,12 +521,12 @@ impl WorldGenerator for CSharp {
}

if self.needs_rep_table {
src.push_str("\n");
src.push('\n');
src.push_str(include_str!("RepTable.cs"));
}

if !&self.world_fragments.is_empty() {
src.push_str("\n");
src.push('\n');

src.push_str("namespace exports {\n");

Expand All @@ -535,28 +535,27 @@ impl WorldGenerator for CSharp {
.world_fragments
.iter()
.flat_map(|f| &f.interop_usings)
.into_iter()
.collect::<HashSet<&String>>() // de-dup across world_fragments
.iter()
.map(|s| "using ".to_owned() + s + ";")
.collect::<Vec<String>>()
.join("\n"),
);
src.push_str("\n");
src.push('\n');

src.push_str(&format!("{access} static class {name}World\n"));
src.push_str("{");
src.push('{');

for fragment in &self.world_fragments {
src.push_str("\n");
src.push('\n');

src.push_str(&fragment.csharp_interop_src);
}
src.push_str("}\n");
src.push_str("}\n");
}

src.push_str("\n");
src.push('\n');

src.push_str("}\n");

Expand Down Expand Up @@ -594,11 +593,11 @@ impl WorldGenerator for CSharp {

let (fragments, fully_qualified_namespace) = match stubs {
Stubs::World(fragments) => {
let fully_qualified_namespace = format!("{namespace}");
let fully_qualified_namespace = namespace.to_string();
(fragments, fully_qualified_namespace)
}
Stubs::Interface(fragments) => {
let fully_qualified_namespace = format!("{stub_namespace}");
let fully_qualified_namespace = stub_namespace.clone();
(fragments, fully_qualified_namespace)
}
};
Expand Down Expand Up @@ -638,7 +637,7 @@ impl WorldGenerator for CSharp {
//TODO: This is currently needed for mono even if it's built as a library.
if self.opts.runtime == CSharpRuntime::Mono {
files.push(
&"MonoEntrypoint.cs".to_string(),
"MonoEntrypoint.cs",
indent(&format!(
r#"
{access} class MonoEntrypoint() {{
Expand Down Expand Up @@ -671,13 +670,9 @@ impl WorldGenerator for CSharp {
// intended to be used non-interactively at link time, the
// linker will have no additional information to resolve such
// ambiguity.
let (resolve, world) =
wit_parser::decoding::decode_world(&wit_component::metadata::encode(
&resolve,
id,
self.opts.string_encoding,
None,
)?)?;
let (resolve, world) = wit_parser::decoding::decode_world(
&wit_component::metadata::encode(resolve, id, self.opts.string_encoding, None)?,
)?;
let pkg = resolve.worlds[world].package.unwrap();

let mut printer = WitPrinter::default();
Expand Down Expand Up @@ -731,7 +726,7 @@ impl WorldGenerator for CSharp {
.collect::<Vec<_>>()
.join("\n");

if body.len() > 0 {
if !body.is_empty() {
let body = format!(
"{header}
{0}
Expand Down Expand Up @@ -802,11 +797,16 @@ enum Stubs<'a> {
// We cant use "StructLayout.Pack" as dotnet will use the minimum of the type and the "Pack" field,
// so for byte it would always use 1 regardless of the "Pack".
pub fn dotnet_aligned_array(array_size: usize, required_alignment: usize) -> (usize, String) {
let num_elements = if array_size % required_alignment > 0 {
array_size / required_alignment + 1
} else {
array_size / required_alignment
};
match required_alignment {
1 => (array_size, "byte".to_owned()),
2 => ((array_size + 1) / 2, "ushort".to_owned()),
4 => ((array_size + 3) / 4, "uint".to_owned()),
8 => ((array_size + 7) / 8, "ulong".to_owned()),
1 => (num_elements, "byte".to_owned()),
2 => (num_elements, "ushort".to_owned()),
4 => (num_elements, "uint".to_owned()),
8 => (num_elements, "ulong".to_owned()),
_ => todo!("unsupported return_area_align {}", required_alignment),
}
}
Expand Down Expand Up @@ -885,11 +885,7 @@ fn interface_name(
);

if let Some(version) = &name.version {
let v = version
.to_string()
.replace('.', "_")
.replace('-', "_")
.replace('+', "_");
let v = version.to_string().replace(['.', '-', '+'], "_");
ns = format!("{}v{}.", ns, &v);
}
ns
Expand Down
28 changes: 28 additions & 0 deletions tests/runtime/lists.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ impl test::lists::test::Host for MyImports {
s.to_string()
}

fn wasi_http_headers_roundtrip(
&mut self,
headers: Vec<(String, Vec<u8>)>,
) -> Vec<(String, Vec<u8>)> {
headers.to_vec()
}

fn list_minmax8(&mut self, u: Vec<u8>, s: Vec<i8>) -> (Vec<u8>, Vec<i8>) {
assert_eq!(u, [u8::MIN, u8::MAX]);
assert_eq!(s, [i8::MIN, i8::MAX]);
Expand Down Expand Up @@ -151,6 +158,27 @@ fn run_test(lists: Lists, store: &mut Store<crate::Wasi<MyImports>>) -> Result<(
exports.call_string_roundtrip(&mut *store, "hello ⚑ world")?,
"hello ⚑ world"
);

let result = exports.call_wasi_http_headers_roundtrip(
&mut *store,
&vec![
("Content-Type".to_owned(), "text/plain".as_bytes().to_vec()),
(
"Content-Length".to_owned(),
"Not found".len().to_string().as_bytes().to_vec(),
),
],
)?;
let (key, value) = result.get(0).unwrap();
assert_eq!(key.as_str(), "Content-Type");
assert_eq!(std::str::from_utf8(value).unwrap(), "text/plain");

let (key, value) = result.get(1).unwrap();
assert_eq!(key.as_str(), "Content-Length");
assert_eq!(
std::str::from_utf8(value).unwrap(),
"Not found".len().to_string().as_str()
);
// Ensure that we properly called `free` everywhere in all the glue that we
// needed to.
assert_eq!(bytes, lists.call_allocated_bytes(&mut *store)?);
Expand Down
Loading