diff --git a/.github/actions/versioning/extract-version/action.yml b/.github/actions/versioning/extract-version/action.yml index 40229ad8..ba604761 100644 --- a/.github/actions/versioning/extract-version/action.yml +++ b/.github/actions/versioning/extract-version/action.yml @@ -22,7 +22,7 @@ inputs: outputs: version: description: 'Version extracted from the branch name.' - value: ${{ steps.regex-match.outputs.match }} + value: ${{ steps.resolve-version.outputs.version }} runs: using: "composite" @@ -43,14 +43,9 @@ runs: regex: ${{ inputs.version-format }} flags: 'g' - - name: 'Set extracted version output' - if: steps.regex-match.outputs.match != '' + - name: 'Resolve version' + id: resolve-version shell: bash run: | - echo "version=${{ steps.regex-match.outputs.match }}" >> $GITHUB_OUTPUT - - - name: 'Set default version output' - if: steps.regex-match.outputs.match == '' - shell: bash - run: | - echo "version=${{ inputs.default-version }}" >> $GITHUB_OUTPUT + VERSION="${{ steps.regex-match.outputs.match }}" + echo "version=${VERSION:-${{ inputs.default-version }}}" >> $GITHUB_OUTPUT diff --git a/README.md b/README.md index b235ecaa..9dfb8a18 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,12 @@ Lightweight .NET Standard 2.1 library implementing Google-compliant Encoded Poly ## Features - Fully compliant Google Encoded Polyline Algorithm for .NET Standard 2.1+ -- Immutable, strongly-typed coordinate and polyline data structures -- Predefined encoder and decoder types for quick usage, extensibility for custom coordinate types +- Extensible encoding and decoding APIs for custom coordinate and polyline types (`IPolylineEncoder`, `IPolylineDecoder`, `AbstractPolylineEncoder`, `AbstractPolylineDecoder`) +- Extension methods for encoding from `List` and arrays (`PolylineEncoderExtensions`) - Robust input validation with descriptive exceptions for malformed/invalid data -- Simple, extensible encoding and decoding APIs (`IPolylineEncoder`, `IPolylineDecoder`, `AbstractPolylineEncoder`, `AbstractPolylineDecoder`) -- Default encoding and decoding implementations (`PolylineEncoder`, `PolylineDecoder`) -- Advanced configuration via `PolylineEncodingOptions` (buffer size, logging, etc.) -- Internal logging and diagnostic supports logging for CI/CD and developer diagnostics +- Advanced configuration via `PolylineEncodingOptions` (precision, buffer size, logging) +- Logging and diagnostic support for CI/CD and developer diagnostics via `Microsoft.Extensions.Logging` +- Low-level utilities for normalization, validation, encoding and decoding via static `PolylineEncoding` class - Thorough unit tests and benchmarks for correctness and performance - Auto-generated API documentation ([API Reference](https://petesramek.github.io/polyline-algorithm-csharp/)) - Support for .NET Core, .NET 5+, Xamarin, Unity, Blazor, and other platforms supporting `netstandard2.1` @@ -44,48 +43,23 @@ Install-Package PolylineAlgorithm ## Usage -### PolylineEncoder and PolylineDecoder (predefined `Coordinate` and `Polyline` types) +The library provides abstract base classes to implement your own encoder and decoder for any coordinate and polyline type. -#### Encoding - -```csharp -using PolylineAlgorithm; - -var coordinates = new List -{ - new Coordinate(48.858370, 2.294481), - new Coordinate(51.500729, -0.124625) -}; - -var encoder = new PolylineEncoder(); -Polyline encoded = encoder.Encode(coordinates); - -Console.WriteLine(encoded.ToString()); -``` - -#### Decoding - -```csharp -using PolylineAlgorithm; - -Polyline polyline = Polyline.FromString("yseiHoc_MwacOjnwM"); - -var decoder = new PolylineDecoder(); -IEnumerable decoded = decoder.Decode(polyline); -``` - -### Custom encoder and decoder (user-defined coordinate and polyline types) +### Custom encoder and decoder #### Encoding Custom encoder implementation. ```csharp +using PolylineAlgorithm; +using PolylineAlgorithm.Abstraction; + public sealed class MyPolylineEncoder : AbstractPolylineEncoder<(double Latitude, double Longitude), string> { - public PolylineEncoder() + public MyPolylineEncoder() : base() { } - public PolylineEncoder(PolylineEncodingOptions options) + public MyPolylineEncoder(PolylineEncodingOptions options) : base(options) { } protected override double GetLatitude((double Latitude, double Longitude) coordinate) { @@ -105,7 +79,7 @@ public sealed class MyPolylineEncoder : AbstractPolylineEncoder<(double Latitude Custom encoder usage. ```csharp -using PolylineAlgorithm; +using PolylineAlgorithm.Extensions; var coordinates = new List<(double Latitude, double Longitude)> { @@ -114,9 +88,9 @@ var coordinates = new List<(double Latitude, double Longitude)> }; var encoder = new MyPolylineEncoder(); -string encoded = encoder.Encode(coordinates); +string encoded = encoder.Encode(coordinates); // extension method for List -Console.WriteLine(encoded.ToString()); +Console.WriteLine(encoded); ``` #### Decoding @@ -124,18 +98,21 @@ Console.WriteLine(encoded.ToString()); Custom decoder implementation. ```csharp +using PolylineAlgorithm; +using PolylineAlgorithm.Abstraction; + public sealed class MyPolylineDecoder : AbstractPolylineDecoder { - public PolylineDecoder() + public MyPolylineDecoder() : base() { } - public PolylineDecoder(PolylineEncodingOptions options) + public MyPolylineDecoder(PolylineEncodingOptions options) : base(options) { } protected override (double Latitude, double Longitude) CreateCoordinate(double latitude, double longitude) { return (latitude, longitude); } - protected override ReadOnlyMemory GetReadOnlyMemory(ref string polyline) { + protected override ReadOnlyMemory GetReadOnlyMemory(in string polyline) { return polyline.AsMemory(); } } @@ -144,8 +121,6 @@ public sealed class MyPolylineDecoder : AbstractPolylineDecoder`, `AbstractPolylineDecoder`) +- Extension methods for encoding from `List` and arrays (`PolylineEncoderExtensions`) - Robust input validation and descriptive exceptions -- Configurable with `PolylineEncodingOptions` (buffer, logging, etc.) +- Configurable with `PolylineEncodingOptions` (precision, buffer size, logging) - Thread-safe, stateless APIs +- Low-level utilities via static `PolylineEncoding` class (Normalize, Denormalize, TryReadValue, TryWriteValue, ValidateFormat, etc.) - Benchmarks and unit tests for correctness and performance - Auto-generated API docs ([API Reference](https://petesramek.github.io/polyline-algorithm-csharp/)) - Supports .NET Core, .NET 5+, Xamarin, Unity, Blazor via `netstandard2.1` @@ -29,37 +29,63 @@ Install-Package PolylineAlgorithm ## Quick Start -### Encode coordinates +The library provides abstract base classes to build your own encoder and decoder for any coordinate and polyline type. + +### Implement a custom encoder ```csharp using PolylineAlgorithm; +using PolylineAlgorithm.Abstraction; + +public sealed class MyPolylineEncoder : AbstractPolylineEncoder<(double Latitude, double Longitude), string> { + protected override double GetLatitude((double Latitude, double Longitude) coordinate) => coordinate.Latitude; + protected override double GetLongitude((double Latitude, double Longitude) coordinate) => coordinate.Longitude; + protected override string CreatePolyline(ReadOnlyMemory polyline) => polyline.ToString(); +} +``` + +### Encode coordinates + +```csharp +using PolylineAlgorithm.Extensions; -var coordinates = new List +var coordinates = new List<(double Latitude, double Longitude)> { - new Coordinate(48.858370, 2.294481), - new Coordinate(51.500729, -0.124625) + (48.858370, 2.294481), + (51.500729, -0.124625) }; -var encoder = new PolylineEncoder(); -Polyline encoded = encoder.Encode(coordinates); +var encoder = new MyPolylineEncoder(); +string encoded = encoder.Encode(coordinates); // extension method for List -Console.WriteLine(encoded.ToString()); // Print encoded polyline string +Console.WriteLine(encoded); ``` -### Decode polyline +### Implement a custom decoder ```csharp using PolylineAlgorithm; +using PolylineAlgorithm.Abstraction; + +public sealed class MyPolylineDecoder : AbstractPolylineDecoder { + protected override (double Latitude, double Longitude) CreateCoordinate(double latitude, double longitude) => (latitude, longitude); + protected override ReadOnlyMemory GetReadOnlyMemory(in string polyline) => polyline.AsMemory(); +} +``` + +### Decode polyline + +```csharp +string encoded = "yseiHoc_MwacOjnwM"; -var decoder = new PolylineDecoder(); -Polyline polyline = Polyline.FromString("yseiHoc_MwacOjnwM"); -IEnumerable decoded = decoder.Decode(polyline); +var decoder = new MyPolylineDecoder(); +IEnumerable<(double Latitude, double Longitude)> decoded = decoder.Decode(encoded); ``` ## Advanced Usage -- Custom coordinate/polyline types are supported via `AbstractPolylineEncoder` and `AbstractPolylineDecoder`. -- Additional configuration via `PolylineEncodingOptionsBuilder`. +- Pass a `PolylineEncodingOptions` (built via `PolylineEncodingOptionsBuilder`) to the encoder/decoder constructor for custom precision, stack-alloc limit, and logging. +- Use static methods on `PolylineEncoding` for low-level normalization, validation, and bit-level read/write operations. > See [API Reference](https://petesramek.github.io/polyline-algorithm-csharp/) for full documentation. @@ -70,7 +96,7 @@ IEnumerable decoded = decoder.Decode(polyline); - **What .NET versions are supported?** Any environment supporting `netstandard2.1` - **How do I customize encoder options?** - Use `PolylineEncodingOptionsBuilder` and pass to the encoder constructor. + Use `PolylineEncodingOptionsBuilder` and pass the built options to the encoder or decoder constructor. - **Where can I get help?** [GitHub issues](https://github.com/petesramek/polyline-algorithm-csharp/issues)