dry-validation-rust 0.1.0.pre5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +74 -0
  3. data/LICENSE +21 -0
  4. data/NOTICE.md +28 -0
  5. data/README.md +459 -0
  6. data/docs/ARCHITECTURE.md +256 -0
  7. data/docs/COMPATIBILITY.md +198 -0
  8. data/docs/FEASIBILITY.md +207 -0
  9. data/docs/SUPPORT_MATRIX.md +66 -0
  10. data/docs/VERIFICATION.md +128 -0
  11. data/dry-validation-rust.gemspec +58 -0
  12. data/ext/dry_validation_rust/Cargo.lock +809 -0
  13. data/ext/dry_validation_rust/Cargo.toml +44 -0
  14. data/ext/dry_validation_rust/benches/coercion.rs +77 -0
  15. data/ext/dry_validation_rust/benches/full_schema.rs +189 -0
  16. data/ext/dry_validation_rust/benches/plan_compile.rs +37 -0
  17. data/ext/dry_validation_rust/benches/predicates.rs +105 -0
  18. data/ext/dry_validation_rust/extconf.rb +29 -0
  19. data/ext/dry_validation_rust/src/coercion.rs +515 -0
  20. data/ext/dry_validation_rust/src/engine.rs +416 -0
  21. data/ext/dry_validation_rust/src/error.rs +82 -0
  22. data/ext/dry_validation_rust/src/extract_primitive.rs +23 -0
  23. data/ext/dry_validation_rust/src/generated_predicates.rs +33 -0
  24. data/ext/dry_validation_rust/src/lib.rs +228 -0
  25. data/ext/dry_validation_rust/src/plan.rs +611 -0
  26. data/ext/dry_validation_rust/src/predicates.rs +449 -0
  27. data/ext/dry_validation_rust/src/ruby_bridge.rs +78 -0
  28. data/lib/dry/schema.rb +6 -0
  29. data/lib/dry/validation/rust/block_keyword_parameters.rb +20 -0
  30. data/lib/dry/validation/rust/config.rb +74 -0
  31. data/lib/dry/validation/rust/contract/result.rb +180 -0
  32. data/lib/dry/validation/rust/contract/values.rb +73 -0
  33. data/lib/dry/validation/rust/contract.rb +400 -0
  34. data/lib/dry/validation/rust/errors.rb +14 -0
  35. data/lib/dry/validation/rust/evaluator.rb +295 -0
  36. data/lib/dry/validation/rust/failures.rb +57 -0
  37. data/lib/dry/validation/rust/generated_predicates.rb +14 -0
  38. data/lib/dry/validation/rust/macros.rb +45 -0
  39. data/lib/dry/validation/rust/message.rb +41 -0
  40. data/lib/dry/validation/rust/message_backend.rb +115 -0
  41. data/lib/dry/validation/rust/message_set.rb +159 -0
  42. data/lib/dry/validation/rust/native.rb +25 -0
  43. data/lib/dry/validation/rust/path.rb +65 -0
  44. data/lib/dry/validation/rust/path_trie.rb +57 -0
  45. data/lib/dry/validation/rust/result.rb +3 -0
  46. data/lib/dry/validation/rust/rule.rb +62 -0
  47. data/lib/dry/validation/rust/schema/dsl.rb +76 -0
  48. data/lib/dry/validation/rust/schema/field_builder.rb +156 -0
  49. data/lib/dry/validation/rust/schema/field_definition.rb +99 -0
  50. data/lib/dry/validation/rust/schema/predicate_block.rb +56 -0
  51. data/lib/dry/validation/rust/schema/processor_hooks.rb +46 -0
  52. data/lib/dry/validation/rust/schema/result.rb +67 -0
  53. data/lib/dry/validation/rust/schema/ruby_type_processor.rb +44 -0
  54. data/lib/dry/validation/rust/schema.rb +323 -0
  55. data/lib/dry/validation/rust/values.rb +3 -0
  56. data/lib/dry/validation/rust/version.rb +10 -0
  57. data/lib/dry/validation/rust.rb +55 -0
  58. data/lib/dry/validation.rb +66 -0
  59. data/lib/dry-schema.rb +3 -0
  60. data/lib/dry-validation.rb +3 -0
  61. data/lib/dry_validation_rust.rb +3 -0
  62. data/predicates.yml +67 -0
  63. data/rust-toolchain.toml +9 -0
  64. metadata +260 -0
