From b8c1222d00e406eead22d0bffe388ff04d11b7ea Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 12 Sep 2023 11:05:07 -0500 Subject: [PATCH] Update string representation to not `char*` (#665) * Update string representation to not `char*` Use `uint8_t*` to represent that it's not a normal `char*` since it's neither nul-terminated and it may also contain interior nul characters. Closes #662 * update to to uint8_t* to represent string in Go gen Signed-off-by: Jiaxiao Zhou (Mossaka) --------- Signed-off-by: Jiaxiao Zhou (Mossaka) Co-authored-by: Jiaxiao Zhou (Mossaka) --- crates/c/src/lib.rs | 24 ++++++++++++++++++------ crates/go/src/lib.rs | 7 +++++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/crates/c/src/lib.rs b/crates/c/src/lib.rs index ed06c6310..8113dc47c 100644 --- a/crates/c/src/lib.rs +++ b/crates/c/src/lib.rs @@ -284,23 +284,35 @@ impl WorldGenerator for C { StringEncoding::CompactUTF16 => unimplemented!(), }; let ty = self.char_type(); + let c_string_ty = match self.opts.string_encoding { + StringEncoding::UTF8 => "char", + StringEncoding::UTF16 => "char16_t", + StringEncoding::CompactUTF16 => panic!("Compact UTF16 unsupported"), + }; uwrite!( self.src.h_helpers, " - void {snake}_string_set({snake}_string_t *ret, const {ty} *s); - void {snake}_string_dup({snake}_string_t *ret, const {ty} *s); + // Transfers ownership of `s` into the string `ret` + void {snake}_string_set({snake}_string_t *ret, {c_string_ty} *s); + + // Creates a copy of the input nul-terminate string `s` and + // stores it into the component model string `ret`. + void {snake}_string_dup({snake}_string_t *ret, const {c_string_ty} *s); + + // Deallocates the string pointed to by `ret`, deallocating + // the memory behind the string. void {snake}_string_free({snake}_string_t *ret);\ ", ); uwrite!( self.src.c_helpers, " - void {snake}_string_set({snake}_string_t *ret, const {ty} *s) {{ + void {snake}_string_set({snake}_string_t *ret, {c_string_ty} *s) {{ ret->ptr = ({ty}*) s; ret->len = {strlen}; }} - void {snake}_string_dup({snake}_string_t *ret, const {ty} *s) {{ + void {snake}_string_dup({snake}_string_t *ret, const {c_string_ty} *s) {{ ret->len = {strlen}; ret->ptr = cabi_realloc(NULL, 0, {size}, ret->len * {size}); memcpy(ret->ptr, s, ret->len * {size}); @@ -440,8 +452,8 @@ impl C { fn char_type(&self) -> &'static str { match self.opts.string_encoding { - StringEncoding::UTF8 => "char", - StringEncoding::UTF16 => "char16_t", + StringEncoding::UTF8 => "uint8_t", + StringEncoding::UTF16 => "uint16_t", StringEncoding::CompactUTF16 => panic!("Compact UTF16 unsupported"), } } diff --git a/crates/go/src/lib.rs b/crates/go/src/lib.rs index 635353138..c493c8077 100644 --- a/crates/go/src/lib.rs +++ b/crates/go/src/lib.rs @@ -1713,6 +1713,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> { uwriteln!(self.lower_src, "{lower_name} := {param}",); } Type::String => { + self.interface.gen.needs_import_unsafe = true; uwriteln!( self.lower_src, "var {lower_name} {value}", @@ -1721,7 +1722,8 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> { uwriteln!( self.lower_src, " - {lower_name}.ptr = C.CString({param}) + // use unsafe.Pointer to avoid copy + {lower_name}.ptr = (*uint8)(unsafe.Pointer(C.CString({param}))) {lower_name}.len = C.size_t(len({param}))" ); } @@ -1887,10 +1889,11 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> { uwriteln!(self.lift_src, "{lift_name} := {param}"); } Type::String => { + self.interface.gen.needs_import_unsafe = true; uwriteln!( self.lift_src, "var {name} {value} - {lift_name} = C.GoStringN({param}.ptr, C.int({param}.len))", + {lift_name} = C.GoStringN((*C.char)(unsafe.Pointer({param}.ptr)), C.int({param}.len))", name = lift_name, value = self.interface.get_ty(ty), );