summaryrefslogtreecommitdiff
path: root/lib9p/core_gen
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/core_gen')
-rw-r--r--lib9p/core_gen/c9util.py2
-rw-r--r--lib9p/core_gen/c_marshal.py3
-rw-r--r--lib9p/core_gen/c_unmarshal.py9
-rw-r--r--lib9p/core_gen/h.py13
4 files changed, 25 insertions, 2 deletions
diff --git a/lib9p/core_gen/c9util.py b/lib9p/core_gen/c9util.py
index 84fdee4..a304ff4 100644
--- a/lib9p/core_gen/c9util.py
+++ b/lib9p/core_gen/c9util.py
@@ -91,6 +91,8 @@ def typename(typ: idl.Type, parent: idl.StructMember | None = None) -> str:
match typ:
case idl.Primitive():
if typ.value == 1 and parent and parent.cnt: # SPECIAL (string)
+ if parent.membname == "data": # SPECIAL (iovec)
+ return f"struct {ident('_iovec')}"
return "[[gnu::nonstring]] char"
return f"uint{typ.value*8}_t"
case idl.Number():
diff --git a/lib9p/core_gen/c_marshal.py b/lib9p/core_gen/c_marshal.py
index 86d82e4..af8d582 100644
--- a/lib9p/core_gen/c_marshal.py
+++ b/lib9p/core_gen/c_marshal.py
@@ -334,6 +334,9 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str:
if child.typ.static_size == 1: # SPECIAL (zerocopy)
if path.root.typname == "stat": # SPECIAL (stat)
ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES(ctx, {path.c_str('val->')[:-3]}, {cnt_str});\n"
+ elif c9util.typename(child.typ, child) == f"struct {c9util.ident("_iovec")}": # SPECIAL (iovec)
+ ret += f"{'\t'*indent_lvl()}for (int iov_i = 0; iov_i < {path.c_str('val->')[:-3]}->iovcnt; iov_i++)\n"
+ ret += f"{'\t'*(indent_lvl()+1)}MARSHAL_BYTES_ZEROCOPY(ctx, {path.c_str('val->')[:-3]}->iov[iov_i].iov_base, {path.c_str('val->')[:-3]}->iov[iov_i].iov_len);\n"
else:
ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES_ZEROCOPY(ctx, {path.c_str('val->')[:-3]}, {cnt_str});\n"
return idlutil.WalkCmd.KEEP_GOING, pop
diff --git a/lib9p/core_gen/c_unmarshal.py b/lib9p/core_gen/c_unmarshal.py
index 206a85b..c510e44 100644
--- a/lib9p/core_gen/c_unmarshal.py
+++ b/lib9p/core_gen/c_unmarshal.py
@@ -100,7 +100,14 @@ def gen_c_unmarshal(versions: set[str], typs: list[idl.UserType]) -> str:
cnt_str = path.parent().add(child.cnt).c_str("out->")
cnt_typ = c9util.typename(child.cnt.typ)
if child.typ.static_size == 1: # SPECIAL (zerocopy)
- ret += f"{'\t'*indent_lvl()}UNMARSHAL_BYTES(ctx, {path.c_str('out->')[:-3]}, {cnt_str});\n"
+ if c9util.typename(child.typ, child) == f"struct {c9util.ident('_iovec')}": # SPECIAL (iovec)
+ ret += f"{'\t'*indent_lvl()}out->{child.membname}.iov = ctx->extra;\n"
+ ret += f"{'\t'*indent_lvl()}ctx->extra += sizeof(out->{child.membname}.iov[0]);\n"
+ ret += f"{'\t'*indent_lvl()}out->{child.membname}.iov->iov_base = &ctx->net_bytes[ctx->net_offset];\n"
+ ret += f"{'\t'*indent_lvl()}out->{child.membname}.iov->iov_len = out->{child.cnt.membname};\n"
+ ret += f"{'\t'*indent_lvl()}out->{child.membname}.iovcnt = 1;\n"
+ else:
+ ret += f"{'\t'*indent_lvl()}UNMARSHAL_BYTES(ctx, {path.c_str('out->')[:-3]}, {cnt_str});\n"
return idlutil.WalkCmd.KEEP_GOING, pop
ret += f"{'\t'*indent_lvl()}{path.c_str('out->')[:-3]} = extra;\n"
ret += f"{'\t'*indent_lvl()}extra += sizeof({path.c_str('out->')[:-3]}[0]) * {cnt_str};\n"
diff --git a/lib9p/core_gen/h.py b/lib9p/core_gen/h.py
index 8c381f8..6ead5ba 100644
--- a/lib9p/core_gen/h.py
+++ b/lib9p/core_gen/h.py
@@ -162,6 +162,11 @@ def gen_h(versions: set[str], typs: list[idl.UserType]) -> str:
#ifndef _LIB9P_CORE_H_
\t#error Do not include <lib9p/_core_generated.h> directly; include <lib9p/core.h> instead
#endif
+
+struct {c9util.ident('_iovec_list')} {{
+\tstruct iovec *iov;
+\tint iovcnt;
+}};
"""
id2typ: dict[int, idl.Message] = {}
for msg in [msg for msg in typs if isinstance(msg, idl.Message)]:
@@ -523,7 +528,13 @@ def gen_struct(typ: idl.Struct) -> str: # and idl.Message
if member.val:
continue
ret += cutil.ifdef_push(2, c9util.ver_ifdef(member.in_versions))
- ret += f"\t{c9util.typename(member.typ, member):<{typewidth}} {'*' if member.cnt else ' '}{member.membname};\n"
+ ptr = bool(member.cnt)
+ if (
+ c9util.typename(member.typ, member)
+ == f"struct {c9util.ident('_iovec')}"
+ ): # SPECIAL (zerocopy)
+ ptr = False
+ ret += f"\t{c9util.typename(member.typ, member):<{typewidth}} {'*' if ptr else ' '}{member.membname};\n"
ret += cutil.ifdef_pop(1)
ret += "};\n"
return ret