Skip to content

[Types] Add lossless conversion between WoT documents and NodeSet2 - #4131

Open
marcschier wants to merge 14 commits into
marcschier/wot-01-core-typesfrom
marcschier/wot-03-converter
Open

[Types] Add lossless conversion between WoT documents and NodeSet2#4131
marcschier wants to merge 14 commits into
marcschier/wot-01-core-typesfrom
marcschier/wot-03-converter

Conversation

@marcschier

Copy link
Copy Markdown
Collaborator

Adds a dependency-light, AOT-safe lexical model for Thing Description and Thing Model documents to Opc.Ua.Types, together with lossless converters between WoT documents and NodeSet2 and canonical NodeSet comparison for round-trip checks.

This is PR 3 of a stacked split of #4093 into independently reviewable pieces. It is self-contained, targets master directly, and depends on no other PR in the stack.

The change is a pure library in Opc.Ua.Types with no server/client involvement and no network I/O of its own. Unknown JSON-LD members are preserved as digest-protected RFC 6901 residue entries, native NodeSet projection is emitted according to the preservation mode, and resolver contracts expose asynchronous bounded resolution with structured diagnostics.

This PR is still large (~8,000 lines). Suggested review passes:

  1. Lexical model and residue preservation.
  2. Converter and native projection.
  3. Resolver contracts and NodeSet comparison.

Adds a dependency-light, AOT-safe lexical model for Thing Description and Thing Model documents to Opc.Ua.Types, together with converters in both directions and a canonical NodeSet comparison used to decide when a conversion round-trips.

Values that the mapping does not recognise are preserved as digest-protected RFC 6901 residue entries in standard NodeSet Extensions, so an unknown JSON-LD member survives repeated conversion in either direction rather than being dropped. The deterministic uav:nodes projection is emitted only when a readable reverse conversion would not reproduce the complete UANodeSet, and the preservation mode selects between WhenRequired, Always and Never.

Resolution of referenced documents is asynchronous, since implementations supply their own transport, and is bounded by depth, cumulative size and cycle detection. Diagnostics are structured rather than exceptions so a caller can report every problem in a document at once.

The library performs no network I/O of its own and has no dependency on the server, the client or the source generator.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Copilot AI review requested due to automatic review settings July 30, 2026 17:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds a WoT lexical document model plus lossless conversion between WoT TD/TM JSON and OPC UA NodeSet2 (including preservation envelope, native projection fallback), along with bounded async resolver contracts and canonical NodeSet comparison utilities for round-trip verification.

Changes:

  • Introduces WoT conversion core (document model, diagnostics, vocabulary, resolver/bounds, converter options/catalog).
  • Adds canonical NodeSet comparison + round-trip reporting helpers.
  • Adds extensive NUnit test coverage for synthesis, preservation modes, resolver bounds/cycles, native projection, and comparison behavior.

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/Opc.Ua.Types.Tests/Wot/WotTestData.cs Adds shared NodeSet fixtures + helpers for WoT conversion tests.
tests/Opc.Ua.Types.Tests/Wot/WotSynthesisTests.cs Validates WoT JSON synthesis into NodeSet nodes/references and determinism.
tests/Opc.Ua.Types.Tests/Wot/WotResolverAndBoundsTests.cs Covers resolver context limits, cycles, redirects, cancellation, and option projection.
tests/Opc.Ua.Types.Tests/Wot/WotResolverAdditionalTests.cs Adds additional resolver/options/context/result behavioral tests.
tests/Opc.Ua.Types.Tests/Wot/WotNodeSetConverterTests.cs Tests envelope roundtrip, determinism, residue preservation, and digest rejection.
tests/Opc.Ua.Types.Tests/Wot/WotNativeProjectionTests.cs Verifies native-only projection reconstruction + determinism and reference type details.
tests/Opc.Ua.Types.Tests/Wot/WotNativeProjectionErrorTests.cs Exercises native projection validation/errors and malformed extension handling.
tests/Opc.Ua.Types.Tests/Wot/WotNativeFirstRoundtripTests.cs Tests readable mapping completeness vs fallback behaviors + residue stability.
tests/Opc.Ua.Types.Tests/Wot/WotMappingValidationTests.cs Validates mapping rules/diagnostics for event types, references, naming, and type hints.
tests/Opc.Ua.Types.Tests/Wot/WotEnvelopeTests.cs Tests envelope integrity, digest behavior, conflict detection, and spec constraints.
tests/Opc.Ua.Types.Tests/Wot/WotDocumentTests.cs Tests lexical preservation, typed accessors, pointers, and canonical writer output.
tests/Opc.Ua.Types.Tests/Wot/WotDocumentKindTests.cs Tests kind inference, forms access, pointer guards, and size-depth parse limits.
tests/Opc.Ua.Types.Tests/Wot/WotConverterPreservationTests.cs Covers preservation modes, size limits, success flags, and envelope restore diagnostics.
tests/Opc.Ua.Types.Tests/Wot/WotBindingReviewTests.cs Validates binding review rules: eventType annotation, portable identity, typed links.
tests/Opc.Ua.Types.Tests/Schema/NodeSetComparerTests.cs Adds tests for NodeSet canonical compare and roundtrip reporting.
tests/Opc.Ua.Types.Tests/Schema/NodeSetComparerAdditionalTests.cs Adds additional comparer guard and diff-report tests, including BOM handling.
src/Opc.Ua.Types/Wot/WotVocabulary.cs Centralizes UA IDs/mappings used by WoT conversion (refs, rules, JSON type mapping).
src/Opc.Ua.Types/Wot/WotThingCatalog.cs Adds catalog to preserve stable generated NodeIds across referenced Things.
src/Opc.Ua.Types/Wot/WotResolver.cs Introduces resolver contracts, bounded options, null resolver, and resolution context.
src/Opc.Ua.Types/Wot/WotNodeSetConverterOptions.cs Adds converter resource limits + mapping to resolver options.
src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs Implements main NodeSet<->WoT conversion paths (envelope/projection/synthesis/residue).
src/Opc.Ua.Types/Wot/WotDocument.cs Implements lossless WoT JSON wrapper with typed accessors + pointer and canonical writer.
src/Opc.Ua.Types/Wot/WotDiagnostics.cs Defines diagnostic codes/severity/location and conversion result container.
src/Opc.Ua.Types/Schema/NodeSetComparer.cs Adds canonicalized NodeSet comparison + roundtrip reporting utility.

