Generate world and social API shims
This commit is contained in:
@@ -9,10 +9,10 @@ projects, public C# type names have Rust declarations, every upstream NUnit case
|
|||||||
has a traceable placeholder, and every sample/tool project has a Rust binary
|
has a traceable placeholder, and every sample/tool project has a Rust binary
|
||||||
target. Types, StructuredData, Imaging, PrimMesher, both rendering adapters, and
|
target. Types, StructuredData, Imaging, PrimMesher, both rendering adapters, and
|
||||||
the main assembly's packet/message/asset/primitive wire-data, core
|
the main assembly's packet/message/asset/primitive wire-data, core
|
||||||
runtime/networking, and avatar-facing manager slices now have complete callable,
|
runtime/networking, avatar-facing manager, and world/social/service manager
|
||||||
failure-only signatures; the remaining world manager and extension slices plus
|
slices now have complete callable, failure-only signatures; the remaining
|
||||||
semantic Rust test translations are still required before the public API shim
|
extension slices plus semantic Rust test translations are still required before
|
||||||
is complete.
|
the public API shim is complete.
|
||||||
|
|
||||||
The source snapshot, compatibility rules, dependency research, and ordered
|
The source snapshot, compatibility rules, dependency research, and ordered
|
||||||
implementation plan are in [RUSTREWRITE.md](RUSTREWRITE.md).
|
implementation plan are in [RUSTREWRITE.md](RUSTREWRITE.md).
|
||||||
|
|||||||
@@ -52,16 +52,17 @@ The current workspace is a structural baseline, not a working client:
|
|||||||
matching independent ECMA-335 counts, with all 142 external signature types
|
matching independent ECMA-335 counts, with all 142 external signature types
|
||||||
resolved to cross-platform Rust or project-owned boundary types;
|
resolved to cross-platform Rust or project-owned boundary types;
|
||||||
- the completed Types, StructuredData, Imaging, PrimMesher, rendering, main
|
- the completed Types, StructuredData, Imaging, PrimMesher, rendering, main
|
||||||
wire/data, core runtime/networking, and avatar-facing manager slices expose
|
wire/data, core runtime/networking, avatar-facing manager, and
|
||||||
2,597 final Rust-facing types and all 27,191 callable members with real
|
world/social/service manager slices expose 2,795 final Rust-facing types and
|
||||||
fields/constants/enum values and standardized failing bodies;
|
all 28,768 callable members with real fields/constants/enum values and
|
||||||
|
standardized failing bodies;
|
||||||
- all 1,295 NUnit `[Test]`/`[TestCase]` invocations have compiling Rust test
|
- all 1,295 NUnit `[Test]`/`[TestCase]` invocations have compiling Rust test
|
||||||
entries that intentionally panic with their source identity and body hash;
|
entries that intentionally panic with their source identity and body hash;
|
||||||
- all nine sample/tool projects have compiling Rust binary targets;
|
- all nine sample/tool projects have compiling Rust binary targets;
|
||||||
- the 128 TestClient command source files are retained as a command inventory.
|
- the 128 TestClient command source files are retained as a command inventory.
|
||||||
|
|
||||||
The remaining 469 generated type shims preserve names and module placement, but
|
The remaining 271 generated type shims preserve names and module placement, but
|
||||||
do not yet expose their 3,598 callable members. `api/SURFACE.tsv` is an inventory aid,
|
do not yet expose their 2,021 callable members. `api/SURFACE.tsv` is an inventory aid,
|
||||||
not proof of API coverage: it records declaration lines but does not fully parse
|
not proof of API coverage: it records declaration lines but does not fully parse
|
||||||
multiline signatures. Likewise, a generated `pending` test is a parity
|
multiline signatures. Likewise, a generated `pending` test is a parity
|
||||||
placeholder, not a semantic translation. **This repository is therefore at
|
placeholder, not a semantic translation. **This repository is therefore at
|
||||||
@@ -74,6 +75,13 @@ Long-running mapped calls retain an explicit cross-platform cancellation token
|
|||||||
and return the shared `NotImplemented { csharp_member }` error; events return a
|
and return the shared `NotImplemented { csharp_member }` error; events return a
|
||||||
typed subscription guard so callback lifetime is visible to Rust callers.
|
typed subscription guard so callback lifetime is visible to Rust callers.
|
||||||
|
|
||||||
|
The world-facing slice preserves the C# object, parcel, terrain, grid,
|
||||||
|
environment, estate, directory, friend, group, sound, interest-list,
|
||||||
|
marketplace, and reporting concepts. Server-facing async operations retain
|
||||||
|
explicit cancellation and shared typed failures; request/reply events expose
|
||||||
|
typed payloads and subscription guards, while catalog constants and flag values
|
||||||
|
remain real.
|
||||||
|
|
||||||
No functional porting starts until both missing gates are complete across the
|
No functional porting starts until both missing gates are complete across the
|
||||||
entire workspace, rather than one crate at a time:
|
entire workspace, rather than one crate at a time:
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Generated by `python3 tools/generate_api_shims.py`; do not edit by hand.
|
|||||||
|
|
||||||
| Assembly | Types | Members | Status |
|
| Assembly | Types | Members | Status |
|
||||||
|---|---:|---:|---|
|
|---|---:|---:|---|
|
||||||
| `LibreMetaverse` | 2,711 | 27,281 | partial callable shim (2,513 types / 25,704 members) |
|
| `LibreMetaverse` | 2,711 | 27,281 | callable failure-only shim |
|
||||||
| `LibreMetaverse.Imaging.Abstractions` | 3 | 20 | callable failure-only shim |
|
| `LibreMetaverse.Imaging.Abstractions` | 3 | 20 | callable failure-only shim |
|
||||||
| `LibreMetaverse.Imaging.Skia` | 1 | 3 | callable failure-only shim |
|
| `LibreMetaverse.Imaging.Skia` | 1 | 3 | callable failure-only shim |
|
||||||
| `LibreMetaverse.LslTools` | 164 | 768 | pending milestone issue |
|
| `LibreMetaverse.LslTools` | 164 | 768 | pending milestone issue |
|
||||||
@@ -18,14 +18,14 @@ Generated by `python3 tools/generate_api_shims.py`; do not edit by hand.
|
|||||||
| `LibreMetaverse.Voice.Vivox` | 64 | 531 | pending milestone issue |
|
| `LibreMetaverse.Voice.Vivox` | 64 | 531 | pending milestone issue |
|
||||||
| `LibreMetaverse.Voice.WebRTC` | 12 | 210 | pending milestone issue |
|
| `LibreMetaverse.Voice.WebRTC` | 12 | 210 | pending milestone issue |
|
||||||
|
|
||||||
The partial `LibreMetaverse` row contains the completed issue #7 wire/data, issue #8 core
|
The `LibreMetaverse` assembly is complete across issue #7 wire/data, issue #8 core runtime/networking,
|
||||||
runtime/networking, and issue #9 avatar-facing manager slices. World/social/service manager types
|
issue #9 avatar-facing manager, and issue #10 world/social/service manager slices.
|
||||||
remain pending shells for issue #10.
|
|
||||||
|
|
||||||
| Main assembly slice | Types | Members |
|
| Main assembly slice | Types | Members |
|
||||||
|---|---:|---:|
|
|---|---:|---:|
|
||||||
| Issue #7 wire/data | 2,209 | 22,805 |
|
| Issue #7 wire/data | 2,209 | 22,805 |
|
||||||
| Issue #8 core runtime/networking | 111 | 965 |
|
| Issue #8 core runtime/networking | 111 | 965 |
|
||||||
| Issue #9 avatar-facing managers | 193 | 1,934 |
|
| Issue #9 avatar-facing managers | 193 | 1,934 |
|
||||||
|
| Issue #10 world/social/service managers | 198 | 1,577 |
|
||||||
|
|
||||||
Current callable coverage: **2,597 types / 27,191 members**.
|
Current callable coverage: **2,795 types / 28,768 members**.
|
||||||
|
|||||||
@@ -134,3 +134,5 @@ pub struct TypeId(pub &'static str);
|
|||||||
pub struct Span<T>(pub PhantomData<fn(T)>);
|
pub struct Span<T>(pub PhantomData<fn(T)>);
|
||||||
|
|
||||||
pub struct RandomSource;
|
pub struct RandomSource;
|
||||||
|
|
||||||
|
pub struct IAsyncEnumerable<T>(pub PhantomData<fn() -> T>);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
86
tests/compat/tests/world_manager_shims.rs
Normal file
86
tests/compat/tests/world_manager_shims.rs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
use libremetaverse::marketplace::{MarketplaceListing, MarketplaceManager};
|
||||||
|
use libremetaverse::{
|
||||||
|
DirectoryManager, DirectoryManagerAgentSearchData, EstateTask, EstateTools, FriendsManager,
|
||||||
|
GroupManager, GroupProfileEventArgs, ObjectManager, ParcelManager, ParcelSettings, Simulator,
|
||||||
|
TerrainManager, TerrainPatch,
|
||||||
|
};
|
||||||
|
use libremetaverse_types::UUID;
|
||||||
|
use libremetaverse_types::compat::{
|
||||||
|
CancellationToken, EventHandler, IAsyncEnumerable, Subscription,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn member_id<T>(result: Result<T, libremetaverse::Error>) -> &'static str {
|
||||||
|
result
|
||||||
|
.err()
|
||||||
|
.expect("failure-only shim unexpectedly returned a value")
|
||||||
|
.csharp_member()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_search_call(directory: &DirectoryManager, token: CancellationToken) {
|
||||||
|
let _: Result<IAsyncEnumerable<DirectoryManagerAgentSearchData>, libremetaverse::Error> =
|
||||||
|
directory.search_people(String::new(), Some(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_group_and_friend_calls(
|
||||||
|
groups: &GroupManager,
|
||||||
|
friends: &FriendsManager,
|
||||||
|
group_id: UUID,
|
||||||
|
friend_id: UUID,
|
||||||
|
handler: EventHandler<GroupProfileEventArgs>,
|
||||||
|
) {
|
||||||
|
let _: Subscription = groups.subscribe_group_profile(handler);
|
||||||
|
let _ = groups.request_group_profile(group_id);
|
||||||
|
let _ = friends.offer_friendship_with_uuid(friend_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_parcel_call(parcels: &ParcelManager, parcel_id: UUID) {
|
||||||
|
let _ = parcels.request_parcel_info(parcel_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_object_call(objects: &ObjectManager, simulator: Simulator) {
|
||||||
|
let _ = objects.request_object(simulator, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_estate_call(estate: &EstateTools) {
|
||||||
|
let _ = estate.request_info();
|
||||||
|
let _ = estate.request_top_scripts();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn compile_terrain_call(terrain: &TerrainManager, token: CancellationToken) {
|
||||||
|
let _ = terrain.get_terrain_material_overrides(Some(token)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn compile_marketplace_call(marketplace: &MarketplaceManager, token: CancellationToken) {
|
||||||
|
let _ = marketplace.fetch_listings(Some(token)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn world_and_social_flows_have_typed_callable_signatures() {
|
||||||
|
let _ = compile_search_call;
|
||||||
|
let _ = compile_group_and_friend_calls;
|
||||||
|
let _ = compile_parcel_call;
|
||||||
|
let _ = compile_object_call;
|
||||||
|
let _ = compile_estate_call;
|
||||||
|
let _ = compile_terrain_call;
|
||||||
|
let _ = compile_marketplace_call;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn world_facing_constructors_fail_with_catalog_ids() {
|
||||||
|
assert_eq!(
|
||||||
|
member_id(EstateTask::new()),
|
||||||
|
"M:LibreMetaverse.EstateTask.#ctor"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
member_id(MarketplaceListing::new()),
|
||||||
|
"M:LibreMetaverse.Marketplace.MarketplaceListing.#ctor"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
member_id(ParcelSettings::new()),
|
||||||
|
"M:LibreMetaverse.ParcelSettings.#ctor"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
member_id(TerrainPatch::new()),
|
||||||
|
"M:LibreMetaverse.TerrainPatch.#ctor"
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -384,6 +384,10 @@ def rust_constant_value(item: dict) -> str:
|
|||||||
return json.dumps(value)
|
return json.dumps(value)
|
||||||
if item["type"] == "System.Boolean":
|
if item["type"] == "System.Boolean":
|
||||||
return value.lower()
|
return value.lower()
|
||||||
|
if item["type"] in {"System.Single", "System.Double"} and not any(
|
||||||
|
marker in value.lower() for marker in (".", "e")
|
||||||
|
):
|
||||||
|
return value + ".0"
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
@@ -500,6 +504,10 @@ def avatar_type(item: dict) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def world_type(item: dict) -> bool:
|
||||||
|
return not wire_type(item) and not core_type(item) and not avatar_type(item)
|
||||||
|
|
||||||
|
|
||||||
def render_modules(items: list[tuple[dict, dict, bool]], member_rows: dict[str, dict[str, str]], mapper: mapping.Mapper) -> str:
|
def render_modules(items: list[tuple[dict, dict, bool]], member_rows: dict[str, dict[str, str]], mapper: mapping.Mapper) -> str:
|
||||||
tree: dict = {"items": [], "children": {}}
|
tree: dict = {"items": [], "children": {}}
|
||||||
for item, type_row, complete in items:
|
for item, type_row, complete in items:
|
||||||
@@ -558,7 +566,11 @@ def generate_sources(catalog: dict) -> tuple[dict[Path, str], dict[str, tuple[in
|
|||||||
selected = (
|
selected = (
|
||||||
assembly["types"]
|
assembly["types"]
|
||||||
if name in TARGETS
|
if name in TARGETS
|
||||||
else [item for item in assembly["types"] if wire_type(item) or core_type(item) or avatar_type(item)]
|
else [
|
||||||
|
item
|
||||||
|
for item in assembly["types"]
|
||||||
|
if wire_type(item) or core_type(item) or avatar_type(item) or world_type(item)
|
||||||
|
]
|
||||||
)
|
)
|
||||||
selected_ids = {item["doc_id"] for item in selected}
|
selected_ids = {item["doc_id"] for item in selected}
|
||||||
rendered_items = [
|
rendered_items = [
|
||||||
@@ -602,7 +614,7 @@ def coverage_report(catalog: dict, coverage: dict[str, tuple[int, int, bool]]) -
|
|||||||
else:
|
else:
|
||||||
status = "pending milestone issue"
|
status = "pending milestone issue"
|
||||||
lines.append(f"| `{name}` | {types:,} | {members:,} | {status} |")
|
lines.append(f"| `{name}` | {types:,} | {members:,} | {status} |")
|
||||||
if "LibreMetaverse" in coverage and not coverage["LibreMetaverse"][2]:
|
if "LibreMetaverse" in coverage:
|
||||||
main_types = next(
|
main_types = next(
|
||||||
assembly["types"]
|
assembly["types"]
|
||||||
for assembly in catalog["assemblies"]
|
for assembly in catalog["assemblies"]
|
||||||
@@ -615,17 +627,27 @@ def coverage_report(catalog: dict, coverage: dict[str, tuple[int, int, bool]]) -
|
|||||||
for item in main_types
|
for item in main_types
|
||||||
if avatar_type(item) and not wire_type(item) and not core_type(item)
|
if avatar_type(item) and not wire_type(item) and not core_type(item)
|
||||||
]
|
]
|
||||||
|
world_types = [item for item in main_types if world_type(item)]
|
||||||
|
complete = coverage["LibreMetaverse"][2]
|
||||||
lines += [
|
lines += [
|
||||||
"",
|
"",
|
||||||
"The partial `LibreMetaverse` row contains the completed issue #7 wire/data, issue #8 core",
|
(
|
||||||
"runtime/networking, and issue #9 avatar-facing manager slices. World/social/service manager types",
|
"The `LibreMetaverse` assembly is complete across issue #7 wire/data, issue #8 core runtime/networking,"
|
||||||
"remain pending shells for issue #10.",
|
if complete
|
||||||
|
else "The partial `LibreMetaverse` row contains the completed issue #7 wire/data, issue #8 core runtime/networking,"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"issue #9 avatar-facing manager, and issue #10 world/social/service manager slices."
|
||||||
|
if complete
|
||||||
|
else "and issue #9 avatar-facing manager slices. World/social/service manager types remain pending for issue #10."
|
||||||
|
),
|
||||||
"",
|
"",
|
||||||
"| Main assembly slice | Types | Members |",
|
"| Main assembly slice | Types | Members |",
|
||||||
"|---|---:|---:|",
|
"|---|---:|---:|",
|
||||||
f"| Issue #7 wire/data | {len(wire_types):,} | {sum(len(item['members']) for item in wire_types):,} |",
|
f"| Issue #7 wire/data | {len(wire_types):,} | {sum(len(item['members']) for item in wire_types):,} |",
|
||||||
f"| Issue #8 core runtime/networking | {len(core_types):,} | {sum(len(item['members']) for item in core_types):,} |",
|
f"| Issue #8 core runtime/networking | {len(core_types):,} | {sum(len(item['members']) for item in core_types):,} |",
|
||||||
f"| Issue #9 avatar-facing managers | {len(avatar_types):,} | {sum(len(item['members']) for item in avatar_types):,} |",
|
f"| Issue #9 avatar-facing managers | {len(avatar_types):,} | {sum(len(item['members']) for item in avatar_types):,} |",
|
||||||
|
f"| Issue #10 world/social/service managers | {len(world_types):,} | {sum(len(item['members']) for item in world_types):,} |",
|
||||||
]
|
]
|
||||||
lines += ["", f"Current callable coverage: **{total_types:,} types / {total_members:,} members**.", ""]
|
lines += ["", f"Current callable coverage: **{total_types:,} types / {total_members:,} members**.", ""]
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|||||||
Reference in New Issue
Block a user