Rustly 10.2.0
See the version list below for details.
dotnet add package Rustly --version 10.2.0
NuGet\Install-Package Rustly -Version 10.2.0
<PackageReference Include="Rustly" Version="10.2.0" />
<PackageVersion Include="Rustly" Version="10.2.0" />
<PackageReference Include="Rustly" />
paket add Rustly --version 10.2.0
#r "nuget: Rustly, 10.2.0"
#:package Rustly@10.2.0
#addin nuget:?package=Rustly&version=10.2.0
#tool nuget:?package=Rustly&version=10.2.0
Rustly (v10.2.0)
Rust-inspired Result<T, E>, Option<T>, Unit, and EnumValue types for C#.
Replace exceptions with explicit, composable error handling. Zero-allocation value types.
All types and helpers are auto-imported when you add the package -- no using statements needed.
Installation
dotnet add package Rustly --version 10.2.0
Types
| Type | Description |
|---|---|
Result<T, E> |
Success (Ok) or error (Err) -- discriminated union |
Option<T> |
Some(T) or None -- nullable alternative |
Unit |
Void replacement for Result<Unit, E> |
[EnumValue] |
Associate data with enum members (Rust-style variants) |
Usage
Option<T>
// Implicit conversion: T -> Some(T)
Option<int> age = 25; // Some(25)
Option<string> name = "Alice"; // Some("Alice")
// None via default
Option<int> empty = default; // None
Option<string> noName = default; // None
// Note: Option<object> cannot be assigned null directly -- use default
Option<object> obj = default; // None (correct)
// Option<object> obj = null; // compile error
// Explicit cast: Option<T> -> T (equivalent to Unwrap)
int value = (int)age; // 25
// Safe access
Option<string> FindUser(int id) =>
id == 1 ? Some("Admin") : None<string>();
string name = FindUser(1).UnwrapOr("Unknown");
// Chaining
var greeting = FindUser(1)
.Map(n => $"Hello, {n}!")
.UnwrapOr("Hello, stranger!");
// Filtering
var admin = FindUser(1).Filter(n => n == "Admin");
// Convert to Result
Result<string, string> r = FindUser(42).OkOr("User not found");
// Pattern matching (U is inferred from lambdas)
var message = FindUser(42).Match(
n => $"Found: {n}",
() => "Not found"
);
Result<T, E>
// Implicit conversion: T -> Ok(T)
Result<int, string> Divide(int a, int b) =>
b == 0 ? Err<int, string>("Division by zero") : a / b;
// Explicit cast: E -> Err(E)
Result<int, string> err = (Result<int, string>)"something went wrong";
// Explicit cast: Result<T, E> -> T (equivalent to Unwrap)
int value = (int)Divide(10, 2); // 5
// Pattern matching (U is inferred from lambdas)
string message = Divide(10, 0).Match(
value => $"Result: {value}",
error => $"Error: {error}"
);
// Chaining
var doubled = Divide(10, 2)
.Map(x => x * 2)
.UnwrapOr(0);
// Composition
var final = Divide(10, 2)
.AndThen(x => Divide(x, 3))
.MapErr(e => $"Pipeline failed: {e}");
// Querying
bool isPositive = Divide(10, 2).IsOkAnd(x => x > 0);
bool isBadInput = Divide(10, 0).ContainsErr("Division by zero");
Result<Unit, E> (void operations)
Result<Unit, string> SaveFile(string path)
{
// ... operation ...
return Unit.Value; // implicit Unit -> Ok
}
SaveFile("/tmp/data.txt")
.InspectErr(e => Console.WriteLine($"Save failed: {e}"));
Combining
// Zip two options
var pair = Some(1).Zip(Some("hello")); // Some((1, "hello"))
// Flatten nested types
Option<Option<int>> nested = Some(Some(42));
Option<int> flat = nested.Flatten(); // Some(42)
// Transpose
Option<Result<int, string>> optRes = Some(Ok<int, string>(42));
Result<Option<int>, string> resOpt = optRes.Transpose(); // Ok(Some(42))
// Xor
var a = Some(1);
var b = None<int>();
var x = a.Xor(b); // Some(1) -- exactly one is Some
EnumValue -- Rust-style Enum Variants
using Rustly.Extensions;
public enum LogLevel
{
[EnumValue("TRC")] Trace,
[EnumValue("DBG")] Debug,
[EnumValue("INF")] Info,
}
var label = LogLevel.Trace.Value<string>(); // "TRC"
var opt = LogLevel.Debug.ValueOption<string>(); // Some("DBG")
var raw = LogLevel.Info.RawValue(); // (object)"INF"
JSON Serialization
Option<T> and Result<T, E> work with System.Text.Json automatically (.NET 5+). No registration needed:
// Option<T> -- Some(x) serializes as x, None as null
JsonSerializer.Serialize(Some("hello")); // "hello"
JsonSerializer.Serialize(None<string>()); // null
JsonSerializer.Deserialize<Option<int>>("42"); // Some(42)
// Result<T, E> -- Ok(x) as {"ok": x}, Err(e) as {"err": e}
JsonSerializer.Serialize(Ok<int, string>(42)); // {"ok":42}
JsonSerializer.Serialize(Err<int, string>("fail")); // {"err":"fail"}
// Works inside other objects too
public record User(string Name, Option<string> Email);
JsonSerializer.Serialize(new User("Alice", "a@b.c")); // {"Name":"Alice","Email":"a@b.c"}
JsonSerializer.Serialize(new User("Bob", default)); // {"Name":"Bob","Email":null}
API Reference
Result<T, E>
| Method | Rust equivalent | Description |
|---|---|---|
Ok(T) / Err(E) |
Ok(v) / Err(e) |
Create result |
IsOk / IsErr |
is_ok() / is_err() |
Check variant |
IsOkAnd(f) / IsErrAnd(f) |
is_ok_and / is_err_and |
Check variant + predicate |
Contains(v) / ContainsErr(e) |
contains / contains_err |
Check if contains value |
Unwrap() / UnwrapErr() |
unwrap / unwrap_err |
Get value (unsafe) |
UnwrapOr(T) |
unwrap_or |
Get value or default |
UnwrapOrElse(Func) |
unwrap_or_else |
Get value or compute default |
Map(f) / MapErr(f) |
map / map_err |
Transform value/error |
MapOr(default, f) |
map_or |
Map with default fallback |
MapOrElse(default_f, f) |
map_or_else |
Map with lazy default |
AndThen(f) / And(res) |
and_then / and |
Chain on Ok |
OrElse(f) / Or(res) |
or_else / or |
Recover on Err |
Inspect(f) / InspectErr(f) |
inspect / inspect_err |
Side-effects |
Match(ok, err) |
match |
Pattern match |
Ok() / ToOption() |
ok() |
Ok->Some, Err->None |
Err() |
err() |
Err->Some, Ok->None |
implicit T->Result |
-- | Result<int,string> r = 42; |
explicit E->Result |
-- | var r = (Result<int,string>)"error"; |
.Flatten() (ext) |
flatten |
Unwrap nested Result |
.Transpose() (ext) |
transpose |
Result<Option> to Option<Result> |
Option<T>
| Method | Rust equivalent | Description |
|---|---|---|
Some(T) / None |
Some(v) / None |
Create option |
IsSome / IsNone |
is_some / is_none |
Check variant |
IsSomeAnd(f) |
is_some_and |
Check + predicate |
Contains(v) |
contains |
Check if contains value |
Unwrap() |
unwrap |
Get value (unsafe) |
UnwrapOr(T) / UnwrapOrElse(f) |
unwrap_or / unwrap_or_else |
Get or default |
Map(f) |
map |
Transform value |
MapOr(default, f) |
map_or |
Map with default |
MapOrElse(default_f, f) |
map_or_else |
Map with lazy default |
Filter(predicate) |
filter |
Keep Some only if matches |
AndThen(f) / And(opt) |
and_then / and |
Chain on Some |
Or(opt) / OrElse(f) |
or / or_else |
Fallback on None |
Xor(opt) |
xor |
Exactly one is Some |
Zip(opt) |
zip |
Combine two Options into tuple |
Inspect(f) |
inspect |
Side-effect on Some |
Match(some, none) |
match |
Pattern match |
OkOr(e) / OkOrElse(f) |
ok_or / ok_or_else |
Convert to Result |
implicit T->Option |
-- | Option<int> o = 42; |
explicit Option->T |
-- | int v = (int)o; |
.Flatten() (ext) |
flatten |
Unwrap nested Option |
.Transpose() (ext) |
transpose |
Option<Result> to Result<Option> |
.ZipWith(opt, f) (ext) |
zip_with |
Combine with function |
.Unzip() (ext) |
unzip |
Split Option<tuple> |
Prelude (auto-imported)
| Helper | Equivalent |
|---|---|
Ok<T, E>(value) |
Result<T, E>.Ok(value) |
Err<T, E>(error) |
Result<T, E>.Err(error) |
Some<T>(value) |
Option<T>.Some(value) |
None<T>() |
Option<T>.None |
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
-
net10.0
- No dependencies.
NuGet packages (5)
Showing the top 5 NuGet packages that depend on Rustly:
| Package | Downloads |
|---|---|
|
Slotly.Core
Core types for the Slotly plugin framework: IPlugin, IPluginManifest, PluginState, PluginError, IPluginContext. |
|
|
Rustly.Json
System.Text.Json converters for Rustly Option, Result, and EnumValue. Includes source generators for AOT-friendly serialization. Part of the Rustly ecosystem. |
|
|
Rustly.Json.Newtonsoft
Newtonsoft.Json converters for Rustly Option, Result, and EnumValue enums. Part of the Rustly ecosystem. |
|
|
Rustly.Configuration
IConfiguration binding for Rustly types. RBind() handles Option and EnumValue object format seamlessly. Part of the Rustly ecosystem. |
|
|
TunnelForge.Tun
Cross-platform TUN adapter abstraction for .NET. Unified ITunAdapter interface for Windows (WinTun) and Linux (/dev/net/tun). Error handling via Rustly Result<T, E> — no exceptions. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 10.6.4 | 817 | 4/28/2026 | |
| 10.6.3 | 230 | 4/16/2026 | |
| 10.6.2 | 236 | 4/16/2026 | |
| 10.6.2-rc6 | 255 | 4/16/2026 | |
| 10.6.2-rc5 | 299 | 4/15/2026 | |
| 10.6.1 | 169 | 4/15/2026 | |
| 10.5.0 | 217 | 4/15/2026 | |
| 10.4.0 | 232 | 4/15/2026 | |
| 10.3.1 | 227 | 4/14/2026 | |
| 10.2.1 | 665 | 4/14/2026 | |
| 10.2.0 | 1,233 | 4/13/2026 | |
| 10.1.1 | 127 | 4/13/2026 | |
| 10.1.0 | 139 | 4/13/2026 | |
| 10.0.3 | 131 | 4/13/2026 | |
| 10.0.2 | 235 | 4/8/2026 | |
| 10.0.1 | 130 | 4/8/2026 | |
| 10.0.0 | 128 | 4/8/2026 | |
| 10.0.0-rc2 | 119 | 4/8/2026 | |
| 10.0.0-rc | 124 | 4/8/2026 |
EN:
Version 10.2.0:
- Added OptionTypeConverter for native compatibility with Microsoft.Extensions.Configuration.Binder.
- Option<T> now works as a drop-in replacement for nullable types in configuration DTOs.
- Added [TypeConverter] attribute on Option<T> (auto-discovery by TypeDescriptor).
- Added [JsonConverter] attribute on Option<T> and Result<T, E> for System.Text.Json (auto, no registration).
- Added EnumValueAttribute for Rust-style enum variants with data.
RU:
Версия 10.2.0:
- Добавлен OptionTypeConverter для нативной совместимости с Microsoft.Extensions.Configuration.Binder.
- Option<T> теперь работает как замена nullable типов в конфигурационных DTO.
- Добавлен атрибут [TypeConverter] на Option<T> (автообнаружение через TypeDescriptor).
- Добавлен атрибут [JsonConverter] на Option<T> и Result<T, E> для System.Text.Json (автоматически, без регистрации).
- Добавлен EnumValueAttribute для Rust-style вариантов enum с данными.