@@ -0,0 +1,66 @@
1
+ # Support matrix
2
+
3
+ This matrix describes the public support target for each planned gem line. It
4
+ does not widen the implemented API surface; feature support remains documented
5
+ in [COMPATIBILITY.md](COMPATIBILITY.md).
6
+
7
+ ## Versioned targets
8
+
9
+ | Gem line | Ruby | Rust MSRV | Platforms | Upstream reference | Status |
10
+ | -------- | ------- | --------- | -------------------------------------------------- | -------------------------------------------- | ------ |
11
+ | 0.1.x | 3.3-3.5 | 1.75 | Source build; all CI workflows use the pinned MSRV | `dry-validation` 1.11.1, `dry-schema` 1.16.0 | alpha |
12
+ | 0.2.x | TBD | TBD | Native gems under evaluation | pinned before beta | beta |
13
+
14
+ ## Support policy
15
+
16
+ - `Dry::Validation::Rust::Contract` is the primary supported API for the
17
+ `0.1.x` line.
18
+ - Familiar dry-validation-style syntax is supported only for the compatible
19
+ subset covered by tests and documented in [COMPATIBILITY.md](COMPATIBILITY.md).
20
+ - Exact compatibility mode owns upstream-like require paths and constants. It
21
+ is experimental, opt-in, and must run in a process isolated from upstream
22
+ `dry-validation` and `dry-schema`.
23
+ - Runtime support means source builds and test coverage for the listed matrix,
24
+ not precompiled native gems unless a later row explicitly says so.
25
+
26
+ ## Semantic versioning policy
27
+
28
+ Releases follow [Semantic Versioning 2.0.0](https://semver.org/). The version
29
+ in `Dry::Validation::Rust::VERSION` is authoritative for the Ruby gem. A
30
+ release must use at least the bump shown below; multiple changes use the
31
+ largest applicable bump.
32
+
33
+ Before 1.0, a breaking change to a supported surface requires the next minor
34
+ line (for example, `0.1.x` to `0.2.0`). From 1.0 onward, it requires the next
35
+ major line. This preserves the `0.1.x` side-by-side API promise while keeping
36
+ the eventual stable-release policy conventional.
37
+
38
+ | Change type | Minimum version bump |
39
+ | ------------------------------------------------------------------------------------------------ | -------------------------------------------- |
40
+ | Backwards-compatible bug fix, documentation correction, or internal native implementation change | Patch (`0.x.y`) |
41
+ | New backwards-compatible Ruby predicate or schema feature | Minor (`0.x.0`) |
42
+ | Addition of a supported precompiled platform gem | Minor (`0.x.0`) |
43
+ | Increase to the documented Rust MSRV | Minor (`0.x.0`) |
44
+ | Removal of a supported platform, Ruby version, or precompiled platform gem | Next minor before 1.0; major from 1.0 onward |
45
+ | Incompatible change or removal in the documented public side-by-side Ruby API | Next minor before 1.0; major from 1.0 onward |
46
+ | Native ABI-incompatible change, including an incompatible Magnus or CRuby ABI support change | Next minor before 1.0; major from 1.0 onward |
47
+
48
+ The compatibility shim is experimental and excluded from the public API
49
+ compatibility guarantee. Changes to its documented support status still follow
50
+ this policy when they remove a listed runtime or platform target. A change to
51
+ the Rust crate's internal implementation is not an ABI break by itself; the
52
+ ABI rule applies when it changes which CRuby/Magnus ABI combinations the gem
53
+ supports or requires users to rebuild incompatible native artifacts.
54
+
55
+ ## Product architecture note
56
+
57
+ The current gem contains both the safe namespace and the exact compatibility
58
+ shim. If the exact shim becomes expensive to maintain or its collision surface
59
+ creates user confusion, the intended split is:
60
+
61
+ ```text
62
+ dry-validation-rust
63
+ dry-validation-rust-compat
64
+ ```
65
+
66
+ No split is planned for `0.1.x` without concrete maintenance evidence.
@@ -0,0 +1,128 @@
1
+ # Verification Guide
2
+
3
+ Status: living document.
4
+ Last updated: 2026-07-29.
5
+
6
+ This document describes how to verify the claims made in the project
7
+ documentation. Every claim in ARCHITECTURE.md, COMPATIBILITY.md, and the
8
+ README should be traceable to a command or test described here.
9
+
10
+ ## Quick Verification
11
+
12
+ Run the full verification suite:
13
+
14
+ script/verify
15
+
16
+ This executes:
17
+
18
+ 1. Ruby unit and integration tests (`bundle exec rake test`).
19
+ 2. Differential compatibility tests against pinned upstream.
20
+ 3. RuboCop lint.
21
+ 4. Package metadata audit.
22
+
23
+ ## Milestone Verification Status
24
+
25
+ | Milestone | Verification Method | Status |
26
+ | ------------------------ | ---------------------------------------------------------------------------------- | ----------- |
27
+ | A — Trustworthy Baseline | `script/verify`, CI workflows, package audit | ✅ Verified |
28
+ | B — Common Schema Subset | Differential corpus (80+ cases), Rust unit tests (28), malformed-input corpus (64) | ✅ Verified |
29
+ | C — Ordinary Rules | `rules_test.rb`, differential rule cases | 🔵 Partial |
30
+ | D — Performance Proof | `benchmark/schema_throughput.rb` (no published results yet) | ⚪ Pending |
31
+ | E–G | Not yet applicable | ⚪ Pending |
32
+
33
+ ## Ruby-Side Evidence
34
+
35
+ ### Unit Tests
36
+
37
+ bundle exec rake test
38
+
39
+ Covers: schema definition, coercion, predicates, rules, result API, messages,
40
+ config, contract DSL, evaluator, path, failures, values.
41
+
42
+ ### Differential Compatibility
43
+
44
+ bundle exec ruby test/differential_compatibility_test.rb
45
+
46
+ Runs each fixture case in an isolated subprocess against both this gem and
47
+ pinned upstream `dry-validation` 1.11.1. Compares:
48
+
49
+ - Output values (deep equality).
50
+ - Error messages (deep equality).
51
+ - Unsupported constructs raise the expected error class.
52
+
53
+ Fixtures live in `test/fixtures/differential/`.
54
+
55
+ ### Unsupported Constructs
56
+
57
+ Six cases verify that unsupported upstream features (hints, i18n, monads,
58
+ macros, each with complex blocks, dry-schema composition) raise
59
+ `UnsupportedFeatureError` rather than silently producing wrong results.
60
+
61
+ ## Rust-Side Evidence
62
+
63
+ ### Unit Tests
64
+
65
+ cd ext/dry_validation_rust && cargo test
66
+
67
+ 21 tests covering:
68
+
69
+ - Plan deserialization and version checking (`plan.rs`).
70
+ - Coercion edge cases: `"Infinity"`, `"NaN"`, `"1_000"`, empty strings,
71
+ overflow, unicode (`coercion.rs`).
72
+ - Predicate evaluation: boundary values, type mismatches (`predicates.rs`).
73
+ - Message interpolation: token substitution, missing tokens (`messages.rs`).
74
+
75
+ ### MSRV
76
+
77
+ The repository pins Rust 1.75.0 in `rust-toolchain.toml`; all CI workflows use
78
+ that exact toolchain. Verify the locked crate and its test suite explicitly
79
+ with:
80
+
81
+ cargo +1.75.0 check --locked --manifest-path ext/dry_validation_rust/Cargo.toml
82
+ cargo +1.75.0 test --locked --manifest-path ext/dry_validation_rust/Cargo.toml
83
+
84
+ ### Clippy
85
+
86
+ cd ext/dry_validation_rust && cargo clippy -- -D warnings
87
+
88
+ ### Malformed-Input Resilience
89
+
90
+ 64-input seeded corpus in `test/malformed_input_test.rb` exercises the Rust
91
+ engine with:
92
+
93
+ - Deeply nested structures (up to depth 200, guarded by recursion limit).
94
+ - Oversized strings (1 MB+).
95
+ - Mixed-type arrays.
96
+ - Null bytes and invalid UTF-8 sequences.
97
+ - Extreme numeric values (MAX_INT, MIN_INT, MAX_FLOAT, NaN, Infinity).
98
+
99
+ ## Compatibility Matrix
100
+
101
+ See `COMPATIBILITY.md` for the feature-by-feature matrix. Each row marked
102
+ "✅ implemented and covered" must have at least one differential fixture case.
103
+
104
+ ## Benchmarks
105
+
106
+ See `benchmark/schema_throughput.rb`. No published results yet — Milestone D
107
+ will produce `docs/BENCHMARKS.md`.
108
+
109
+ ## CI Workflows
110
+
111
+ | Workflow | Trigger | Purpose |
112
+ | ------------------- | ---------------- | ------------------------------------------------- |
113
+ | `ci.yml` | push, PR | Tests + lint + compile |
114
+ | `compatibility.yml` | push, PR, weekly | Differential suite against pinned upstream |
115
+ | `fuzz.yml` | weekly, manual | Five-minute `cargo fuzz` plan-deserialization run |
116
+ | `package.yml` | push, PR | Gemspec/Cargo metadata audit |
117
+ | `security.yml` | push, PR, weekly | `cargo audit` + `bundle audit` |
118
+
119
+ ## Reproducing a Specific Claim
120
+
121
+ | Claim | Command |
122
+ | -------------------------------- | ----------------------------------------------------------------- |
123
+ | "80+ differential cases pass" | `bundle exec ruby test/differential_compatibility_test.rb` |
124
+ | "21 Rust unit tests pass" | `cd ext/dry_validation_rust && cargo test` |
125
+ | "MSRV build and tests pass" | `cargo +1.75.0 check --locked … && cargo +1.75.0 test --locked …` |
126
+ | "64 malformed inputs handled" | `bundle exec ruby test/malformed_input_test.rb` |
127
+ | "Package metadata is consistent" | `script/verify` (package audit step) |
128
+ | "RuboCop clean" | `bundle exec rubocop` |
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/dry/validation/rust/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'dry-validation-rust'
7
+ spec.version = Dry::Validation::Rust::VERSION
8
+ spec.authors = ['Alexey Tomilov']
9
+
10
+ spec.summary = 'Experimental Rust-backed validation contracts with a dry-validation-like API'
11
+ spec.description = <<~DESCRIPTION
12
+ A hybrid Ruby/Rust validation gem that compiles a documented subset of
13
+ dry-validation's declarative schema DSL into a native Rust execution plan
14
+ while retaining Ruby rule blocks and Ruby-owned dynamic behavior.
15
+ DESCRIPTION
16
+ spec.license = 'MIT'
17
+ spec.required_ruby_version = '>= 3.3'
18
+ spec.homepage = 'https://github.com/alex-tomilov/dry-validation-rust'
19
+
20
+ spec.files = [
21
+ 'CHANGELOG.md',
22
+ 'LICENSE',
23
+ 'NOTICE.md',
24
+ 'predicates.yml',
25
+ 'README.md',
26
+ 'dry-validation-rust.gemspec',
27
+ 'rust-toolchain.toml',
28
+ 'docs/ARCHITECTURE.md',
29
+ 'docs/COMPATIBILITY.md',
30
+ 'docs/FEASIBILITY.md',
31
+ 'docs/SUPPORT_MATRIX.md',
32
+ 'docs/VERIFICATION.md',
33
+ Dir['lib/**/*.rb'],
34
+ 'ext/dry_validation_rust/Cargo.lock',
35
+ 'ext/dry_validation_rust/Cargo.toml',
36
+ 'ext/dry_validation_rust/extconf.rb',
37
+ Dir['ext/dry_validation_rust/benches/**/*.rs'],
38
+ Dir['ext/dry_validation_rust/src/**/*.rs']
39
+ ].flatten.sort
40
+ spec.require_paths = ['lib']
41
+ spec.extensions = ['ext/dry_validation_rust/extconf.rb']
42
+ spec.add_dependency 'bigdecimal', '>= 3.1', '< 5.0'
43
+ spec.add_dependency 'rb_sys', '~> 0.9'
44
+ spec.add_development_dependency 'memory_profiler', '~> 1.1'
45
+ spec.add_development_dependency 'minitest', '~> 6.0'
46
+ spec.add_development_dependency 'mutex_m', '~> 0.2'
47
+ spec.add_development_dependency 'ostruct', '~> 0.6'
48
+ spec.add_development_dependency 'rake', '~> 13.1'
49
+ spec.add_development_dependency 'rake-compiler', '~> 1.3'
50
+ spec.add_development_dependency 'rake-compiler-dock', '~> 1.12'
51
+ spec.add_development_dependency 'yard', '~> 0.9'
52
+
53
+ spec.metadata['rubygems_mfa_required'] = 'true'
54
+ spec.metadata['source_code_uri'] = 'https://github.com/alex-tomilov/dry-validation-rust'
55
+ spec.metadata['changelog_uri'] = 'https://github.com/alex-tomilov/dry-validation-rust/blob/main/CHANGELOG.md'
56
+ spec.metadata['documentation_uri'] = 'https://github.com/alex-tomilov/dry-validation-rust/blob/main/README.md'
57
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/alex-tomilov/dry-validation-rust/issues'
58
+ end