documentation update
This commit is contained in:
@@ -1,20 +1,42 @@
|
|||||||
namespace Just.Core;
|
namespace Just.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encoding options for <see cref="Base32.Encode(ReadOnlySpan{byte}, Base32EncodeOptions)"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
public enum Base32EncodeOptions
|
public enum Base32EncodeOptions
|
||||||
{
|
{
|
||||||
|
/// <summary>Standard RFC 4648 encoding (uppercase with padding).</summary>
|
||||||
None = 0x00,
|
None = 0x00,
|
||||||
|
/// <summary>Use lowercase alphabet.</summary>
|
||||||
LowerCase = 0x01,
|
LowerCase = 0x01,
|
||||||
|
/// <summary>Omit padding characters.</summary>
|
||||||
NoPadding = 0x02,
|
NoPadding = 0x02,
|
||||||
|
/// <summary>Lowercase alphabet without padding (combines <see cref="LowerCase"/> | <see cref="NoPadding"/>).</summary>
|
||||||
LowerCaseNoPadding = 0x03,
|
LowerCaseNoPadding = 0x03,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RFC 4648 Base32 encoder/decoder with span-based APIs.
|
||||||
|
/// Uses stack allocation for inputs up to <see cref="MaxBytesStack"/> bytes; heap allocation otherwise.
|
||||||
|
/// </summary>
|
||||||
public static class Base32
|
public static class Base32
|
||||||
{
|
{
|
||||||
|
/// <summary>RFC 4648 Base32 alphabet (uppercase A-Z, 2-7).</summary>
|
||||||
public const string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
public const string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||||
|
/// <summary>Lowercase variant of the RFC 4648 alphabet.</summary>
|
||||||
public const string AlphabetLower = "abcdefghijklmnopqrstuvwxyz234567";
|
public const string AlphabetLower = "abcdefghijklmnopqrstuvwxyz234567";
|
||||||
|
/// <summary>Padding character (=).</summary>
|
||||||
public const char Padding = '=';
|
public const char Padding = '=';
|
||||||
|
/// <summary>Maximum input byte count that uses stack allocation instead of heap.</summary>
|
||||||
public const int MaxBytesStack = 250;
|
public const int MaxBytesStack = 250;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encodes a byte span into a Base32 string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The bytes to encode.</param>
|
||||||
|
/// <param name="options">Encoding options (casing, padding). Defaults to standard RFC 4648.</param>
|
||||||
|
/// <returns>The Base32-encoded string.</returns>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static string Encode(ReadOnlySpan<byte> input, Base32EncodeOptions options = Base32EncodeOptions.None)
|
public static string Encode(ReadOnlySpan<byte> input, Base32EncodeOptions options = Base32EncodeOptions.None)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,10 +2,15 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace Just.Core;
|
namespace Just.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// URL-safe Base64 encoder/decoder for bytes, <see cref="long"/>, and <see cref="Guid"/>.
|
||||||
|
/// Uses the standard Base64Url character set (- and _ instead of + and /), padding stripped by default.
|
||||||
|
/// </summary>
|
||||||
public static class Base64Url
|
public static class Base64Url
|
||||||
{
|
{
|
||||||
private const char Padding = '=';
|
private const char Padding = '=';
|
||||||
|
|
||||||
|
/// <summary>Decodes an 11-character Base64Url string into a <see cref="long"/>.</summary>
|
||||||
[Pure] public static long DecodeLong(ReadOnlySpan<char> value)
|
[Pure] public static long DecodeLong(ReadOnlySpan<char> value)
|
||||||
{
|
{
|
||||||
ArgumentOutOfRangeException.ThrowIfNotEqual(value.Length, 11);
|
ArgumentOutOfRangeException.ThrowIfNotEqual(value.Length, 11);
|
||||||
@@ -24,6 +29,7 @@ public static class Base64Url
|
|||||||
return MemoryMarshal.Read<long>(longBytes);
|
return MemoryMarshal.Read<long>(longBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Decodes a 22-character Base64Url string into a <see cref="Guid"/>.</summary>
|
||||||
[Pure] public static Guid DecodeGuid(ReadOnlySpan<char> value)
|
[Pure] public static Guid DecodeGuid(ReadOnlySpan<char> value)
|
||||||
{
|
{
|
||||||
ArgumentOutOfRangeException.ThrowIfNotEqual(value.Length, 22);
|
ArgumentOutOfRangeException.ThrowIfNotEqual(value.Length, 22);
|
||||||
@@ -42,6 +48,7 @@ public static class Base64Url
|
|||||||
return new Guid(guidBytes);
|
return new Guid(guidBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Decodes a Base64Url string into a byte array.</summary>
|
||||||
[Pure] public static byte[] Decode(ReadOnlySpan<char> input)
|
[Pure] public static byte[] Decode(ReadOnlySpan<char> input)
|
||||||
{
|
{
|
||||||
if (input.IsEmpty) return [];
|
if (input.IsEmpty) return [];
|
||||||
@@ -53,6 +60,7 @@ public static class Base64Url
|
|||||||
return output[..size].ToArray();
|
return output[..size].ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Decodes a Base64Url string into a pre-allocated byte span. Returns the number of bytes written.</summary>
|
||||||
[Pure] public static int Decode(ReadOnlySpan<char> value, Span<byte> output)
|
[Pure] public static int Decode(ReadOnlySpan<char> value, Span<byte> output)
|
||||||
{
|
{
|
||||||
var padding = (4 - (value.Length & 3)) & 3;
|
var padding = (4 - (value.Length & 3)) & 3;
|
||||||
@@ -72,6 +80,7 @@ public static class Base64Url
|
|||||||
return outputBytes;
|
return outputBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Encodes a <see cref="long"/> into an 11-character Base64Url string.</summary>
|
||||||
[Pure] public static string Encode(in long id)
|
[Pure] public static string Encode(in long id)
|
||||||
{
|
{
|
||||||
Span<byte> longBytes = stackalloc byte[8];
|
Span<byte> longBytes = stackalloc byte[8];
|
||||||
@@ -84,6 +93,7 @@ public static class Base64Url
|
|||||||
return new string(chars[..^1]);
|
return new string(chars[..^1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Encodes a <see cref="Guid"/> into a 22-character Base64Url string.</summary>
|
||||||
[Pure] public static string Encode(in Guid id)
|
[Pure] public static string Encode(in Guid id)
|
||||||
{
|
{
|
||||||
Span<byte> guidBytes = stackalloc byte[16];
|
Span<byte> guidBytes = stackalloc byte[16];
|
||||||
@@ -96,6 +106,7 @@ public static class Base64Url
|
|||||||
return new string(chars[..^2]);
|
return new string(chars[..^2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Encodes a byte span into a Base64Url string.</summary>
|
||||||
[Pure] public static string Encode(ReadOnlySpan<byte> input)
|
[Pure] public static string Encode(ReadOnlySpan<byte> input)
|
||||||
{
|
{
|
||||||
if (input.IsEmpty) return string.Empty;
|
if (input.IsEmpty) return string.Empty;
|
||||||
@@ -107,6 +118,7 @@ public static class Base64Url
|
|||||||
return new string(output[..strlen]);
|
return new string(output[..strlen]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Encodes a byte span into a pre-allocated char span. Returns the number of characters written.</summary>
|
||||||
[Pure] public static int Encode(ReadOnlySpan<byte> input, Span<char> output)
|
[Pure] public static int Encode(ReadOnlySpan<byte> input, Span<char> output)
|
||||||
{
|
{
|
||||||
if (input.IsEmpty) return 0;
|
if (input.IsEmpty) return 0;
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace Just.Core.Collections;
|
namespace Just.Core.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A 2D grid with lazy min/max caching, cloning, and binary stream serialization.
|
||||||
|
/// Requires <typeparamref name="T"/> to support comparison and equality operators.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The element type; must implement <c>IComparisonOperators<T, T, bool></c> and <c>IEqualityOperators<T, T, bool></c>.</typeparam>
|
||||||
public class DataMap<T> : Map<T>, IDataMap<T>, ICloneable
|
public class DataMap<T> : Map<T>, IDataMap<T>, ICloneable
|
||||||
where T : IComparisonOperators<T, T, bool>, IEqualityOperators<T, T, bool>
|
where T : IComparisonOperators<T, T, bool>, IEqualityOperators<T, T, bool>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ using System.Numerics;
|
|||||||
|
|
||||||
namespace Just.Core.Collections;
|
namespace Just.Core.Collections;
|
||||||
|
|
||||||
|
/// <summary>Read-only interface for a 2D grid with min/max tracking and cloning.</summary>
|
||||||
|
/// <typeparam name="T">The element type; must support comparison and equality operators.</typeparam>
|
||||||
public interface IDataMap<T> : IMap<T>, ICloneable
|
public interface IDataMap<T> : IMap<T>, ICloneable
|
||||||
where T : IComparisonOperators<T, T, bool>, IEqualityOperators<T, T, bool>
|
where T : IComparisonOperators<T, T, bool>, IEqualityOperators<T, T, bool>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
namespace Just.Core.Collections;
|
namespace Just.Core.Collections;
|
||||||
|
|
||||||
|
/// <summary>Read-only interface for a 2D grid with coordinate-based access and enumeration.</summary>
|
||||||
|
/// <typeparam name="T">The type of elements in the map.</typeparam>
|
||||||
public interface IMap<T> : IReadOnlyCollection<MapPoint<T>>
|
public interface IMap<T> : IReadOnlyCollection<MapPoint<T>>
|
||||||
{
|
{
|
||||||
int Width { get; }
|
int Width { get; }
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ using System.Collections;
|
|||||||
|
|
||||||
namespace Just.Core.Collections;
|
namespace Just.Core.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A 2D grid container providing indexer access, enumeration as <see cref="MapPoint{T}"/> values,
|
||||||
|
/// and conversion to a 2D array. Coordinates are clamped to valid ranges.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of elements in the map.</typeparam>
|
||||||
public class Map<T> : IMap<T>
|
public class Map<T> : IMap<T>
|
||||||
{
|
{
|
||||||
internal readonly T[] _values;
|
internal readonly T[] _values;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
namespace Just.Core.Collections;
|
namespace Just.Core.Collections;
|
||||||
|
|
||||||
|
/// <summary>A value and its coordinates within a <see cref="IMap{T}"/>.</summary>
|
||||||
|
/// <typeparam name="T">The type of the map element.</typeparam>
|
||||||
public readonly struct MapPoint<T>(T value, int x, int y, IMap<T> map)
|
public readonly struct MapPoint<T>(T value, int x, int y, IMap<T> map)
|
||||||
{
|
{
|
||||||
public readonly T Value = value;
|
public readonly T Value = value;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AssemblyName>Just.Core</AssemblyName>
|
<AssemblyName>Just.Core</AssemblyName>
|
||||||
<RootNamespace>Just.Core</RootNamespace>
|
<RootNamespace>Just.Core</RootNamespace>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
|
||||||
<Description>Small .Net library with useful helper classes, functions and extensions.</Description>
|
<Description>Small .Net library with useful helper classes, functions and extensions.</Description>
|
||||||
<PackageTags>extensions;helpers;helper-functions</PackageTags>
|
<PackageTags>extensions;helpers;helper-functions</PackageTags>
|
||||||
|
|||||||
@@ -1,18 +1,92 @@
|
|||||||
# .Net library with helpers, functions and extensions
|
# Just.Core
|
||||||
|
|
||||||
Just some stuff that is used in different projects...
|
Small .NET library with useful helper classes, functions, and extensions — stuff used across multiple projects.
|
||||||
|
|
||||||
|
[](https://www.nuget.org/packages/Just.Core)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dotnet add package Just.Core
|
||||||
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- ```Map``` and ```DataMap``` collection types
|
### Encoding
|
||||||
- Extensions for ```System.String``` and ```System.IO.Stream```
|
|
||||||
- Small converters for **Base32** and **Base64Url** encodings
|
|
||||||
|
|
||||||
## Getting Started
|
**Base32** — RFC 4648 encoder/decoder with lowercase and no-padding options.
|
||||||
|
|
||||||
### Install from NuGet.org
|
```csharp
|
||||||
|
var encoded = Base32.Encode(bytes); // "ABCDEFGH..."
|
||||||
```sh
|
var encoded = Base32.Encode(bytes, Base32EncodeOptions.LowerCaseNoPadding);
|
||||||
# install the package using NuGet
|
var bytes = Base32.Decode("ABCDEFGH...");
|
||||||
dotnet add package Just.Core
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Base64Url** — URL-safe Base64 for bytes, `long`, and `Guid`.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var str = Base64Url.Encode(myGuid); // "5QrdUxDUVkCAEGw8pvLsEw"
|
||||||
|
var guid = Base64Url.DecodeGuid(str);
|
||||||
|
var str = Base64Url.Encode(123456789L); // "7NcVAAAAAA"
|
||||||
|
var val = Base64Url.DecodeLong(str);
|
||||||
|
```
|
||||||
|
|
||||||
|
### IDs
|
||||||
|
|
||||||
|
**SeqId** — Time-based 64-bit sequential ID with configurable entropy. Thread-safe.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var id = SeqId.NextId(); // default instance, Strong entropy
|
||||||
|
var id = SeqId.NextId(RngEntropy.Weak); // faster, less collision-resistant
|
||||||
|
|
||||||
|
// Custom epoch
|
||||||
|
var generator = new SeqId(new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
var id = generator.Next();
|
||||||
|
```
|
||||||
|
|
||||||
|
Structure: `[1 bit reserved][41 bits ms since epoch][8 bits sequence][14 bits random]`
|
||||||
|
|
||||||
|
**GuidV8** — Time-sortable UUID v8 with extractable timestamp.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var guid = GuidV8.NewGuid(); // current UTC, Strong entropy
|
||||||
|
var guid = GuidV8.NewGuid(specificTime);
|
||||||
|
var when = GuidV8.ExtractTimestamp(guid); // recover timestamp (100µs precision)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collections
|
||||||
|
|
||||||
|
**Map<T> / DataMap<T>** — 2D grid container with indexing, enumeration, and min/max.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var map = new Map<int>(width: 10, height: 10, values);
|
||||||
|
var value = map[3, 5]; // integer or double coordinates
|
||||||
|
var point = map.Get(3.5, 5.2); // MapPoint<T> with position metadata
|
||||||
|
|
||||||
|
var dmap = new DataMap<double>(values, 10, 10);
|
||||||
|
var min = dmap.Min; // MapPoint<double> — cached
|
||||||
|
var max = dmap.Max; // lazy, thread-safe on first access
|
||||||
|
|
||||||
|
// Stream serialization (sync + async)
|
||||||
|
dmap.WriteToStream(stream);
|
||||||
|
var copy = DataMap.ReadFromStream<double>(stream);
|
||||||
|
```
|
||||||
|
|
||||||
|
**ImmutableSequence<T>** — Immutable list with structural value equality.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var seq = new ImmutableSequence<int>([1, 2, 3]);
|
||||||
|
var seq2 = seq.Add(4); // new instance, seq unchanged
|
||||||
|
seq == seq2; // false — 3 vs 4 elements
|
||||||
|
new ImmutableSequence<int>([1, 2, 3]) == seq; // true — value equality
|
||||||
|
```
|
||||||
|
|
||||||
|
## Supported Targets
|
||||||
|
|
||||||
|
- .NET 8.0 (LTS)
|
||||||
|
- .NET 9.0
|
||||||
|
- .NET 10.0
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT — see [LICENSE](LICENSE).
|
||||||
|
|||||||
Reference in New Issue
Block a user