summaryrefslogtreecommitdiff
path: root/lib9p/idl.gen
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-01-28 01:35:57 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-02-12 20:55:19 -0700
commit9fc8825764cb9d860a26ac3eab59a4ff164cca71 (patch)
treedae41706581285fbdfc8ea783b33c8ae093295d9 /lib9p/idl.gen
parenta24a60232204702fe245c312edb0c2c8041b17a8 (diff)
lib9p: Don't copy byte-arrays when unmarshaling
Diffstat (limited to 'lib9p/idl.gen')
-rwxr-xr-xlib9p/idl.gen19
1 files changed, 12 insertions, 7 deletions
diff --git a/lib9p/idl.gen b/lib9p/idl.gen
index 9a8260a..f2b4f13 100755
--- a/lib9p/idl.gen
+++ b/lib9p/idl.gen
@@ -831,7 +831,10 @@ LM_ALWAYS_INLINE static bool validate_8(struct _validate_ctx *ctx) { return _val
if member.in_versions != typ.in_versions:
ret += "( " + c_ver_cond(member.in_versions) + " && "
if member.cnt is not None:
- ret += f"_validate_list(ctx, {member.cnt.name}, validate_{member.typ.name}, sizeof({c_typename(member.typ)}))"
+ if member.typ.static_size == 1: # SPECIAL (zerocopy)
+ ret += f"_validate_size_net(ctx, {member.cnt.name})"
+ else:
+ ret += f"_validate_list(ctx, {member.cnt.name}, validate_{member.typ.name}, sizeof({c_typename(member.typ)}))"
if typ.name == "s": # SPECIAL (string)
ret += f'\n\t || ({{ (!is_valid_utf8_without_nul(&ctx->net_bytes[ctx->net_offset-len], len)) && lib9p_error(ctx->ctx, LINUX_EBADMSG, "message contains invalid UTF-8"); }})'
else:
@@ -935,13 +938,15 @@ LM_ALWAYS_INLINE static void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *o
if member.in_versions != typ.in_versions:
ret += "{\n"
ret += prefix
- ret += f"out->{member.name} = ctx->extra;\n"
- ret += f"{prefix}ctx->extra += sizeof(out->{member.name}[0]) * out->{member.cnt.name};\n"
- ret += f"{prefix}for (typeof(out->{member.cnt.name}) i = 0; i < out->{member.cnt.name}; i++)\n"
- if member.typ.static_size == 1: # SPECIAL (string)
- # Special-case is that we cast from `char` to `uint8_t`.
- ret += f"{prefix}\tunmarshal_{member.typ.name}(ctx, (uint8_t *)&out->{member.name}[i]);\n"
+ if member.typ.static_size == 1: # SPECIAL (string, zerocopy)
+ ret += f"out->{member.name} = (char *)&ctx->net_bytes[ctx->net_offset];\n"
+ ret += (
+ f"{prefix}ctx->net_offset += out->{member.cnt.name};\n"
+ )
else:
+ ret += f"out->{member.name} = ctx->extra;\n"
+ ret += f"{prefix}ctx->extra += sizeof(out->{member.name}[0]) * out->{member.cnt.name};\n"
+ ret += f"{prefix}for (typeof(out->{member.cnt.name}) i = 0; i < out->{member.cnt.name}; i++)\n"
ret += f"{prefix}\tunmarshal_{member.typ.name}(ctx, &out->{member.name}[i]);\n"
if member.in_versions != typ.in_versions:
ret += "\t}\n"