Complete Rust API and migration documentation (#102)
Some checks failed
Native code generation / deterministic (push) Failing after 2m5s
Concurrency and resource soak audit / soak (push) Failing after 6m22s
Documentation / documentation (push) Failing after 1m25s
Imaging and meshing gate / native (push) Failing after 2m47s
JPEG 2000 feature / linux (push) Successful in 3m54s
Release platform and feature matrix / audit (push) Successful in 37s
Native Rust workspace compile / compile (push) Failing after 1m14s
Skia feature / linux (push) Successful in 30m46s
Dependency and supply-chain audit / audit (push) Failing after 8m56s
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Failing after 9m16s
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Failing after 1m20s
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Failing after 1m18s
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled

This commit is contained in:
2026-08-12 00:24:06 +00:00
parent 3db144da63
commit 5eb3f01122
37 changed files with 133519 additions and 48 deletions

View File

@@ -3205,6 +3205,11 @@ VALUE_DERIVES = {
"T:LibreMetaverse.WorldSettings": "Clone, Debug, Eq, PartialEq",
}
PINNED_CSHARP_SOURCE = (
"https://github.com/cinderblocks/libremetaverse/tree/"
"2aa70bb68513b39795da5d13c88f31b86e85a3ba"
)
# Native implementations occasionally need Rust-only bounds that have no
# direct C# metadata equivalent. C#'s `where T : class` permits returning a
# reference to the stored object; the Rust inventory store returns an owned
@@ -3385,10 +3390,29 @@ def duplicate_enum_values(item: dict) -> bool:
return len(values) != len(set(values))
def render_enum(item: dict, rust_name: str) -> list[str]:
def render_type_docs(item: dict, type_row: dict) -> list[str]:
return [
f"/// C# type: `{item['doc_id']}`.",
"///",
f"/// Native Rust mapping of C# `{item['signature']}` using decision",
f"/// `{type_row['mapping_decision']}`. See the [pinned C# source]({PINNED_CSHARP_SOURCE}).",
]
def render_member_docs(row: dict[str, str], indent: str = "") -> list[str]:
return [
f"{indent}/// C# member: `{row['csharp_id']}`.",
f"{indent}///",
f"{indent}/// C# signature: `{row['csharp_signature']}`.",
f"{indent}/// Mapping contract: ownership `{row['ownership']}`; async `{row['asyncness']}`;",
f"{indent}/// errors `{row['error_model']}`; overload `{row['overload_decision']}`; kind `{row['mapping_kind']}`.",
]
def render_enum(item: dict, type_row: dict, rust_name: str, member_rows: dict[str, dict[str, str]]) -> list[str]:
underlying = UNDERLYING[item["enum_underlying_type"]]
values = [member for member in item["members"] if member["kind"] == "enum_value"]
lines = [f"/// C# type: `{item['doc_id']}`."]
lines = render_type_docs(item, type_row)
if item["doc_id"] in OPEN_ENUM_IDS:
lines += [
"#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]",
@@ -3398,10 +3422,10 @@ def render_enum(item: dict, rust_name: str) -> list[str]:
f"impl {rust_name} {{",
]
for member in values:
lines += [
f" /// C# member: `{member['doc_id']}`.",
f" pub const {mapping.pascal(member['name'])}: Self = Self({member['value']['value']});",
]
lines += render_member_docs(member_rows[member["doc_id"]], " ")
lines.append(
f" pub const {mapping.pascal(member['name'])}: Self = Self({member['value']['value']});"
)
lines.append("}")
return lines
if flags_enum(item) or duplicate_enum_values(item):
@@ -3414,7 +3438,8 @@ def render_enum(item: dict, rust_name: str) -> list[str]:
for member in values:
name = mapping.snake(member["name"]).upper()
value = member["value"]["value"]
lines += [f" /// C# member: `{member['doc_id']}`.", f" pub const {name}: Self = Self({value});"]
lines += render_member_docs(member_rows[member["doc_id"]], " ")
lines.append(f" pub const {name}: Self = Self({value});")
lines.append("}")
return lines
lines += [
@@ -3423,7 +3448,8 @@ def render_enum(item: dict, rust_name: str) -> list[str]:
f"pub enum {rust_name} {{",
]
for member in values:
lines += [f" /// C# member: `{member['doc_id']}`.", f" {mapping.pascal(member['name'])} = {member['value']['value']},"]
lines += render_member_docs(member_rows[member["doc_id"]], " ")
lines.append(f" {mapping.pascal(member['name'])} = {member['value']['value']},")
lines.append("}")
return lines
@@ -3593,16 +3619,17 @@ def rust_constant_value(item: dict) -> str:
def render_type(item: dict, type_row: dict, member_rows: dict[str, dict[str, str]], mapper: mapping.Mapper) -> str:
rust_name = type_name(type_row)
if native_path := NATIVE_TYPES.get(item["doc_id"]):
lines = [f"/// C# type: `{item['doc_id']}`."]
lines.extend(f"/// C# member: `{member['doc_id']}`." for member in item["members"])
lines = render_type_docs(item, type_row)
for member in item["members"]:
lines.extend(render_member_docs(member_rows[member["doc_id"]]))
lines.append(f"pub use {native_path} as {rust_name};")
return "\n".join(lines)
if item["kind"] == "enum":
return "\n".join(render_enum(item, rust_name))
return "\n".join(render_enum(item, type_row, rust_name, member_rows))
names = generic_names(item)
suffix = generic_suffix(names)
trait = item["kind"] == "interface"
lines = [f"/// C# type: `{item['doc_id']}`."]
lines = render_type_docs(item, type_row)
if trait:
supertrait = TRAIT_SUPERTRAITS.get(item["doc_id"])
inheritance = f": {supertrait}" if supertrait else ""
@@ -3614,10 +3641,8 @@ def render_type(item: dict, type_row: dict, member_rows: dict[str, dict[str, str
native_declaration = NATIVE_DECLARATIONS.get(item["doc_id"])
if native_declaration:
lines.append(f"pub use {native_declaration} as {rust_name};")
lines.extend(
f"/// C# member: `{field['doc_id']}`."
for field in fields
)
for field in fields:
lines.extend(render_member_docs(member_rows[field["doc_id"]]))
elif derives := VALUE_DERIVES.get(item["doc_id"]):
lines.append(f"#[derive({derives})]")
if native_declaration:
@@ -3648,7 +3673,8 @@ def render_type(item: dict, type_row: dict, member_rows: dict[str, dict[str, str
raise ValueError(f"invalid mapped field signature: {field_signature}")
field_name = field_name_match.group(1)
field_type = field_name_match.group(2)
lines += [f" /// C# member: `{field['doc_id']}`.", f" pub {field_name}: {field_type},"]
lines += render_member_docs(member_rows[field["doc_id"]], " ")
lines.append(f" pub {field_name}: {field_type},")
for field_name, field_type in private_fields:
lines.append(f" {field_name}: {field_type},")
if names:
@@ -3661,7 +3687,7 @@ def render_type(item: dict, type_row: dict, member_rows: dict[str, dict[str, str
if member["kind"] in {"enum_value"} or (member["kind"] == "field" and not member.get("static")):
continue
row = member_rows[member["doc_id"]]
lines.append(f" /// C# member: `{member['doc_id']}`.")
lines.extend(render_member_docs(row, " "))
if member["kind"] == "constant":
lines.append(f" {row['rust_signature']} = {rust_constant_value(member)};")
continue