{"id":31933007,"url":"https://github.com/dusrdev/verifast","last_synced_at":"2026-01-20T17:31:58.927Z","repository":{"id":315221335,"uuid":"1056710250","full_name":"dusrdev/Verifast","owner":"dusrdev","description":"High performance validation library for .NET","archived":false,"fork":false,"pushed_at":"2025-09-17T10:09:13.000Z","size":69,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"stable","last_synced_at":"2025-10-03T22:46:10.365Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dusrdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-14T16:44:35.000Z","updated_at":"2025-09-17T10:09:17.000Z","dependencies_parsed_at":"2025-09-17T11:44:24.327Z","dependency_job_id":"2ec25807-4e66-4645-a723-6cddda06082a","html_url":"https://github.com/dusrdev/Verifast","commit_stats":null,"previous_names":["dusrdev/verifast"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dusrdev/Verifast","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dusrdev%2FVerifast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dusrdev%2FVerifast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dusrdev%2FVerifast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dusrdev%2FVerifast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dusrdev","download_url":"https://codeload.github.com/dusrdev/Verifast/tar.gz/refs/heads/stable","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dusrdev%2FVerifast/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018014,"owners_count":26086237,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-14T05:49:23.678Z","updated_at":"2026-01-20T17:31:58.910Z","avatar_url":"https://github.com/dusrdev.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Verifast\n\n[![NuGet](https://img.shields.io/nuget/v/Verifast.svg?style=flat-square)](https://www.nuget.org/packages/Verifast)\n[![NuGet Downloads](https://img.shields.io/nuget/dt/Verifast?style=flat\u0026label=Downloads)](https://www.nuget.org/packages/Verifast)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)\n[![.NET](https://img.shields.io/badge/.NET-net9.0%20%7C%20netstandard2.1%20%7C%20netstandard2.0-512BD4?style=flat-square)](#)\n\nHigh‑performance, allocation‑friendly validation for .NET 9 and netstandard (2.1/2.0). No complicated APIs, no expression trees - just plain C#. Implement a tiny interface, add errors or warnings, and you’re done.\n\n## Why Verifast\n\n- Minimal API: implement `IValidator\u003cT\u003e` or `IAsyncValidator\u003cT\u003e` and write ordinary C#.\n- Fast by design: struct based `ValidationResult\u003cTMessage\u003e` allocates only when you add messages.\n- Ergonomic helpers: call `.Validate(...)` for a result or `.TryValidate(...)` for a quick bool.\n- Plays well with `ref struct`: APIs are designed to enable stack‑only scenarios.\n- Your messages, your way: use `string` or a custom `TMessage` for richer metadata.\n\n## Benchmarks\n\n[BenchmarkDotNet](https://benchmarkdotnet.org/) results comparing `Verifast` to [FluentValidation](https://github.com/FluentValidation/FluentValidation) (baseline, industry standard). Full report: [BenchmarkRun-joined.md](benchmarks/Verifast.Benchmarks/BenchmarkRun-joined.md).\n\n| Type            | Method           | ValidDto | Mean        | Ratio           | Allocated | Alloc Ratio   |\n|---------------- |----------------- |--------- |------------:|----------------:|----------:|--------------:|\n| AsyncValidation | FluentValidation | False    | 10,935.2 ns |        baseline |   14104 B |               |\n| AsyncValidation | Verifast         | False    |  2,203.2 ns |    4.96x faster |    1096 B |   12.87x less |\n| AsyncValidation | FluentValidation | True     |  8,470.8 ns |        baseline |    9808 B |               |\n| AsyncValidation | Verifast         | True     |  2,101.9 ns |    5.20x faster |    1016 B |   13.88x less |\n|                 |                  |          |             |                 |           |               |\n| SyncValidation  | FluentValidation | False    | 35,687.7 ns |        baseline |   63112 B |               |\n| SyncValidation  | Verifast         | False    |    141.4 ns | 252.377x faster |     328 B | 192.415x less |\n| SyncValidation  | FluentValidation | True     | 26,091.2 ns |        baseline |   50063 B |               |\n| SyncValidation  | Verifast         | True     |    112.3 ns | 320.264x faster |         - |            NA |\n\n## Install\n\n```bash\ndotnet add package Verifast\n```\n\n## Quick Start\n\nDefine your model and implement its validator. Then call the extension helpers.\n\n```csharp\nusing Verifast;\n\npublic readonly record struct User(string? Name, int Age);\n\npublic readonly struct UserValidator : IValidator\u003cUser\u003e {\n    public void Validate(in User instance, ref ValidationResult\u003cstring\u003e result) {\n        if (string.IsNullOrWhiteSpace(instance.Name))\n            result.AddError(\"'Name' must be non-empty\");\n        if (instance.Age is \u003c 18 or \u003e 120)\n            result.AddError(\"'Age' must be between 18 and 120\");\n    }\n}\n\nvar user = new User(\"Ada\", 33);\nvar validator = new UserValidator();\nvar result = validator.Validate(user);\nif (!result.IsValid)\n    foreach (var error in result.Errors) Console.WriteLine(error);\n```\n\nOr get a simple pass/fail while still capturing details:\n\n```csharp\nif (!validator.TryValidate(user, out var result))\n    foreach (var error in result.Errors) Console.WriteLine(error);\n```\n\n## Async Validation\n\nPrefer async? Implement `IAsyncValidator\u003cT\u003e` and return a `ValueTask\u003cValidationResult\u003cTMessage\u003e\u003e`.\n\n```csharp\npublic record AsyncUser(string? Email);\n\npublic sealed class AsyncUserValidator : IAsyncValidator\u003cAsyncUser\u003e {\n    public async ValueTask\u003cValidationResult\u003cstring\u003e\u003e ValidateAsync(AsyncUser instance, CancellationToken ct = default) {\n        await Task.Yield(); // e.g., call a store or service\n\n        ValidationResult\u003cstring\u003e result = default;\n        if (!string.IsNullOrWhiteSpace(instance.Email))\n            if (!LooksLikeEmail(instance.Email!))\n                result.AddError(\"'Email' must be a valid email\");\n\n        return result;\n\n        static bool LooksLikeEmail(string s) {\n            int at = s.IndexOf('@');\n            if (at \u003c= 0 || at \u003e= s.Length - 1) return false;\n            int dot = s.IndexOf('.', at + 1);\n            if (dot \u003c= at + 1 || dot \u003e= s.Length - 1) return false;\n            return true;\n        }\n    }\n}\n```\n\n## Custom Message Types\n\nAvoid string allocations or carry structured metadata by choosing your own `TMessage`.\n\n```csharp\nusing Verifast;\n\npublic readonly record struct Msg(string Code, string Text);\n\npublic readonly struct EvenValidator : IValidator\u003cint, Msg\u003e {\n    public void Validate(in int value, ref ValidationResult\u003cMsg\u003e result) {\n        if ((value \u0026 1) != 0)\n            result.AddError(new Msg(\"NotEven\", \"Value must be even\"));\n    }\n}\n\nif (!new EvenValidator().TryValidate(3, out var res))\n    foreach (var e in res.Errors) Console.WriteLine($\"{e.Code}: {e.Text}\");\n```\n\n## Design Philosophy\n\n- Pure language constructs: write straightforward `if`/`for` statements - no fluent builders, no new mental model, onboarding takes minutes.\n- Allocation‑aware: messages are captured on demand; zero allocations when data is valid.\n\n## License\n\nMIT - see `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdusrdev%2Fverifast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdusrdev%2Fverifast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdusrdev%2Fverifast/lists"}