Comment thread src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs Outdated
Comment thread src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs Outdated
Comment thread src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs Outdated
Comment thread src/Opc.Ua.Types/Wot/WotResolver.cs
Comment thread tests/Opc.Ua.Types.Tests/Wot/WotNodeSetConverterTests.cs
Comment thread tests/Opc.Ua.Types.Tests/Wot/WotNativeProjectionErrorTests.cs Outdated
@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.23529% with 432 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.05%. Comparing base (8a10139) to head (fc38861).
⚠️ Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
src/Opc.Ua.Types/Wot/WotNodeSetConverter.WoT.cs 89.03% 63 Missing and 51 partials ⚠️
...rc/Opc.Ua.Types/Wot/WotNodeSetConverter.NodeSet.cs 83.99% 43 Missing and 54 partials ⚠️
src/Opc.Ua.Types/Wot/WotJsonResidue.cs 87.71% 44 Missing and 27 partials ⚠️
src/Opc.Ua.Types/Wot/WotNativeProjection.cs 92.49% 25 Missing and 34 partials ⚠️
src/Opc.Ua.Types/Schema/NodeSetComparer.cs 83.58% 15 Missing and 7 partials ⚠️
src/Opc.Ua.Types/Wot/WotDocument.cs 89.71% 15 Missing and 7 partials ⚠️
src/Opc.Ua.Types/Wot/WotVocabulary.cs 85.88% 8 Missing and 4 partials ⚠️
src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs 78.72% 7 Missing and 3 partials ⚠️
src/Opc.Ua.Types/Wot/WotResolver.cs 90.09% 4 Missing and 6 partials ⚠️
src/Opc.Ua.Types/Wot/WotDiagnostics.cs 81.25% 1 Missing and 5 partials ⚠️
... and 2 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #4131      +/-   ##
==========================================
- Coverage   80.23%   80.05%   -0.19%     
==========================================
  Files        1515     1537      +22     
  Lines      209980   214309    +4329     
  Branches    36213    37040     +827     
==========================================
+ Hits       168479   171557    +3078     
- Misses      28867    29890    +1023     
- Partials    12634    12862     +228     
Files with missing lines Coverage Δ
src/Opc.Ua.Types/Wot/WotThingCatalog.cs 66.66% <66.66%> (ø)
src/Opc.Ua.Types/Wot/WotNodeSetConverterOptions.cs 86.48% <86.48%> (ø)
src/Opc.Ua.Types/Wot/WotDiagnostics.cs 81.25% <81.25%> (ø)
src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs 78.72% <78.72%> (ø)
src/Opc.Ua.Types/Wot/WotResolver.cs 90.09% <90.09%> (ø)
src/Opc.Ua.Types/Wot/WotVocabulary.cs 85.88% <85.88%> (ø)
src/Opc.Ua.Types/Schema/NodeSetComparer.cs 83.58% <83.58%> (ø)
src/Opc.Ua.Types/Wot/WotDocument.cs 89.71% <89.71%> (ø)
src/Opc.Ua.Types/Wot/WotNativeProjection.cs 92.49% <92.49%> (ø)
src/Opc.Ua.Types/Wot/WotJsonResidue.cs 87.71% <87.71%> (ø)
... and 2 more

... and 70 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Track active resolver entries by both WotResolutionKind and reference so a shared URI can be resolved as different document kinds without being reported as a cycle, while same-kind cycles remain blocked.

Make the digest mismatch test mutate uav:nodeSet.data structurally and make the malformed native projection extension test assert the actual null-result/error-diagnostic contract.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Comment thread src/Opc.Ua.Types/Wot/WotNodeSetConverter.Mapping.cs Outdated
Comment thread src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs Outdated
Comment thread src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs Outdated
Comment thread src/Opc.Ua.Types/Wot/WotNodeSetConverter.cs Outdated
marcschier and others added 10 commits July 31, 2026 10:54
Replace stored multi-field WoT converter tuples with private readonly record structs so the carried values have named types without changing value semantics.

Replace the CA2000 SuppressMessage attribute with a narrowly scoped pragma around the WotDocument ownership-transfer statement.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
The package readme did not mention the Opc.Ua.Wot conversion surface this change
introduces. Describes WotNodeSetConverter, the three
WotNodeSetConverterOptions.PreservationMode values, the pointer-addressed residue for
unmapped WoT JSON-LD members, and the NamespaceUri-qualified typed reference links.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
@marcschier
marcschier changed the base branch from master to marcschier/wot-01-core-types August 1, 2026 11:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants