Skip to content

Conversation

@konard
Copy link
Member

@konard konard commented Jan 13, 2026

Summary

This PR implements Rust-specific tuple conversion support for Links Notation, enabling ergonomic link creation using native Rust tuple syntax. The implementation uses a macro-based approach to support all tuple sizes from 2 to 12 (following Rust's standard library convention), plus alternative APIs for arbitrary-length link creation.

Changes

Core Implementation

  • Added impl_tuple_from! macro in rust/links-notation/src/lib.rs that generates From trait implementations for tuples
  • Support for tuples sizes 2-12 (44 total implementations: 4 types × 11 sizes)
  • Support for multiple tuple type combinations:
    • All &str: ("id", "v1", "v2", ...)(id: v1 v2 ...)
    • All String: (id.to_string(), v1.to_string(), ...)(id: v1 v2 ...)
    • &str ID with LiNo values: ("id", lino1, lino2, ...)(id: <lino1> <lino2> ...)
    • All LiNo: (lino1, lino2, ...)(<lino1> <lino2> ...) (anonymous link)

Alternative APIs for Arbitrary-Length Links

Since Rust lacks variadic generics, we provide alternative APIs for creating links with any number of values:

1. LinkBuilder (Fluent API)

let link: LiNo<String> = LinkBuilder::new()
    .id("myLink")
    .value("v1")
    .values(vec!["v2", "v3"])
    .lino(nested_link)
    .build();

2. Vec-based Conversions

// Anonymous link from Vec
let link: LiNo<String> = vec!["a", "b", "c"].into();

// Named link from (id, Vec) tuple
let link: LiNo<String> = ("myId", vec!["v1", "v2", "v3"]).into();

3. Static Methods

let link = LiNo::new(Some("id".to_string()), values);
let link = LiNo::anonymous(values);
let r = LiNo::reference("value".to_string());

Test Coverage

  • 47 comprehensive tests in rust/links-notation/tests/tuple_tests.rs
  • Tests cover:
    • Basic tuple to link conversion (2-4 tuples)
    • Large tuple conversions (5-12 tuples)
    • Owned vs borrowed strings
    • Mixed tuple types
    • Anonymous links from LiNo tuples
    • Nested link structures
    • Complex examples matching C# implementation
    • Vec-based conversions (arbitrary length)
    • LinkBuilder API tests
    • Static method tests

Documentation

  • Updated rust/links-notation/README.md with comprehensive tuple conversion section
  • Detailed comments explaining Rust's variadic generics limitation

Why Can't We Support Any Tuple Length?

Rust does not have variadic generics (a feature still in pre-RFC stage), which would be required to implement From for tuples of arbitrary length. This is a fundamental Rust limitation - even the standard library only implements traits for tuples up to 12 elements.

For more information:

Testing

All tests pass successfully:

  • ✅ 47 tuple conversion tests (including Vec and Builder tests)
  • ✅ All existing tests (275+ tests total) continue to pass
  • ✅ Code formatting (cargo fmt)
  • ✅ Linting (cargo clippy)
  • ✅ No warnings or errors

API Summary

API Max Length Use Case
Tuple conversion 12 Most common cases, ergonomic syntax
Vec conversion Unlimited Runtime-determined or large fixed sets
LinkBuilder Unlimited Fluent construction, mixing types
LiNo::new() Unlimited Direct construction with Vec

Fixes #200


🤖 Generated with Claude Code

Adding CLAUDE.md with task information for AI processing.
This file will be removed when the task is complete.

Issue: #200
@konard konard self-assigned this Jan 13, 2026
Implement From trait conversions for Rust tuples (2-tuple through 4-tuple)
to LiNo<String>, enabling ergonomic syntax similar to C#'s tuple conversion.

Features:
- Support for string tuples: (&str, &str), (String, String), etc.
- Support for mixed tuples: (&str, LiNo<String>), etc.
- Support for LiNo tuples: (LiNo<String>, LiNo<String>), etc.
- Anonymous links from multiple LiNo values
- Comprehensive test coverage with 16 new tests

This brings Rust implementation closer to feature parity with C#,
allowing developers to create links using native Rust tuple syntax.

Fixes #200

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@konard konard changed the title [WIP] Tuple to Links Notation and Links Notation to Tuple Add Rust tuple conversion support for ergonomic link creation Jan 13, 2026
Create comprehensive example showing:
- Basic 2-tuple, 3-tuple, and 4-tuple conversions
- Mixed tuples with LiNo values
- Anonymous links from LiNo tuples
- Complex nested structures
- Ergonomic collection creation
- Owned String tuple conversion

Example can be run with: cargo run --example tuple_conversion

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@konard konard marked this pull request as ready for review January 13, 2026 12:21
@konard
Copy link
Member Author

konard commented Jan 13, 2026

⚠️ Solution Draft Finished with Errors

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost estimation:

  • Public pricing estimate: $2.595061 USD
  • Calculated by Anthropic: $0.000000 USD
  • Difference: $-2.595061 (-100.00%)

Note: The session encountered errors during execution, but some work may have been completed. Please review the changes carefully.

📎 Log file uploaded as Gist (571KB)
🔗 View complete solution draft log

Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Member Author

konard commented Jan 16, 2026

Resolve conflicts.

Can we support all tuple sizes all at once? Do we need marco for that?

@konard konard marked this pull request as draft January 16, 2026 12:19
@konard
Copy link
Member Author

konard commented Jan 16, 2026

🤖 AI Work Session Started

Starting automated work session at 2026-01-16T12:19:53.892Z

The PR has been converted to draft mode while work is in progress.

This comment marks the beginning of an AI work session. Please wait working session to finish, and provide your feedback.

konard and others added 2 commits January 16, 2026 13:21
Resolve merge conflicts from Rust project restructuring:
- Move tuple_conversion.rs to new location: rust/links-notation/examples/
- Move tuple_tests.rs to new location: rust/links-notation/tests/

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace manually written From implementations for tuples with a macro-based
approach (impl_tuple_from!) that generates all necessary implementations for
tuples of sizes 2 through 12, following Rust's standard library convention.

Changes:
- Replace 12 manual impl From blocks with macro-generated implementations
- Support 4 conversion types for each tuple size:
  - All &str: first becomes ID, rest become values
  - All String: same pattern with owned strings
  - &str ID with LiNo values: for nested link structures
  - All LiNo: creates anonymous links (no ID)
- Add 16 new tests for tuple sizes 5-12
- Update README documentation with new tuple size support

This reduces code duplication while providing compile-time type safety
for all supported tuple sizes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@konard konard changed the title Add Rust tuple conversion support for ergonomic link creation Add Rust tuple conversion support with macro for all sizes (2-12) Jan 16, 2026
@konard konard marked this pull request as ready for review January 16, 2026 12:31
@konard
Copy link
Member Author

konard commented Jan 16, 2026

Changes Made

I've addressed the feedback:

1. Resolved Merge Conflicts

Merged the latest changes from main which included the Rust project restructuring (moving from rust/ to rust/links-notation/).

2. Implemented Macro for All Tuple Sizes (2-12)

As requested, I replaced the manual From implementations with a macro-based approach:

macro_rules! impl_tuple_from {
    // ... generates all implementations
}

// Generate implementations for tuples of sizes 2 through 12
impl_tuple_from!(2);
impl_tuple_from!(3);
// ... up to
impl_tuple_from!(12);

This follows the Rust standard library convention of supporting tuples up to 12 elements. The macro generates 44 total implementations (4 types × 11 sizes):

Tuple Type Description Example
All &str First becomes ID, rest become values ("id", "v1", "v2")(id: v1 v2)
All String Same with owned strings (String, String, String)
&str + LiNo String ID with LiNo values ("id", lino1, lino2)
All LiNo Anonymous link (no ID) (lino1, lino2)(lino1 lino2)

Test Results

  • ✅ All 265+ tests pass
  • ✅ 29 tuple tests (16 new tests for large tuples)
  • cargo fmt and cargo clippy pass with no warnings

The PR is now ready for review.

@konard
Copy link
Member Author

konard commented Jan 16, 2026

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost estimation:

  • Public pricing estimate: $4.886820 USD
  • Calculated by Anthropic: $4.707230 USD
  • Difference: $-0.179590 (-3.67%)
    📎 Log file uploaded as Gist (817KB)
    🔗 View complete solution draft log

Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Member Author

konard commented Jan 17, 2026

So we cannot support any tuple length? Once and for all?

@konard konard marked this pull request as draft January 17, 2026 00:03
@konard
Copy link
Member Author

konard commented Jan 17, 2026

🤖 AI Work Session Started

Starting automated work session at 2026-01-17T00:03:57.382Z

The PR has been converted to draft mode while work is in progress.

This comment marks the beginning of an AI work session. Please wait working session to finish, and provide your feedback.

Rust does not support variadic generics (a long-requested feature still
in pre-RFC stage), which means we cannot implement From for tuples of
arbitrary length. This is a fundamental Rust limitation - even the
standard library only implements traits for tuples up to 12 elements.

This commit adds alternative APIs for creating links when tuple
conversion is insufficient:

1. LinkBuilder - fluent builder API for constructing links:
   ```rust
   LinkBuilder::new()
       .id("myLink")
       .value("v1")
       .values(vec!["v2", "v3"])
       .lino(nested_link)
       .build()
   ```

2. Vec-based From implementations:
   - From<Vec<&str>> for anonymous links
   - From<Vec<String>> for anonymous links
   - From<Vec<LiNo<String>>> for anonymous links
   - From<(&str, Vec<&str>)> for named links
   - From<(String, Vec<String>)> for named links
   - From<(&str, Vec<LiNo<String>>)> for named links
   - From<(String, Vec<LiNo<String>>)> for named links

3. Static methods on LiNo:
   - LiNo::new(id, values) - create named link
   - LiNo::anonymous(values) - create anonymous link
   - LiNo::reference(value) - create reference

These APIs support creating links with any number of values,
addressing the user's question about supporting "any tuple length,
once and for all."

For reference on Rust's variadic generics status:
- rust-lang/rfcs#376
- rust-lang/rust#10124

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@konard
Copy link
Member Author

konard commented Jan 17, 2026

Response to Question: Can we support any tuple length?

Short answer: No, not with Rust's current type system.

Why Rust Can't Support Arbitrary-Length Tuples

Rust does not have variadic generics, which would be required to implement From for tuples of any length. This is a fundamental limitation of Rust's type system, not something we can work around with macros or clever tricks.

Even the Rust standard library faces this same limitation - traits like Debug, Default, Hash, PartialEq, Clone, etc. are only implemented for tuples up to 12 elements.

Status of variadic generics in Rust:

  • The feature has been requested since 2013 (RFC #10124)
  • It's still in the pre-RFC/design discussion phase (RFC #376)
  • Recent progress at RustWeek 2025 shows the Lang team is more open to discussions now that the new trait solver is partially stabilized
  • No RFC has been accepted and implementation has not begun

Solution: Alternative APIs for Arbitrary-Length Links

I've added three alternative approaches that do support any number of values:

1. Vec-based Conversions

// Anonymous link with any number of values
let values: Vec<&str> = vec!["v1", "v2", "v3", ..., "v100"];
let link: LiNo<String> = values.into();

// Named link with any number of values
let link: LiNo<String> = ("myId", values).into();

2. LinkBuilder (Fluent API)

let link: LiNo<String> = LinkBuilder::new()
    .id("myLink")
    .value("v1")
    .value("v2")
    .values(vec!["v3", "v4", "v5"])
    .lino(nested_link)
    .build();

3. Static Methods

let values: Vec<LiNo<String>> = (1..=100)
    .map(|i| LiNo::Ref(format!("item{}", i)))
    .collect();
let link = LiNo::new(Some("hundred".to_string()), values);

Summary

API Max Length Use Case
Tuple conversion 12 Most common cases, ergonomic syntax
Vec conversion Unlimited Runtime-determined or large fixed sets
LinkBuilder Unlimited Fluent construction, mixing types
LiNo::new() Unlimited Direct construction with Vec

The tuple conversion (2-12 elements) covers the vast majority of use cases with the most ergonomic syntax. For cases needing more elements or runtime-determined sizes, the new APIs provide full support.

All 275 tests pass ✅

@konard konard marked this pull request as ready for review January 17, 2026 00:09
@konard
Copy link
Member Author

konard commented Jan 17, 2026

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost estimation:

  • Public pricing estimate: $3.405479 USD
  • Calculated by Anthropic: $2.469812 USD
  • Difference: $-0.935667 (-27.48%)
    📎 Log file uploaded as Gist (727KB)
    🔗 View complete solution draft log

Now working session is ended, feel free to review and add any feedback on the solution draft.

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.

Tuple to Links Notation and Links Notation to Tuple

2 participants