diff --git a/.editorconfig b/.editorconfig
index 2e3045fb..f579ff5d 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -104,8 +104,8 @@ dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:war
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion
# Expression-level preferences
-dotnet_style_object_initializer = true:warning
-dotnet_style_collection_initializer = true:warning
+dotnet_style_object_initializer = true:error
+dotnet_style_collection_initializer = true:error
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_prefer_inferred_tuple_names = true:warning
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
@@ -135,9 +135,9 @@ csharp_style_prefer_null_check_over_type_check = true:warning
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules
[*.{cs,csx,cake}]
# 'var' preferences
-csharp_style_var_for_built_in_types = false:warning
-csharp_style_var_when_type_is_apparent = false:warning
-csharp_style_var_elsewhere = false:warning
+csharp_style_var_for_built_in_types = false:error
+csharp_style_var_when_type_is_apparent = false:error
+csharp_style_var_elsewhere = false:error
# Expression-bodied members
csharp_style_expression_bodied_methods = true:warning
csharp_style_expression_bodied_constructors = true:warning
@@ -160,7 +160,10 @@ csharp_style_pattern_local_over_anonymous_function = true:warning
csharp_style_deconstructed_variable_declaration = true:warning
csharp_style_prefer_index_operator = true:warning
csharp_style_prefer_range_operator = true:warning
-csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
+csharp_style_implicit_object_creation_when_type_is_apparent = true:error
+# ReSharper inspection severities
+resharper_arrange_object_creation_when_type_evident_highlighting = error
+resharper_arrange_object_creation_when_type_not_evident_highlighting = error
# "Null" checking preferences
csharp_style_throw_expression = true:warning
csharp_style_conditional_delegate_call = true:warning
@@ -172,6 +175,11 @@ dotnet_diagnostic.IDE0063.severity = suggestion
csharp_using_directive_placement = outside_namespace:warning
# Modifier preferences
csharp_prefer_static_local_function = true:warning
+# Primary constructor preferences
+csharp_style_prefer_primary_constructors = false:none
+# Collection preferences
+dotnet_style_prefer_collection_expression = true:error
+resharper_use_collection_expression_highlighting =true:error
##########################################
# Unnecessary Code Rules
diff --git a/.gitattributes b/.gitattributes
index ff4ec940..7de2c159 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -85,18 +85,12 @@
###############################################################################
*.basis binary
*.dll binary
-*.eot binary
*.exe binary
-*.otf binary
*.pdf binary
*.ppt binary
*.pptx binary
*.pvr binary
*.snk binary
-*.ttc binary
-*.ttf binary
-*.woff binary
-*.woff2 binary
*.xls binary
*.xlsx binary
###############################################################################
@@ -118,6 +112,7 @@
*.bmp filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
+*.qoi filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.tiff filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
@@ -125,6 +120,7 @@
*.dds filter=lfs diff=lfs merge=lfs -text
*.ktx filter=lfs diff=lfs merge=lfs -text
*.ktx2 filter=lfs diff=lfs merge=lfs -text
+*.astc filter=lfs diff=lfs merge=lfs -text
*.pam filter=lfs diff=lfs merge=lfs -text
*.pbm filter=lfs diff=lfs merge=lfs -text
*.pgm filter=lfs diff=lfs merge=lfs -text
@@ -132,3 +128,22 @@
*.pnm filter=lfs diff=lfs merge=lfs -text
*.wbmp filter=lfs diff=lfs merge=lfs -text
*.exr filter=lfs diff=lfs merge=lfs -text
+*.ico filter=lfs diff=lfs merge=lfs -text
+*.cur filter=lfs diff=lfs merge=lfs -text
+*.ani filter=lfs diff=lfs merge=lfs -text
+*.heic filter=lfs diff=lfs merge=lfs -text
+*.hif filter=lfs diff=lfs merge=lfs -text
+*.avif filter=lfs diff=lfs merge=lfs -text
+###############################################################################
+# Handle ICC files by git lfs
+###############################################################################
+*.icc filter=lfs diff=lfs merge=lfs -text
+###############################################################################
+# Handle font files by git lfs
+###############################################################################
+*.eot filter=lfs diff=lfs merge=lfs -text
+*.otf filter=lfs diff=lfs merge=lfs -text
+*.ttc filter=lfs diff=lfs merge=lfs -text
+*.ttf filter=lfs diff=lfs merge=lfs -text
+*.woff filter=lfs diff=lfs merge=lfs -text
+*.woff2 filter=lfs diff=lfs merge=lfs -text
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index d323d270..7f4f9078 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -4,42 +4,90 @@ on:
push:
branches:
- main
+ - release/*
tags:
- "v*"
pull_request:
branches:
- main
+ - release/*
+ types: [ opened, synchronize, reopened ]
jobs:
+ # Prime a single LFS cache and expose the exact key for the matrix
+ WarmLFS:
+ runs-on: ubuntu-latest
+ outputs:
+ lfs_key: ${{ steps.expose-key.outputs.lfs_key }}
+ steps:
+ - name: Git Config
+ shell: bash
+ run: |
+ git config --global core.autocrlf false
+ git config --global core.longpaths true
+
+ - name: Git Checkout
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+ submodules: recursive
+
+ # Deterministic list of LFS object IDs, then compute a portable key:
+ # - `git lfs ls-files -l` lists all tracked LFS objects with their SHA-256
+ # - `awk '{print $1}'` extracts just the SHA field
+ # - `sort` sorts in byte order (hex hashes sort the same everywhere)
+ # This ensures the file content is identical regardless of OS or locale
+ - name: Git Create LFS id list
+ shell: bash
+ run: git lfs ls-files -l | awk '{print $1}' | sort > .lfs-assets-id
+
+ - name: Git Expose LFS cache key
+ id: expose-key
+ shell: bash
+ env:
+ LFS_KEY: lfs-${{ hashFiles('.lfs-assets-id') }}-v1
+ run: echo "lfs_key=$LFS_KEY" >> "$GITHUB_OUTPUT"
+
+ - name: Git Setup LFS Cache
+ uses: actions/cache@v5
+ with:
+ path: .git/lfs
+ key: ${{ steps.expose-key.outputs.lfs_key }}
+
+ - name: Git Pull LFS
+ shell: bash
+ run: git lfs pull
+
Build:
+ needs: WarmLFS
strategy:
matrix:
options:
- os: ubuntu-latest
- framework: net7.0
+ framework: net10.0
sdk-preview: true
runtime: -x64
codecov: false
- os: macos-latest
- framework: net7.0
+ framework: net10.0
sdk-preview: true
runtime: -x64
codecov: false
- os: windows-latest
- framework: net7.0
+ framework: net10.0
sdk-preview: true
runtime: -x64
codecov: true
- os: ubuntu-latest
- framework: net6.0
+ framework: net8.0
runtime: -x64
codecov: false
- os: macos-latest
- framework: net6.0
+ framework: net8.0
runtime: -x64
codecov: false
- os: windows-latest
- framework: net6.0
+ framework: net8.0
runtime: -x64
codecov: false
@@ -58,25 +106,22 @@ jobs:
fetch-depth: 0
submodules: recursive
- # See https://github.com/actions/checkout/issues/165#issuecomment-657673315
- - name: Git Create LFS FileList
- run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id
-
+ # Use the warmed key from WarmLFS. Do not recompute or recreate .lfs-assets-id here.
- name: Git Setup LFS Cache
- uses: actions/cache@v4
- id: lfs-cache
+ uses: actions/cache@v5
with:
path: .git/lfs
- key: ${{ runner.os }}-lfs-${{ hashFiles('.lfs-assets-id') }}-v1
+ key: ${{ needs.WarmLFS.outputs.lfs_key }}
- name: Git Pull LFS
+ shell: bash
run: git lfs pull
- name: NuGet Install
uses: NuGet/setup-nuget@v2
- name: NuGet Setup Cache
- uses: actions/cache@v4
+ uses: actions/cache@v5
id: nuget-cache
with:
path: ~/.nuget
@@ -112,11 +157,18 @@ jobs:
s3rver -d . &
- name: DotNet Setup
- uses: actions/setup-dotnet@v4
+ if: ${{ matrix.options.sdk-preview != true }}
+ uses: actions/setup-dotnet@v5
+ with:
+ dotnet-version: |
+ 8.0.x
+
+ - name: DotNet Setup Preview
+ if: ${{ matrix.options.sdk-preview == true }}
+ uses: actions/setup-dotnet@v5
with:
dotnet-version: |
- 7.0.x
- 6.0.x
+ 10.0.x
- name: DotNet Build
if: ${{ matrix.options.sdk-preview != true }}
@@ -153,6 +205,7 @@ jobs:
if: matrix.options.codecov == true && startsWith(github.repository, 'SixLabors')
with:
flags: unittests
+ token: ${{ secrets.CODECOV_TOKEN }}
Publish:
needs: [Build]
@@ -178,7 +231,7 @@ jobs:
uses: NuGet/setup-nuget@v2
- name: NuGet Setup Cache
- uses: actions/cache@v4
+ uses: actions/cache@v5
id: nuget-cache
with:
path: ~/.nuget
diff --git a/samples/ImageSharp.Web.Sample/ImageSharp.Web.Sample.csproj b/samples/ImageSharp.Web.Sample/ImageSharp.Web.Sample.csproj
index d20146da..f4b67405 100644
--- a/samples/ImageSharp.Web.Sample/ImageSharp.Web.Sample.csproj
+++ b/samples/ImageSharp.Web.Sample/ImageSharp.Web.Sample.csproj
@@ -1,10 +1,9 @@
- net6.0
+ net8.0
enable
enable
- 10
diff --git a/samples/ImageSharp.Web.Sample/Pages/Index.cshtml b/samples/ImageSharp.Web.Sample/Pages/Index.cshtml
index 73ad597b..74cb5f15 100644
--- a/samples/ImageSharp.Web.Sample/Pages/Index.cshtml
+++ b/samples/ImageSharp.Web.Sample/Pages/Index.cshtml
@@ -237,7 +237,7 @@
sixlabors.imagesharp.web.png?width=300&bgcolor=128,28,32
-
+
@@ -253,7 +253,7 @@
sixlabors.imagesharp.web.png?width=300&bgcolor=128,28,32,128
-
+
diff --git a/samples/ImageSharp.Web.Sample/Pages/_ViewImports.cshtml b/samples/ImageSharp.Web.Sample/Pages/_ViewImports.cshtml
index 05714033..a811452d 100644
--- a/samples/ImageSharp.Web.Sample/Pages/_ViewImports.cshtml
+++ b/samples/ImageSharp.Web.Sample/Pages/_ViewImports.cshtml
@@ -1,4 +1,5 @@
@using SixLabors.ImageSharp
+@using SixLabors.ImageSharp.PixelFormats
@using SixLabors.ImageSharp.Processing
@using SixLabors.ImageSharp.Web
@using ImageSharp.Web.Sample
diff --git a/samples/ImageSharp.Web.Sample/Program.cs b/samples/ImageSharp.Web.Sample/Program.cs
index 44a5de87..d82ee33b 100644
--- a/samples/ImageSharp.Web.Sample/Program.cs
+++ b/samples/ImageSharp.Web.Sample/Program.cs
@@ -1,9 +1,9 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using SixLabors.ImageSharp.Web;
using SixLabors.ImageSharp.Web.Caching;
using SixLabors.ImageSharp.Web.Commands;
-using SixLabors.ImageSharp.Web.DependencyInjection;
using SixLabors.ImageSharp.Web.Processors;
using SixLabors.ImageSharp.Web.Providers;
@@ -27,7 +27,7 @@ public static void Main(string[] args)
services.AddRazorPages();
// TODO: Enable HMAC
- services.AddImageSharp(options => options.HMACSecretKey = new byte[] { 1, 2, 3, 4, 5 })
+ services.AddImageSharp(options => options.HMACSecretKey = [1, 2, 3, 4, 5])
.SetRequestParser()
.Configure(options =>
{
diff --git a/shared-infrastructure b/shared-infrastructure
index f0d7ed20..bed6f53b 160000
--- a/shared-infrastructure
+++ b/shared-infrastructure
@@ -1 +1 @@
-Subproject commit f0d7ed20b36ab1f9e379ca3bee528e6efd991b00
+Subproject commit bed6f53bea0239e4afa19e81c24a6fff421707e1
diff --git a/src/ImageSharp.Web.Providers.AWS/AmazonS3BucketClient.cs b/src/ImageSharp.Web.Providers.AWS/AmazonS3BucketClient.cs
index d8940666..d67fad61 100644
--- a/src/ImageSharp.Web.Providers.AWS/AmazonS3BucketClient.cs
+++ b/src/ImageSharp.Web.Providers.AWS/AmazonS3BucketClient.cs
@@ -3,7 +3,7 @@
using Amazon.S3;
-namespace SixLabors.ImageSharp.Web;
+namespace SixLabors.ImageSharp.Web.AWS;
///
/// Represents a scoped Amazon S3 client instance that is explicitly associated with a single S3 bucket.
diff --git a/src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs b/src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs
index ff21b56a..347d4254 100644
--- a/src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs
+++ b/src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs
@@ -5,7 +5,7 @@
using Amazon.Runtime;
using Amazon.S3;
-namespace SixLabors.ImageSharp.Web;
+namespace SixLabors.ImageSharp.Web.AWS;
internal static class AmazonS3ClientFactory
{
diff --git a/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCache.cs b/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCache.cs
index aef41ac7..a3b9f5b3 100644
--- a/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCache.cs
+++ b/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCache.cs
@@ -5,10 +5,11 @@
using Amazon.S3;
using Amazon.S3.Model;
using Microsoft.Extensions.Options;
+using SixLabors.ImageSharp.Web.AWS.Resolvers;
+using SixLabors.ImageSharp.Web.Caching;
using SixLabors.ImageSharp.Web.Resolvers;
-using SixLabors.ImageSharp.Web.Resolvers.AWS;
-namespace SixLabors.ImageSharp.Web.Caching.AWS;
+namespace SixLabors.ImageSharp.Web.AWS.Caching;
///
/// Implements an AWS S3 Storage based cache.
diff --git a/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCacheOptions.cs b/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCacheOptions.cs
index e9c4a606..60b74439 100644
--- a/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCacheOptions.cs
+++ b/src/ImageSharp.Web.Providers.AWS/Caching/AWSS3StorageCacheOptions.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-namespace SixLabors.ImageSharp.Web.Caching.AWS;
+namespace SixLabors.ImageSharp.Web.AWS.Caching;
///
/// Configuration options for the provider.
diff --git a/src/ImageSharp.Web.Providers.AWS/IAWSS3BucketClientOptions.cs b/src/ImageSharp.Web.Providers.AWS/IAWSS3BucketClientOptions.cs
index 62bd79fe..452c9ce9 100644
--- a/src/ImageSharp.Web.Providers.AWS/IAWSS3BucketClientOptions.cs
+++ b/src/ImageSharp.Web.Providers.AWS/IAWSS3BucketClientOptions.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-namespace SixLabors.ImageSharp.Web;
+namespace SixLabors.ImageSharp.Web.AWS;
///
/// Provides a common interface for AWS S3 Bucket Client Options.
diff --git a/src/ImageSharp.Web.Providers.AWS/ImageSharp.Web.Providers.AWS.csproj b/src/ImageSharp.Web.Providers.AWS/ImageSharp.Web.Providers.AWS.csproj
index 41a35fa7..a8311d23 100644
--- a/src/ImageSharp.Web.Providers.AWS/ImageSharp.Web.Providers.AWS.csproj
+++ b/src/ImageSharp.Web.Providers.AWS/ImageSharp.Web.Providers.AWS.csproj
@@ -3,7 +3,7 @@
SixLabors.ImageSharp.Web.Providers.AWS
SixLabors.ImageSharp.Web.Providers.AWS
- SixLabors.ImageSharp.Web
+ SixLabors.ImageSharp.Web.AWS
SixLabors.ImageSharp.Web.Providers.AWS
sixlabors.imagesharp.web.128.png
LICENSE
@@ -20,19 +20,19 @@
-
- 3.0
+
+ 4.0
- net7.0;net6.0
+ net8.0;net10.0
- net6.0
+ net8.0
@@ -43,7 +43,7 @@
-
+
diff --git a/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProvider.cs b/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProvider.cs
index 20ab9b15..f8f10389 100644
--- a/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProvider.cs
+++ b/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProvider.cs
@@ -6,10 +6,11 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Options;
+using SixLabors.ImageSharp.Web.AWS.Resolvers;
+using SixLabors.ImageSharp.Web.Providers;
using SixLabors.ImageSharp.Web.Resolvers;
-using SixLabors.ImageSharp.Web.Resolvers.AWS;
-namespace SixLabors.ImageSharp.Web.Providers.AWS;
+namespace SixLabors.ImageSharp.Web.AWS.Providers;
///
/// Returns images stored in AWS S3.
@@ -19,13 +20,13 @@ public class AWSS3StorageImageProvider : IImageProvider, IDisposable
///
/// Character array to remove from paths.
///
- private static readonly char[] SlashChars = { '\\', '/' };
+ private static readonly char[] SlashChars = ['\\', '/'];
///
/// The containers for the blob services.
///
private readonly Dictionary buckets
- = new();
+ = [];
private readonly AWSS3StorageImageProviderOptions storageOptions;
private Func? match;
@@ -154,7 +155,7 @@ private bool IsMatch(HttpContext context)
}
// ref https://github.com/aws/aws-sdk-net/blob/master/sdk/src/Services/S3/Custom/_bcl/IO/S3FileInfo.cs#L118
- private static async Task KeyExists(IAmazonS3 s3Client, string bucketName, string key)
+ private static async Task KeyExists(AmazonS3Client s3Client, string bucketName, string key)
{
try
{
diff --git a/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProviderOptions.cs b/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProviderOptions.cs
index 187aec7e..93aa1cc2 100644
--- a/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProviderOptions.cs
+++ b/src/ImageSharp.Web.Providers.AWS/Providers/AWSS3StorageImageProviderOptions.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-namespace SixLabors.ImageSharp.Web.Providers.AWS;
+namespace SixLabors.ImageSharp.Web.AWS.Providers;
///
/// Configuration options for the provider.
diff --git a/src/ImageSharp.Web.Providers.AWS/Resolvers/AWSS3StorageCacheResolver.cs b/src/ImageSharp.Web.Providers.AWS/Resolvers/AWSS3StorageCacheResolver.cs
index 2add992f..78b534b8 100644
--- a/src/ImageSharp.Web.Providers.AWS/Resolvers/AWSS3StorageCacheResolver.cs
+++ b/src/ImageSharp.Web.Providers.AWS/Resolvers/AWSS3StorageCacheResolver.cs
@@ -3,8 +3,9 @@
using Amazon.S3;
using Amazon.S3.Model;
+using SixLabors.ImageSharp.Web.Resolvers;
-namespace SixLabors.ImageSharp.Web.Resolvers.AWS;
+namespace SixLabors.ImageSharp.Web.AWS.Resolvers;
///
/// Provides means to manage image buffers within the .
@@ -34,7 +35,7 @@ public AWSS3StorageCacheResolver(IAmazonS3 amazonS3, string bucketName, string i
///
public Task GetMetaDataAsync()
{
- Dictionary dict = new();
+ Dictionary dict = [];
foreach (string key in this.metadata.Keys)
{
// Trim automatically added x-amz-meta-
diff --git a/src/ImageSharp.Web.Providers.AWS/Resolvers/AWSS3StorageImageResolver.cs b/src/ImageSharp.Web.Providers.AWS/Resolvers/AWSS3StorageImageResolver.cs
index 42e042fd..65c5b8a1 100644
--- a/src/ImageSharp.Web.Providers.AWS/Resolvers/AWSS3StorageImageResolver.cs
+++ b/src/ImageSharp.Web.Providers.AWS/Resolvers/AWSS3StorageImageResolver.cs
@@ -4,8 +4,9 @@
using System.Net.Http.Headers;
using Amazon.S3;
using Amazon.S3.Model;
+using SixLabors.ImageSharp.Web.Resolvers;
-namespace SixLabors.ImageSharp.Web.Resolvers.AWS;
+namespace SixLabors.ImageSharp.Web.AWS.Resolvers;
///
/// Provides means to manage image buffers within the AWS S3 file system.
diff --git a/src/ImageSharp.Web.Providers.Azure/Caching/AzureBlobStorageCache.cs b/src/ImageSharp.Web.Providers.Azure/Caching/AzureBlobStorageCache.cs
index e49d281a..6252ac33 100644
--- a/src/ImageSharp.Web.Providers.Azure/Caching/AzureBlobStorageCache.cs
+++ b/src/ImageSharp.Web.Providers.Azure/Caching/AzureBlobStorageCache.cs
@@ -5,10 +5,11 @@
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Microsoft.Extensions.Options;
+using SixLabors.ImageSharp.Web.Azure.Resolvers;
+using SixLabors.ImageSharp.Web.Caching;
using SixLabors.ImageSharp.Web.Resolvers;
-using SixLabors.ImageSharp.Web.Resolvers.Azure;
-namespace SixLabors.ImageSharp.Web.Caching.Azure;
+namespace SixLabors.ImageSharp.Web.Azure.Caching;
///
/// Implements an Azure Blob Storage based cache.
diff --git a/src/ImageSharp.Web.Providers.Azure/Caching/AzureBlobStorageCacheOptions.cs b/src/ImageSharp.Web.Providers.Azure/Caching/AzureBlobStorageCacheOptions.cs
index ab119aa6..d41229ca 100644
--- a/src/ImageSharp.Web.Providers.Azure/Caching/AzureBlobStorageCacheOptions.cs
+++ b/src/ImageSharp.Web.Providers.Azure/Caching/AzureBlobStorageCacheOptions.cs
@@ -3,7 +3,7 @@
using Azure.Storage.Blobs;
-namespace SixLabors.ImageSharp.Web.Caching.Azure;
+namespace SixLabors.ImageSharp.Web.Azure.Caching;
///
/// Configuration options for the .
diff --git a/src/ImageSharp.Web.Providers.Azure/ImageSharp.Web.Providers.Azure.csproj b/src/ImageSharp.Web.Providers.Azure/ImageSharp.Web.Providers.Azure.csproj
index da7e9305..c54d7a7f 100644
--- a/src/ImageSharp.Web.Providers.Azure/ImageSharp.Web.Providers.Azure.csproj
+++ b/src/ImageSharp.Web.Providers.Azure/ImageSharp.Web.Providers.Azure.csproj
@@ -1,9 +1,9 @@
-
+
SixLabors.ImageSharp.Web.Providers.Azure
SixLabors.ImageSharp.Web.Providers.Azure
- SixLabors.ImageSharp.Web
+ SixLabors.ImageSharp.Web.Azure
SixLabors.ImageSharp.Web.Providers.Azure
sixlabors.imagesharp.web.128.png
LICENSE
@@ -20,19 +20,19 @@
-
- 3.0
+
+ 4.0
- net7.0;net6.0
+ net8.0;net10.0
- net6.0
+ net8.0
@@ -43,7 +43,7 @@
-
+
diff --git a/src/ImageSharp.Web.Providers.Azure/Providers/AzureBlobStorageImageProvider.cs b/src/ImageSharp.Web.Providers.Azure/Providers/AzureBlobStorageImageProvider.cs
index 60069a55..ca95de7e 100644
--- a/src/ImageSharp.Web.Providers.Azure/Providers/AzureBlobStorageImageProvider.cs
+++ b/src/ImageSharp.Web.Providers.Azure/Providers/AzureBlobStorageImageProvider.cs
@@ -5,10 +5,11 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Options;
+using SixLabors.ImageSharp.Web.Azure.Resolvers;
+using SixLabors.ImageSharp.Web.Providers;
using SixLabors.ImageSharp.Web.Resolvers;
-using SixLabors.ImageSharp.Web.Resolvers.Azure;
-namespace SixLabors.ImageSharp.Web.Providers.Azure;
+namespace SixLabors.ImageSharp.Web.Azure.Providers;
///
/// Returns images stored in Azure Blob Storage.
@@ -18,13 +19,13 @@ public class AzureBlobStorageImageProvider : IImageProvider
///
/// Character array to remove from paths.
///
- private static readonly char[] SlashChars = { '\\', '/' };
+ private static readonly char[] SlashChars = ['\\', '/'];
///
/// The containers for the blob services.
///
private readonly Dictionary containers
- = new();
+ = [];
///
/// Contains various helper methods based on the current configuration.
diff --git a/src/ImageSharp.Web.Providers.Azure/Providers/AzureBlobStorageImageProviderOptions.cs b/src/ImageSharp.Web.Providers.Azure/Providers/AzureBlobStorageImageProviderOptions.cs
index 9b1b8a1b..fa30977d 100644
--- a/src/ImageSharp.Web.Providers.Azure/Providers/AzureBlobStorageImageProviderOptions.cs
+++ b/src/ImageSharp.Web.Providers.Azure/Providers/AzureBlobStorageImageProviderOptions.cs
@@ -3,7 +3,7 @@
using Azure.Storage.Blobs;
-namespace SixLabors.ImageSharp.Web.Providers.Azure;
+namespace SixLabors.ImageSharp.Web.Azure.Providers;
///
/// Configuration options for the provider.
diff --git a/src/ImageSharp.Web.Providers.Azure/Resolvers/AzureBlobStorageCacheResolver.cs b/src/ImageSharp.Web.Providers.Azure/Resolvers/AzureBlobStorageCacheResolver.cs
index cdfad480..5f6062ec 100644
--- a/src/ImageSharp.Web.Providers.Azure/Resolvers/AzureBlobStorageCacheResolver.cs
+++ b/src/ImageSharp.Web.Providers.Azure/Resolvers/AzureBlobStorageCacheResolver.cs
@@ -3,9 +3,10 @@
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
-using SixLabors.ImageSharp.Web.Caching.Azure;
+using SixLabors.ImageSharp.Web.Azure.Caching;
+using SixLabors.ImageSharp.Web.Resolvers;
-namespace SixLabors.ImageSharp.Web.Resolvers.Azure;
+namespace SixLabors.ImageSharp.Web.Azure.Resolvers;
///
/// Provides means to manage image buffers within the .
diff --git a/src/ImageSharp.Web.Providers.Azure/Resolvers/AzureBlobStorageImageResolver.cs b/src/ImageSharp.Web.Providers.Azure/Resolvers/AzureBlobStorageImageResolver.cs
index 3b22d794..4fa2ec66 100644
--- a/src/ImageSharp.Web.Providers.Azure/Resolvers/AzureBlobStorageImageResolver.cs
+++ b/src/ImageSharp.Web.Providers.Azure/Resolvers/AzureBlobStorageImageResolver.cs
@@ -4,8 +4,9 @@
using System.Net.Http.Headers;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
+using SixLabors.ImageSharp.Web.Resolvers;
-namespace SixLabors.ImageSharp.Web.Resolvers.Azure;
+namespace SixLabors.ImageSharp.Web.Azure.Resolvers;
///
/// Provides means to manage image buffers within the Azure Blob file system.
diff --git a/src/ImageSharp.Web/DependencyInjection/ApplicationBuilderExtensions.cs b/src/ImageSharp.Web/ApplicationBuilderExtensions.cs
similarity index 93%
rename from src/ImageSharp.Web/DependencyInjection/ApplicationBuilderExtensions.cs
rename to src/ImageSharp.Web/ApplicationBuilderExtensions.cs
index e2f896dc..0246de2b 100644
--- a/src/ImageSharp.Web/DependencyInjection/ApplicationBuilderExtensions.cs
+++ b/src/ImageSharp.Web/ApplicationBuilderExtensions.cs
@@ -4,7 +4,7 @@
using Microsoft.AspNetCore.Builder;
using SixLabors.ImageSharp.Web.Middleware;
-namespace SixLabors.ImageSharp.Web.DependencyInjection;
+namespace SixLabors.ImageSharp.Web;
///
/// Extension methods for to simplify middleware registration.
diff --git a/src/ImageSharp.Web/Caching/HexEncoder.cs b/src/ImageSharp.Web/Caching/HexEncoder.cs
index acf72787..6541a802 100644
--- a/src/ImageSharp.Web/Caching/HexEncoder.cs
+++ b/src/ImageSharp.Web/Caching/HexEncoder.cs
@@ -12,13 +12,13 @@ namespace SixLabors.ImageSharp.Web.Caching;
internal static class HexEncoder
{
// LUT's that provide the hexidecimal representation of each possible byte value.
- private static readonly char[] HexLutBase = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ private static readonly char[] HexLutBase = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
// The base LUT arranged in 16x each item order. 0 * 16, 1 * 16, .... F * 16
- private static readonly char[] HexLutHi = Enumerable.Range(0, 256).Select(x => HexLutBase[x / 0x10]).ToArray();
+ private static readonly char[] HexLutHi = [.. Enumerable.Range(0, 256).Select(x => HexLutBase[x / 0x10])];
// The base LUT repeated 16x.
- private static readonly char[] HexLutLo = Enumerable.Range(0, 256).Select(x => HexLutBase[x % 0x10]).ToArray();
+ private static readonly char[] HexLutLo = [.. Enumerable.Range(0, 256).Select(x => HexLutBase[x % 0x10])];
///
/// Converts a to a hexidecimal formatted padded to 2 digits.
@@ -32,7 +32,7 @@ public static unsafe string Encode(ReadOnlySpan bytes)
{
return string.Create(bytes.Length * 2, (Ptr: (IntPtr)bytesPtr, bytes.Length), (chars, args) =>
{
- var ros = new ReadOnlySpan((byte*)args.Ptr, args.Length);
+ ReadOnlySpan ros = new((byte*)args.Ptr, args.Length);
EncodeToUtf16(ros, chars);
});
}
diff --git a/src/ImageSharp.Web/Caching/ICacheHash.cs b/src/ImageSharp.Web/Caching/ICacheHash.cs
index 26324709..c70b70b8 100644
--- a/src/ImageSharp.Web/Caching/ICacheHash.cs
+++ b/src/ImageSharp.Web/Caching/ICacheHash.cs
@@ -14,5 +14,5 @@ public interface ICacheHash
/// The input value to hash.
/// The length of the returned hash without any extensions.
/// The .
- string Create(string value, uint length);
+ public string Create(string value, uint length);
}
diff --git a/src/ImageSharp.Web/Caching/ICacheKey.cs b/src/ImageSharp.Web/Caching/ICacheKey.cs
index d7d3ae43..80282631 100644
--- a/src/ImageSharp.Web/Caching/ICacheKey.cs
+++ b/src/ImageSharp.Web/Caching/ICacheKey.cs
@@ -19,5 +19,5 @@ public interface ICacheKey
///
/// The cache key.
///
- string Create(HttpContext context, CommandCollection commands);
+ public string Create(HttpContext context, CommandCollection commands);
}
diff --git a/src/ImageSharp.Web/Caching/IImageCache.cs b/src/ImageSharp.Web/Caching/IImageCache.cs
index 1ac8e5cd..cdd790f0 100644
--- a/src/ImageSharp.Web/Caching/IImageCache.cs
+++ b/src/ImageSharp.Web/Caching/IImageCache.cs
@@ -16,7 +16,7 @@ public interface IImageCache
///
/// The cache key.
/// The .
- Task GetAsync(string key);
+ public Task GetAsync(string key);
///
/// Sets the value associated with the specified key.
@@ -25,5 +25,5 @@ public interface IImageCache
/// The stream containing the image to store.
/// The associated with the image to store.
/// The task.
- Task SetAsync(string key, Stream stream, ImageCacheMetadata metadata);
+ public Task SetAsync(string key, Stream stream, ImageCacheMetadata metadata);
}
diff --git a/src/ImageSharp.Web/Caching/LegacyV1CacheKey.cs b/src/ImageSharp.Web/Caching/LegacyV1CacheKey.cs
index 64b56e0b..03bba64d 100644
--- a/src/ImageSharp.Web/Caching/LegacyV1CacheKey.cs
+++ b/src/ImageSharp.Web/Caching/LegacyV1CacheKey.cs
@@ -22,16 +22,16 @@ public string Create(HttpContext context, CommandCollection commands)
string pathBase = context.Request.PathBase.ToString();
if (!string.IsNullOrWhiteSpace(pathBase))
{
- sb.AppendFormat(CultureInfo.InvariantCulture, "{0}/", pathBase);
+ _ = sb.AppendFormat(CultureInfo.InvariantCulture, "{0}/", pathBase);
}
string path = context.Request.Path.ToString();
if (!string.IsNullOrWhiteSpace(path))
{
- sb.Append(path);
+ _ = sb.Append(path);
}
- sb.Append(QueryString.Create(commands));
+ _ = sb.Append(QueryString.Create(commands));
return sb.ToString().ToLowerInvariant();
}
diff --git a/src/ImageSharp.Web/Caching/LruCache/ConcurrentTLruCache{TKey,TValue}.cs b/src/ImageSharp.Web/Caching/LruCache/ConcurrentTLruCache{TKey,TValue}.cs
index dbb1cf16..6d44700e 100644
--- a/src/ImageSharp.Web/Caching/LruCache/ConcurrentTLruCache{TKey,TValue}.cs
+++ b/src/ImageSharp.Web/Caching/LruCache/ConcurrentTLruCache{TKey,TValue}.cs
@@ -148,7 +148,7 @@ public TValue GetOrAdd(TKey key, Func valueFactory)
if (this.dictionary.TryAdd(key, newItem))
{
this.hotQueue.Enqueue(newItem);
- Interlocked.Increment(ref this.hotCount);
+ _ = Interlocked.Increment(ref this.hotCount);
this.Cycle();
return newItem.Value;
}
@@ -177,7 +177,7 @@ public async Task GetOrAddAsync(TKey key, Func> value
if (this.dictionary.TryAdd(key, newItem))
{
this.hotQueue.Enqueue(newItem);
- Interlocked.Increment(ref this.hotCount);
+ _ = Interlocked.Increment(ref this.hotCount);
this.Cycle();
return newItem.Value;
}
@@ -260,7 +260,7 @@ private void CycleHot()
{
if (this.hotCount > this.hotCapacity)
{
- Interlocked.Decrement(ref this.hotCount);
+ _ = Interlocked.Decrement(ref this.hotCount);
if (this.hotQueue.TryDequeue(out LongTickCountLruItem? item))
{
@@ -269,7 +269,7 @@ private void CycleHot()
}
else
{
- Interlocked.Increment(ref this.hotCount);
+ _ = Interlocked.Increment(ref this.hotCount);
}
}
}
@@ -278,7 +278,7 @@ private void CycleWarm()
{
if (this.warmCount > this.warmCapacity)
{
- Interlocked.Decrement(ref this.warmCount);
+ _ = Interlocked.Decrement(ref this.warmCount);
if (this.warmQueue.TryDequeue(out LongTickCountLruItem? item))
{
@@ -298,7 +298,7 @@ private void CycleWarm()
}
else
{
- Interlocked.Increment(ref this.warmCount);
+ _ = Interlocked.Increment(ref this.warmCount);
}
}
}
@@ -307,7 +307,7 @@ private void CycleCold()
{
if (this.coldCount > this.coldCapacity)
{
- Interlocked.Decrement(ref this.coldCount);
+ _ = Interlocked.Decrement(ref this.coldCount);
if (this.coldQueue.TryDequeue(out LongTickCountLruItem? item))
{
@@ -324,7 +324,7 @@ private void CycleCold()
}
else
{
- Interlocked.Increment(ref this.coldCount);
+ _ = Interlocked.Increment(ref this.coldCount);
}
}
}
@@ -338,11 +338,11 @@ private void Move(LongTickCountLruItem item, ItemDestination where
{
case ItemDestination.Warm:
this.warmQueue.Enqueue(item);
- Interlocked.Increment(ref this.warmCount);
+ _ = Interlocked.Increment(ref this.warmCount);
break;
case ItemDestination.Cold:
this.coldQueue.Enqueue(item);
- Interlocked.Increment(ref this.coldCount);
+ _ = Interlocked.Increment(ref this.coldCount);
break;
case ItemDestination.Remove:
if (!item.WasRemoved)
diff --git a/src/ImageSharp.Web/Caching/PhysicalFileSystemCache.cs b/src/ImageSharp.Web/Caching/PhysicalFileSystemCache.cs
index 34fe94a3..f70f8c8b 100644
--- a/src/ImageSharp.Web/Caching/PhysicalFileSystemCache.cs
+++ b/src/ImageSharp.Web/Caching/PhysicalFileSystemCache.cs
@@ -100,7 +100,7 @@ public async Task SetAsync(string key, Stream stream, ImageCacheMetadata metadat
// Ensure cache directory is created before creating files
if (!Directory.Exists(directory) && directory is not null)
{
- Directory.CreateDirectory(directory);
+ _ = Directory.CreateDirectory(directory);
}
using (FileStream fileStream = File.Create(imagePath))
diff --git a/src/ImageSharp.Web/Caching/SHA256CacheHash.cs b/src/ImageSharp.Web/Caching/SHA256CacheHash.cs
index 7eeae17a..7d3181b6 100644
--- a/src/ImageSharp.Web/Caching/SHA256CacheHash.cs
+++ b/src/ImageSharp.Web/Caching/SHA256CacheHash.cs
@@ -55,11 +55,11 @@ public string Create(string value, uint length)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string HashValue(ReadOnlySpan value, uint length, Span bufferSpan)
{
- Encoding.ASCII.GetBytes(value, bufferSpan);
+ _ = Encoding.ASCII.GetBytes(value, bufferSpan);
// Hashed output maxes out at 32 bytes @ 256bit/8 so we're safe to use stackalloc
Span hash = stackalloc byte[32];
- SHA256.TryHashData(bufferSpan, hash, out int _);
+ _ = SHA256.TryHashData(bufferSpan, hash, out _);
// Length maxes out at 64 since we throw if options is greater
return HexEncoder.Encode(hash[..(int)(length / 2)]);
diff --git a/src/ImageSharp.Web/Commands/CommandCollectionExtensions.cs b/src/ImageSharp.Web/Commands/CommandCollectionExtensions.cs
index 126c990a..b9f4a220 100644
--- a/src/ImageSharp.Web/Commands/CommandCollectionExtensions.cs
+++ b/src/ImageSharp.Web/Commands/CommandCollectionExtensions.cs
@@ -16,7 +16,7 @@ public static class CommandCollectionExtensions
/// The value associated with the specified key or the default value.
public static string? GetValueOrDefault(this CommandCollection collection, string key)
{
- collection.TryGetValue(key, out KeyValuePair result);
+ _ = collection.TryGetValue(key, out KeyValuePair result);
return result.Value;
}
}
diff --git a/src/ImageSharp.Web/Commands/CommandParser.cs b/src/ImageSharp.Web/Commands/CommandParser.cs
index 4bd0f534..1df81e9d 100644
--- a/src/ImageSharp.Web/Commands/CommandParser.cs
+++ b/src/ImageSharp.Web/Commands/CommandParser.cs
@@ -23,7 +23,7 @@ public sealed class CommandParser
public CommandParser(IEnumerable converters)
{
Guard.NotNull(converters, nameof(converters));
- this.converters = converters.ToArray();
+ this.converters = [.. converters];
}
///
diff --git a/src/ImageSharp.Web/Commands/Converters/ArrayConverter{T}.cs b/src/ImageSharp.Web/Commands/Converters/ArrayConverter{T}.cs
index 426da7e3..451ce3ab 100644
--- a/src/ImageSharp.Web/Commands/Converters/ArrayConverter{T}.cs
+++ b/src/ImageSharp.Web/Commands/Converters/ArrayConverter{T}.cs
@@ -28,7 +28,7 @@ public T[] ConvertFrom(
return Array.Empty();
}
- List result = new();
+ List result = [];
foreach (string pill in GetStringArray(value, culture))
{
T? item = parser.ParseValue(pill, culture);
@@ -38,7 +38,7 @@ public T[] ConvertFrom(
}
}
- return result.ToArray();
+ return [.. result];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -48,6 +48,6 @@ private static string[] GetStringArray(string input, CultureInfo culture)
// TODO: Can we use StringSplit Enumerator here?
// https://github.com/dotnet/runtime/issues/934
- return input.Split(separator).Select(s => s.Trim()).ToArray();
+ return [.. input.Split(separator).Select(s => s.Trim())];
}
}
diff --git a/src/ImageSharp.Web/Commands/Converters/ColorConverter.cs b/src/ImageSharp.Web/Commands/Converters/ColorConverter.cs
index ccf2c111..3bdc1150 100644
--- a/src/ImageSharp.Web/Commands/Converters/ColorConverter.cs
+++ b/src/ImageSharp.Web/Commands/Converters/ColorConverter.cs
@@ -5,24 +5,25 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
+using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Web.Commands.Converters;
///
/// Allows the conversion of strings into rgba32 pixel colors.
///
-public sealed class ColorConverter : ICommandConverter
+public sealed partial class ColorConverter : ICommandConverter
{
///
/// The web color hexadecimal regex. Matches strings arranged
/// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax.
///
- private static readonly Regex HexColorRegex = new("([0-9a-fA-F][^,;.-]\\B{3}){1,2}", RegexOptions.Compiled);
+ private static readonly Regex HexColorRegex = HexRegex();
///
/// The number color regex.
///
- private static readonly Regex NumberRegex = new(@"\d+", RegexOptions.Compiled);
+ private static readonly Regex NumberRegex = NumberColorRegex();
///
/// The color constants table map.
@@ -69,8 +70,8 @@ public Color ConvertFrom(CommandParser parser, CultureInfo culture, string? valu
return rgba?.Count switch
{
- 4 => Color.FromRgba(rgba[0], rgba[1], rgba[2], rgba[3]),
- 3 => Color.FromRgb(rgba[0], rgba[1], rgba[2]),
+ 4 => Color.FromPixel(new(rgba[0], rgba[1], rgba[2], rgba[3])),
+ 3 => Color.FromPixel(new(rgba[0], rgba[1], rgba[2])),
_ => default,
};
}
@@ -85,9 +86,9 @@ public Color ConvertFrom(CommandParser parser, CultureInfo culture, string? valu
return default;
}
- private static IDictionary InitializeColorConstantsTable()
+ private static Dictionary InitializeColorConstantsTable()
{
- IDictionary table = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ Dictionary table = new(StringComparer.OrdinalIgnoreCase);
foreach (FieldInfo field in typeof(Color).GetFields(BindingFlags.Public | BindingFlags.Static))
{
@@ -99,4 +100,10 @@ private static IDictionary InitializeColorConstantsTable()
return table;
}
+
+ [GeneratedRegex(@"\d+", RegexOptions.Compiled)]
+ private static partial Regex NumberColorRegex();
+
+ [GeneratedRegex("([0-9a-fA-F][^,;.-]\\B{3}){1,2}", RegexOptions.Compiled)]
+ private static partial Regex HexRegex();
}
diff --git a/src/ImageSharp.Web/Commands/Converters/ConverterUtility.cs b/src/ImageSharp.Web/Commands/Converters/ConverterUtility.cs
index c924e35c..18104b0f 100644
--- a/src/ImageSharp.Web/Commands/Converters/ConverterUtility.cs
+++ b/src/ImageSharp.Web/Commands/Converters/ConverterUtility.cs
@@ -6,6 +6,7 @@
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Web.Commands.Converters;
+
internal static class ConverterUtility
{
///
diff --git a/src/ImageSharp.Web/Commands/Converters/EnumConverter.cs b/src/ImageSharp.Web/Commands/Converters/EnumConverter.cs
index 43573145..3d226c93 100644
--- a/src/ImageSharp.Web/Commands/Converters/EnumConverter.cs
+++ b/src/ImageSharp.Web/Commands/Converters/EnumConverter.cs
@@ -29,7 +29,7 @@ public sealed class EnumConverter : ICommandConverter
/// Encapsulates all HTTP-specific information about an individual HTTP request.
/// The .
- CommandCollection ParseRequestCommands(HttpContext context);
+ public CommandCollection ParseRequestCommands(HttpContext context);
}
diff --git a/src/ImageSharp.Web/Commands/PresetOnlyQueryCollectionRequestParser.cs b/src/ImageSharp.Web/Commands/PresetOnlyQueryCollectionRequestParser.cs
index 89042ac2..f879463b 100644
--- a/src/ImageSharp.Web/Commands/PresetOnlyQueryCollectionRequestParser.cs
+++ b/src/ImageSharp.Web/Commands/PresetOnlyQueryCollectionRequestParser.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Web.Commands;
///
public class PresetOnlyQueryCollectionRequestParser : IRequestParser
{
- private readonly IDictionary presets;
+ private readonly Dictionary presets;
///
/// The command constant for the preset query parameter.
@@ -36,7 +36,7 @@ public CommandCollection ParseRequestCommands(HttpContext context)
|| !queryCollection.ContainsKey(QueryKey))
{
// We return new here and below to ensure the collection is still mutable via events.
- return new();
+ return [];
}
StringValues query = queryCollection[QueryKey];
@@ -46,10 +46,10 @@ public CommandCollection ParseRequestCommands(HttpContext context)
return collection;
}
- return new();
+ return [];
}
- private static IDictionary ParsePresets(
+ private static Dictionary ParsePresets(
IDictionary unparsedPresets) =>
unparsedPresets
.Select(keyValue =>
@@ -58,7 +58,7 @@ private static IDictionary ParsePresets(
private static CommandCollection ParsePreset(string unparsedPresetValue)
{
- CommandCollection transformed = new();
+ CommandCollection transformed = [];
foreach (QueryStringEnumerable.EncodedNameValuePair pair in new QueryStringEnumerable(unparsedPresetValue))
{
// Last value wins.
diff --git a/src/ImageSharp.Web/Commands/PresetOnlyQueryCollectionRequestParserOptions.cs b/src/ImageSharp.Web/Commands/PresetOnlyQueryCollectionRequestParserOptions.cs
index 7c40e8a4..d138cc72 100644
--- a/src/ImageSharp.Web/Commands/PresetOnlyQueryCollectionRequestParserOptions.cs
+++ b/src/ImageSharp.Web/Commands/PresetOnlyQueryCollectionRequestParserOptions.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Web.Commands;
@@ -11,5 +11,5 @@ public class PresetOnlyQueryCollectionRequestParserOptions
///
/// Gets or sets the presets, which is a Dictionary of preset names to command query strings.
///
- public IDictionary Presets { get; set; } = new Dictionary();
+ public Dictionary Presets { get; set; } = [];
}
diff --git a/src/ImageSharp.Web/Commands/QueryCollectionRequestParser.cs b/src/ImageSharp.Web/Commands/QueryCollectionRequestParser.cs
index 420fc019..7c813acd 100644
--- a/src/ImageSharp.Web/Commands/QueryCollectionRequestParser.cs
+++ b/src/ImageSharp.Web/Commands/QueryCollectionRequestParser.cs
@@ -18,10 +18,10 @@ public CommandCollection ParseRequestCommands(HttpContext context)
if (query is null || query.Count == 0)
{
// We return new to ensure the collection is still mutable via events.
- return new();
+ return [];
}
- CommandCollection transformed = new();
+ CommandCollection transformed = [];
foreach (KeyValuePair pair in query)
{
// Use the indexer for both set and query. This replaces any previously parsed values.
diff --git a/src/ImageSharp.Web/Commands/TypeConstants.cs b/src/ImageSharp.Web/Commands/TypeConstants.cs
index c6460de5..249ff8f1 100644
--- a/src/ImageSharp.Web/Commands/TypeConstants.cs
+++ b/src/ImageSharp.Web/Commands/TypeConstants.cs
@@ -52,7 +52,7 @@ internal static class TypeConstants
/// The collection of integral number types.
///
public static readonly Type[] IntegralTypes =
- {
+ [
Sbyte,
Byte,
Short,
@@ -61,5 +61,5 @@ internal static class TypeConstants
UInt,
Long,
ULong
- };
+ ];
}
diff --git a/src/ImageSharp.Web/DependencyInjection/ServiceCollectionExtensions.cs b/src/ImageSharp.Web/DependencyInjection/ServiceCollectionExtensions.cs
deleted file mode 100644
index 4a3a3e59..00000000
--- a/src/ImageSharp.Web/DependencyInjection/ServiceCollectionExtensions.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using Microsoft.Extensions.DependencyInjection;
-using SixLabors.ImageSharp.Web.Caching;
-using SixLabors.ImageSharp.Web.Commands;
-using SixLabors.ImageSharp.Web.Commands.Converters;
-using SixLabors.ImageSharp.Web.Middleware;
-using SixLabors.ImageSharp.Web.Processors;
-using SixLabors.ImageSharp.Web.Providers;
-using SixLabors.ImageSharp.Web.Synchronization;
-
-namespace SixLabors.ImageSharp.Web.DependencyInjection;
-
-///
-/// Extension methods for to simplify middleware service registration.
-///
-public static class ServiceCollectionExtensions
-{
- ///
- /// Adds ImageSharp services to the specified with the default options.
- ///
- /// The to add services to.
- /// An that can be used to further configure the ImageSharp services.
- public static IImageSharpBuilder AddImageSharp(this IServiceCollection services)
- => AddImageSharp(services, _ => { });
-
- ///
- /// Adds ImageSharp services to the specified with the given options.
- ///
- /// The to add services to.
- /// An to configure the provided .
- /// An that can be used to further configure the ImageSharp services.
- public static IImageSharpBuilder AddImageSharp(
- this IServiceCollection services,
- Action setupAction)
- {
- Guard.NotNull(services, nameof(services));
- Guard.NotNull(setupAction, nameof(setupAction));
-
- IImageSharpBuilder builder = new ImageSharpBuilder(services);
-
- AddDefaultServices(builder, setupAction);
-
- return builder;
- }
-
- private static void AddDefaultServices(
- IImageSharpBuilder builder,
- Action setupAction)
- {
- builder.Services.Configure(setupAction);
-
- builder.Services.AddSingleton();
-
- builder.Services.AddSingleton>();
-
- builder.SetRequestParser();
-
- builder.Services.AddSingleton();
-
- builder.SetCache();
-
- builder.SetCacheKey();
-
- builder.SetCacheHash();
-
- builder.AddProvider();
-
- builder.AddProcessor()
- .AddProcessor()
- .AddProcessor()
- .AddProcessor()
- .AddProcessor();
-
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
-
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
-
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
-
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
- builder.AddConverter>();
-
- builder.AddConverter();
- builder.AddConverter();
-
- builder.Services.AddSingleton();
- }
-}
diff --git a/src/ImageSharp.Web/FormatUtilities.cs b/src/ImageSharp.Web/FormatUtilities.cs
index 928241bf..95c6aaed 100644
--- a/src/ImageSharp.Web/FormatUtilities.cs
+++ b/src/ImageSharp.Web/FormatUtilities.cs
@@ -17,8 +17,8 @@ namespace SixLabors.ImageSharp.Web;
///
public sealed class FormatUtilities
{
- private readonly List extensions = new();
- private readonly Dictionary extensionsByMimeType = new();
+ private readonly List extensions = [];
+ private readonly Dictionary extensionsByMimeType = [];
///
/// Initializes a new instance of the class.
@@ -30,7 +30,7 @@ public FormatUtilities(IOptions options)
foreach (IImageFormat imageFormat in options.Value.Configuration.ImageFormats)
{
- string[] extensions = imageFormat.FileExtensions.ToArray();
+ string[] extensions = [.. imageFormat.FileExtensions];
this.extensions.AddRange(extensions);
diff --git a/src/ImageSharp.Web/FormattedImage.cs b/src/ImageSharp.Web/FormattedImage.cs
index d0e47f67..acecbd92 100644
--- a/src/ImageSharp.Web/FormattedImage.cs
+++ b/src/ImageSharp.Web/FormattedImage.cs
@@ -101,9 +101,6 @@ public IImageEncoder Encoder
internal static async Task LoadAsync(DecoderOptions options, Stream source)
where TPixel : unmanaged, IPixel
{
- // TODO: We want to be able to apply decoder options per request.
- // For example. If a resize command has been passed with no extra resampling options
- // then we should apply those changes on decode. This will allow memory savings and performance improvements.
Image image = await Image.LoadAsync(options, source);
return new FormattedImage(image, image.Metadata.DecodedImageFormat!, false);
}
diff --git a/src/ImageSharp.Web/HMACUtilities.cs b/src/ImageSharp.Web/HMACUtilities.cs
index e0834780..eb9d4f5f 100644
--- a/src/ImageSharp.Web/HMACUtilities.cs
+++ b/src/ImageSharp.Web/HMACUtilities.cs
@@ -38,10 +38,8 @@ private enum HashAlgorithmSizes
/// The key can be any length. However, the recommended size is 64 bytes.
///
/// The hashed .
- public static unsafe string ComputeHMACSHA256(string value, byte[] secret)
- {
- return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA256);
- }
+ public static string ComputeHMACSHA256(string value, byte[] secret)
+ => CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA256);
///
/// Computes a Hash-based Message Authentication Code (HMAC) by using the SHA384 hash function.
@@ -52,10 +50,8 @@ public static unsafe string ComputeHMACSHA256(string value, byte[] secret)
/// The key can be any length. However, the recommended size is 128 bytes.
///
/// The hashed .
- public static unsafe string ComputeHMACSHA384(string value, byte[] secret)
- {
- return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA384);
- }
+ public static string ComputeHMACSHA384(string value, byte[] secret)
+ => CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA384);
///
/// Computes a Hash-based Message Authentication Code (HMAC) by using the SHA512 hash function.
@@ -66,13 +62,11 @@ public static unsafe string ComputeHMACSHA384(string value, byte[] secret)
/// The key can be any length. However, the recommended size is 128 bytes.
///
/// The hashed .
- public static unsafe string ComputeHMACSHA512(string value, byte[] secret)
- {
- return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA512);
- }
+ public static string ComputeHMACSHA512(string value, byte[] secret)
+ => CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA512);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static unsafe string CreateHMAC(string value, ReadOnlySpan secret, HashAlgorithmSizes hashSize)
+ private static string CreateHMAC(string value, ReadOnlySpan secret, HashAlgorithmSizes hashSize)
{
int byteCount = Encoding.ASCII.GetByteCount(value);
byte[]? buffer = null;
@@ -84,23 +78,16 @@ private static unsafe string CreateHMAC(string value, ReadOnlySpan secret,
? stackalloc byte[byteCount]
: (buffer = ArrayPool.Shared.Rent(byteCount)).AsSpan(0, byteCount);
- Encoding.ASCII.GetBytes(value, bytes);
+ _ = Encoding.ASCII.GetBytes(value, bytes);
// Safe to always stackalloc here. We max out at 64 bytes.
Span hash = stackalloc byte[(int)hashSize];
- switch (hashSize)
+ _ = hashSize switch
{
- default:
- case HashAlgorithmSizes.HMACSHA256:
- HMACSHA256.TryHashData(secret, bytes, hash, out _);
- break;
- case HashAlgorithmSizes.HMACSHA384:
- HMACSHA384.TryHashData(secret, bytes, hash, out _);
- break;
- case HashAlgorithmSizes.HMACSHA512:
- HMACSHA512.TryHashData(secret, bytes, hash, out _);
- break;
- }
+ HashAlgorithmSizes.HMACSHA384 => HMACSHA384.TryHashData(secret, bytes, hash, out _),
+ HashAlgorithmSizes.HMACSHA512 => HMACSHA512.TryHashData(secret, bytes, hash, out _),
+ _ => HMACSHA256.TryHashData(secret, bytes, hash, out _),
+ };
// Finally encode the hash to make it web safe.
return HexEncoder.Encode(hash);
diff --git a/src/ImageSharp.Web/DependencyInjection/IImageSharpBuilder.cs b/src/ImageSharp.Web/IImageSharpBuilder.cs
similarity index 73%
rename from src/ImageSharp.Web/DependencyInjection/IImageSharpBuilder.cs
rename to src/ImageSharp.Web/IImageSharpBuilder.cs
index f1935af9..c2673a6c 100644
--- a/src/ImageSharp.Web/DependencyInjection/IImageSharpBuilder.cs
+++ b/src/ImageSharp.Web/IImageSharpBuilder.cs
@@ -1,9 +1,9 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using Microsoft.Extensions.DependencyInjection;
-namespace SixLabors.ImageSharp.Web.DependencyInjection;
+namespace SixLabors.ImageSharp.Web;
///
/// Defines a contract for adding ImageSharp services.
@@ -13,5 +13,5 @@ public interface IImageSharpBuilder
///
/// Gets the where ImageSharp services are configured.
///
- IServiceCollection Services { get; }
+ public IServiceCollection Services { get; }
}
diff --git a/src/ImageSharp.Web/ImageCacheMetadata.cs b/src/ImageSharp.Web/ImageCacheMetadata.cs
index fafc4d5e..bdac1d31 100644
--- a/src/ImageSharp.Web/ImageCacheMetadata.cs
+++ b/src/ImageSharp.Web/ImageCacheMetadata.cs
@@ -97,13 +97,13 @@ public ImageCacheMetadata(
public static ImageCacheMetadata FromDictionary(IDictionary dictionary)
{
// DateTime.TryParse(null) == DateTime.MinValue so no need for conditional;
- dictionary.TryGetValue(SourceLastModifiedKey, out string? sourceLastWriteTimeUtcString);
- DateTime.TryParse(sourceLastWriteTimeUtcString, null, DateTimeStyles.RoundtripKind, out DateTime sourceLastWriteTimeUtc);
+ _ = dictionary.TryGetValue(SourceLastModifiedKey, out string? sourceLastWriteTimeUtcString);
+ _ = DateTime.TryParse(sourceLastWriteTimeUtcString, null, DateTimeStyles.RoundtripKind, out DateTime sourceLastWriteTimeUtc);
- dictionary.TryGetValue(CacheLastModifiedKey, out string? cacheLastWriteTimeUtcString);
- DateTime.TryParse(cacheLastWriteTimeUtcString, null, DateTimeStyles.RoundtripKind, out DateTime cacheLastWriteTimeUtc);
+ _ = dictionary.TryGetValue(CacheLastModifiedKey, out string? cacheLastWriteTimeUtcString);
+ _ = DateTime.TryParse(cacheLastWriteTimeUtcString, null, DateTimeStyles.RoundtripKind, out DateTime cacheLastWriteTimeUtc);
- dictionary.TryGetValue(ContentTypeKey, out string? contentType);
+ _ = dictionary.TryGetValue(ContentTypeKey, out string? contentType);
Guard.NotNull(contentType);
// int.TryParse(null) == 0 and we want to return TimeSpan.MinValue not TimeSpan.Zero
@@ -114,7 +114,7 @@ public static ImageCacheMetadata FromDictionary(IDictionary dict
cacheControlMaxAge = TimeSpan.FromSeconds(maxAge);
}
- dictionary.TryGetValue(ContentLengthKey, out string? contentLengthString);
+ _ = dictionary.TryGetValue(ContentLengthKey, out string? contentLengthString);
_ = long.TryParse(contentLengthString, out long contentLength);
return new ImageCacheMetadata(
@@ -132,7 +132,7 @@ public static ImageCacheMetadata FromDictionary(IDictionary dict
/// The .
public static async Task ReadAsync(Stream stream)
{
- Dictionary dictionary = new();
+ Dictionary dictionary = [];
using (StreamReader reader = new(stream, Encoding.UTF8))
{
string? line;
@@ -202,8 +202,17 @@ public async Task WriteAsync(Stream stream)
await using StreamWriter writer = new(stream, Encoding.UTF8);
foreach (KeyValuePair keyValuePair in dictionary)
{
- // TODO: string.Create
- await writer.WriteLineAsync($"{keyValuePair.Key}:{keyValuePair.Value}");
+ string line = string.Create(
+ keyValuePair.Key.Length + keyValuePair.Value.Length + 1,
+ keyValuePair,
+ static (span, state) =>
+ {
+ state.Key.AsSpan().CopyTo(span);
+ span[state.Key.Length] = ':';
+ state.Value.AsSpan().CopyTo(span[(state.Key.Length + 1)..]);
+ });
+
+ await writer.WriteLineAsync(line);
}
await writer.FlushAsync();
diff --git a/src/ImageSharp.Web/ImageSharp.Web.csproj b/src/ImageSharp.Web/ImageSharp.Web.csproj
index ccbd0346..e149431e 100644
--- a/src/ImageSharp.Web/ImageSharp.Web.csproj
+++ b/src/ImageSharp.Web/ImageSharp.Web.csproj
@@ -1,4 +1,4 @@
-
+
SixLabors.ImageSharp.Web
@@ -20,19 +20,19 @@
-
- 3.0
+
+ 4.0
- net7.0;net6.0
+ net8.0;net10.0
- net6.0
+ net8.0
@@ -46,7 +46,7 @@
-
+
diff --git a/src/ImageSharp.Web/DependencyInjection/ImageSharpBuilder.cs b/src/ImageSharp.Web/ImageSharpBuilder.cs
similarity index 92%
rename from src/ImageSharp.Web/DependencyInjection/ImageSharpBuilder.cs
rename to src/ImageSharp.Web/ImageSharpBuilder.cs
index 58da1137..303f71ba 100644
--- a/src/ImageSharp.Web/DependencyInjection/ImageSharpBuilder.cs
+++ b/src/ImageSharp.Web/ImageSharpBuilder.cs
@@ -3,7 +3,7 @@
using Microsoft.Extensions.DependencyInjection;
-namespace SixLabors.ImageSharp.Web.DependencyInjection;
+namespace SixLabors.ImageSharp.Web;
///
/// Allows fine grained configuration of ImageSharp services.
diff --git a/src/ImageSharp.Web/DependencyInjection/ImageSharpBuilderExtensions.cs b/src/ImageSharp.Web/ImageSharpBuilderExtensions.cs
similarity index 81%
rename from src/ImageSharp.Web/DependencyInjection/ImageSharpBuilderExtensions.cs
rename to src/ImageSharp.Web/ImageSharpBuilderExtensions.cs
index 8c4a17bb..4f17539c 100644
--- a/src/ImageSharp.Web/DependencyInjection/ImageSharpBuilderExtensions.cs
+++ b/src/ImageSharp.Web/ImageSharpBuilderExtensions.cs
@@ -1,16 +1,18 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
+using SixLabors.ImageSharp.Web;
using SixLabors.ImageSharp.Web.Caching;
using SixLabors.ImageSharp.Web.Commands;
using SixLabors.ImageSharp.Web.Commands.Converters;
using SixLabors.ImageSharp.Web.Processors;
using SixLabors.ImageSharp.Web.Providers;
-namespace SixLabors.ImageSharp.Web.DependencyInjection;
+namespace SixLabors.ImageSharp.Web;
///
/// Extension methods for that allow configuration of services.
@@ -23,10 +25,10 @@ public static class ImageSharpBuilderExtensions
/// The type of class implementing to add.
/// The core builder.
/// The .
- public static IImageSharpBuilder SetRequestParser(this IImageSharpBuilder builder)
+ public static IImageSharpBuilder SetRequestParser<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TParser>(this IImageSharpBuilder builder)
where TParser : class, IRequestParser
{
- builder.Services.Replace(ServiceDescriptor.Singleton());
+ _ = builder.Services.Replace(ServiceDescriptor.Singleton());
return builder;
}
@@ -39,7 +41,7 @@ public static IImageSharpBuilder SetRequestParser(this IImageSharpBuild
/// The .
public static IImageSharpBuilder SetRequestParser(this IImageSharpBuilder builder, Func implementationFactory)
{
- builder.Services.Replace(ServiceDescriptor.Singleton(implementationFactory));
+ _ = builder.Services.Replace(ServiceDescriptor.Singleton(implementationFactory));
return builder;
}
@@ -50,10 +52,10 @@ public static IImageSharpBuilder SetRequestParser(this IImageSharpBuilder builde
/// The type of class implementing to add.
/// The core builder.
/// The .
- public static IImageSharpBuilder SetCache(this IImageSharpBuilder builder)
+ public static IImageSharpBuilder SetCache<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TCache>(this IImageSharpBuilder builder)
where TCache : class, IImageCache
{
- builder.Services.Replace(ServiceDescriptor.Singleton());
+ _ = builder.Services.Replace(ServiceDescriptor.Singleton());
return builder;
}
@@ -66,7 +68,7 @@ public static IImageSharpBuilder SetCache(this IImageSharpBuilder builde
/// The .
public static IImageSharpBuilder SetCache(this IImageSharpBuilder builder, Func implementationFactory)
{
- builder.Services.Replace(ServiceDescriptor.Singleton(implementationFactory));
+ _ = builder.Services.Replace(ServiceDescriptor.Singleton(implementationFactory));
return builder;
}
@@ -77,10 +79,10 @@ public static IImageSharpBuilder SetCache(this IImageSharpBuilder builder, Func<
/// The type of class implementing to add.
/// The core builder.
/// The .
- public static IImageSharpBuilder SetCacheKey(this IImageSharpBuilder builder)
+ public static IImageSharpBuilder SetCacheKey<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TCacheKey>(this IImageSharpBuilder builder)
where TCacheKey : class, ICacheKey
{
- builder.Services.Replace(ServiceDescriptor.Singleton());
+ _ = builder.Services.Replace(ServiceDescriptor.Singleton());
return builder;
}
@@ -93,7 +95,7 @@ public static IImageSharpBuilder SetCacheKey(this IImageSharpBuilder
/// The .
public static IImageSharpBuilder SetCacheKey(this IImageSharpBuilder builder, Func implementationFactory)
{
- builder.Services.Replace(ServiceDescriptor.Singleton(implementationFactory));
+ _ = builder.Services.Replace(ServiceDescriptor.Singleton(implementationFactory));
return builder;
}
@@ -104,10 +106,10 @@ public static IImageSharpBuilder SetCacheKey(this IImageSharpBuilder builder, Fu
/// The type of class implementing to add.
/// The core builder.
/// The .
- public static IImageSharpBuilder SetCacheHash(this IImageSharpBuilder builder)
+ public static IImageSharpBuilder SetCacheHash<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TCacheHash>(this IImageSharpBuilder builder)
where TCacheHash : class, ICacheHash
{
- builder.Services.Replace(ServiceDescriptor.Singleton());
+ _ = builder.Services.Replace(ServiceDescriptor.Singleton());
return builder;
}
@@ -120,7 +122,7 @@ public static IImageSharpBuilder SetCacheHash(this IImageSharpBuilde
/// The .
public static IImageSharpBuilder SetCacheHash(this IImageSharpBuilder builder, Func implementationFactory)
{
- builder.Services.Replace(ServiceDescriptor.Singleton(implementationFactory));
+ _ = builder.Services.Replace(ServiceDescriptor.Singleton(implementationFactory));
return builder;
}
@@ -131,7 +133,7 @@ public static IImageSharpBuilder SetCacheHash(this IImageSharpBuilder builder, F
/// The type of class implementing to add.
/// The core builder.
/// The .
- public static IImageSharpBuilder AddProvider(this IImageSharpBuilder builder)
+ public static IImageSharpBuilder AddProvider<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TProvider>(this IImageSharpBuilder builder)
where TProvider : class, IImageProvider
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton());
@@ -161,14 +163,14 @@ public static IImageSharpBuilder AddProvider(this IImageSharpBuilder
/// The core builder.
/// The zero-based index at which the provider should be inserted.
/// The .
- public static IImageSharpBuilder InsertProvider(this IImageSharpBuilder builder, int index)
+ public static IImageSharpBuilder InsertProvider<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TProvider>(this IImageSharpBuilder builder, int index)
where TProvider : class, IImageProvider
{
- var descriptors = builder.Services.Where(x => x.ServiceType == typeof(IImageProvider)).ToList();
- descriptors.RemoveAll(x => x.GetImplementationType() == typeof(TProvider));
+ List descriptors = [.. builder.Services.Where(x => x.ServiceType == typeof(IImageProvider))];
+ _ = descriptors.RemoveAll(x => x.GetImplementationType() == typeof(TProvider));
descriptors.Insert(index, ServiceDescriptor.Singleton());
- builder.ClearProviders();
+ _ = builder.ClearProviders();
builder.Services.TryAddEnumerable(descriptors);
return builder;
@@ -185,11 +187,11 @@ public static IImageSharpBuilder InsertProvider(this IImageSharpBuild
public static IImageSharpBuilder InsertProvider(this IImageSharpBuilder builder, int index, Func implementationFactory)
where TProvider : class, IImageProvider
{
- var descriptors = builder.Services.Where(x => x.ServiceType == typeof(IImageProvider)).ToList();
- descriptors.RemoveAll(x => x.GetImplementationType() == typeof(TProvider));
+ List descriptors = [.. builder.Services.Where(x => x.ServiceType == typeof(IImageProvider))];
+ _ = descriptors.RemoveAll(x => x.GetImplementationType() == typeof(TProvider));
descriptors.Insert(index, ServiceDescriptor.Singleton(implementationFactory));
- builder.ClearProviders();
+ _ = builder.ClearProviders();
builder.Services.TryAddEnumerable(descriptors);
return builder;
@@ -207,7 +209,7 @@ public static IImageSharpBuilder RemoveProvider(this IImageSharpBuild
ServiceDescriptor? descriptor = builder.Services.FirstOrDefault(x => x.ServiceType == typeof(IImageProvider) && x.GetImplementationType() == typeof(TProvider));
if (descriptor != null)
{
- builder.Services.Remove(descriptor);
+ _ = builder.Services.Remove(descriptor);
}
return builder;
@@ -220,7 +222,7 @@ public static IImageSharpBuilder RemoveProvider(this IImageSharpBuild
/// The .
public static IImageSharpBuilder ClearProviders(this IImageSharpBuilder builder)
{
- builder.Services.RemoveAll();
+ _ = builder.Services.RemoveAll();
return builder;
}
@@ -231,7 +233,7 @@ public static IImageSharpBuilder ClearProviders(this IImageSharpBuilder builder)
/// The type of class implementing to add.
/// The core builder.
/// The .
- public static IImageSharpBuilder AddProcessor(this IImageSharpBuilder builder)
+ public static IImageSharpBuilder AddProcessor<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(this IImageSharpBuilder builder)
where T : class, IImageWebProcessor
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton());
@@ -266,7 +268,7 @@ public static IImageSharpBuilder RemoveProcessor(this IImageSharpBui
ServiceDescriptor? descriptor = builder.Services.FirstOrDefault(x => x.ServiceType == typeof(IImageWebProcessor) && x.GetImplementationType() == typeof(TProcessor));
if (descriptor != null)
{
- builder.Services.Remove(descriptor);
+ _ = builder.Services.Remove(descriptor);
}
return builder;
@@ -279,7 +281,7 @@ public static IImageSharpBuilder RemoveProcessor(this IImageSharpBui
/// The .
public static IImageSharpBuilder ClearProcessors(this IImageSharpBuilder builder)
{
- builder.Services.RemoveAll();
+ _ = builder.Services.RemoveAll();
return builder;
}
@@ -290,7 +292,7 @@ public static IImageSharpBuilder ClearProcessors(this IImageSharpBuilder builder
/// The type of class implementing to add.
/// The core builder.
/// The .
- public static IImageSharpBuilder AddConverter(this IImageSharpBuilder builder)
+ public static IImageSharpBuilder AddConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TConverter>(this IImageSharpBuilder builder)
where TConverter : class, ICommandConverter
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton());
@@ -325,7 +327,7 @@ public static IImageSharpBuilder RemoveConverter(this IImageSharpBui
ServiceDescriptor? descriptor = builder.Services.FirstOrDefault(x => x.ServiceType == typeof(ICommandConverter) && x.GetImplementationType() == typeof(TConverter));
if (descriptor != null)
{
- builder.Services.Remove(descriptor);
+ _ = builder.Services.Remove(descriptor);
}
return builder;
@@ -338,7 +340,7 @@ public static IImageSharpBuilder RemoveConverter(this IImageSharpBui
/// The .
public static IImageSharpBuilder ClearConverters(this IImageSharpBuilder builder)
{
- builder.Services.RemoveAll();
+ _ = builder.Services.RemoveAll();
return builder;
}
@@ -350,10 +352,12 @@ public static IImageSharpBuilder ClearConverters(this IImageSharpBuilder builder
/// The core builder.
/// The configuration being bound.
/// The .
- public static IImageSharpBuilder Configure(this IImageSharpBuilder builder, IConfiguration config)
+ [RequiresDynamicCode("Binding strongly typed objects to configuration values may require generating dynamic code at runtime.")]
+ [RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")]
+ public static IImageSharpBuilder Configure<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions>(this IImageSharpBuilder builder, IConfiguration config)
where TOptions : class
{
- builder.Services.Configure(config);
+ _ = builder.Services.Configure(config);
return builder;
}
@@ -368,7 +372,7 @@ public static IImageSharpBuilder Configure(this IImageSharpBuilder bui
public static IImageSharpBuilder Configure(this IImageSharpBuilder builder, Action configureOptions)
where TOptions : class
{
- builder.Services.Configure(configureOptions);
+ _ = builder.Services.Configure(configureOptions);
return builder;
}
diff --git a/src/ImageSharp.Web/Middleware/ImageSharpMiddleware.cs b/src/ImageSharp.Web/Middleware/ImageSharpMiddleware.cs
index 6bcde2e0..bfa8ac33 100644
--- a/src/ImageSharp.Web/Middleware/ImageSharpMiddleware.cs
+++ b/src/ImageSharp.Web/Middleware/ImageSharpMiddleware.cs
@@ -160,8 +160,8 @@ public ImageSharpMiddleware(
this.next = next;
this.options = options.Value;
this.requestParser = requestParser;
- this.providers = resolvers as IImageProvider[] ?? resolvers.ToArray();
- this.processors = processors as IImageWebProcessor[] ?? processors.ToArray();
+ this.providers = resolvers as IImageProvider[] ?? [.. resolvers];
+ this.processors = processors as IImageWebProcessor[] ?? [.. processors];
this.cache = cache;
this.cacheKey = cacheKey;
this.cacheHash = cacheHash;
@@ -344,7 +344,6 @@ private async Task ProcessRequestAsync(
await using (Stream inStream = await sourceImageResolver.OpenReadAsync())
{
- // TODO: Do we need some way to set options based upon processors?
DecoderOptions decoderOptions = await this.options.OnBeforeLoadAsync.Invoke(imageCommandContext, this.options.Configuration)
?? new() { Configuration = this.options.Configuration };
@@ -369,7 +368,7 @@ private async Task ProcessRequestAsync(
image = await FormattedImage.LoadAsync(decoderOptions, inStream);
}
- image.Process(
+ _ = image.Process(
this.logger,
sortedProcessors,
commands,
@@ -407,7 +406,7 @@ private async Task ProcessRequestAsync(
// Remove any resolver from the cache so we always resolve next request
// for the same key.
- CacheResolverLru.TryRemove(key);
+ _ = CacheResolverLru.TryRemove(key);
readResult = new ImageWorkerResult(cachedImageMetadata, null);
}
@@ -469,7 +468,7 @@ private async Task IsNewOrUpdatedAsync(
if (cachedImage.ImageCacheResolver is null)
{
// Remove the null resolver from the store.
- CacheResolverLru.TryRemove(key);
+ _ = CacheResolverLru.TryRemove(key);
return new ImageWorkerResult(sourceImageMetadata);
}
@@ -481,7 +480,7 @@ private async Task IsNewOrUpdatedAsync(
|| cachedImage.ImageCacheMetadata.SourceLastWriteTimeUtc != sourceImageMetadata.LastWriteTimeUtc)
{
// We want to remove the resolver from the store so that the next check gets the updated file.
- CacheResolverLru.TryRemove(key);
+ _ = CacheResolverLru.TryRemove(key);
return new ImageWorkerResult(sourceImageMetadata);
}
@@ -534,7 +533,7 @@ private async Task SendResponseAsync(
// The image has failed to be returned from the cache.
// This can happen if the cached image has been physically deleted but the item is still in the LRU cache.
// We'll retry running the request again in it's entirety. This ensures any changes to the source are tracked also.
- CacheResolverLru.TryRemove(key);
+ _ = CacheResolverLru.TryRemove(key);
await this.Invoke(httpContext, true);
return;
}
diff --git a/src/ImageSharp.Web/Middleware/ImageSharpMiddlewareOptions.cs b/src/ImageSharp.Web/Middleware/ImageSharpMiddlewareOptions.cs
index fa4c21e6..8653d4d4 100644
--- a/src/ImageSharp.Web/Middleware/ImageSharpMiddlewareOptions.cs
+++ b/src/ImageSharp.Web/Middleware/ImageSharpMiddlewareOptions.cs
@@ -81,7 +81,7 @@ public class ImageSharpMiddlewareOptions
///
/// The key can be any length. However, the recommended size is at least 64 bytes. If the length is zero then no authentication is performed.
///
- public byte[] HMACSecretKey { get; set; } = Array.Empty();
+ public byte[] HMACSecretKey { get; set; } = [];
///
/// Gets or sets the method used to compute a Hash-based Message Authentication Code (HMAC) for request authentication.
diff --git a/src/ImageSharp.Web/Middleware/LoggerExtensions.cs b/src/ImageSharp.Web/Middleware/LoggerExtensions.cs
index 7f158e8a..0b2b0676 100644
--- a/src/ImageSharp.Web/Middleware/LoggerExtensions.cs
+++ b/src/ImageSharp.Web/Middleware/LoggerExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using Microsoft.Extensions.Logging;
@@ -54,9 +54,7 @@ static LoggerExtensions()
/// The full request uri.
/// The captured exception.
public static void LogImageProcessingFailed(this ILogger logger, string uri, Exception exception)
- {
- LogProcessingErrorAction(logger, uri, exception);
- }
+ => LogProcessingErrorAction(logger, uri, exception);
///
/// Logs that a given image could not be resolved.
@@ -64,9 +62,7 @@ public static void LogImageProcessingFailed(this ILogger logger, string uri, Exc
/// The type used to perform logging.
/// The full request uri.
public static void LogImageResolveFailed(this ILogger logger, string uri)
- {
- LogResolveFailedAction(logger, uri, null);
- }
+ => LogResolveFailedAction(logger, uri, null);
///
/// Logs that a given image request has been served.
@@ -75,9 +71,7 @@ public static void LogImageResolveFailed(this ILogger logger, string uri)
/// The full request uri.
/// The cached image key.
public static void LogImageServed(this ILogger logger, string uri, string key)
- {
- LogServedAction(logger, uri, key, null);
- }
+ => LogServedAction(logger, uri, key, null);
///
/// Logs that a given image request has not been modified.
@@ -85,9 +79,7 @@ public static void LogImageServed(this ILogger logger, string uri, string key)
/// The type used to perform logging.
/// The full request uri.
public static void LogImageNotModified(this ILogger logger, string uri)
- {
- LogPathNotModifiedAction(logger, uri, null);
- }
+ => LogPathNotModifiedAction(logger, uri, null);
///
/// Logs that access to a given image request has been denied.
@@ -95,7 +87,5 @@ public static void LogImageNotModified(this ILogger logger, string uri)
/// The type used to perform logging.
/// The full request uri.
public static void LogImagePreconditionFailed(this ILogger logger, string uri)
- {
- LogPreconditionFailedAction(logger, uri, null);
- }
+ => LogPreconditionFailedAction(logger, uri, null);
}
diff --git a/src/ImageSharp.Web/PathUtilities.cs b/src/ImageSharp.Web/PathUtilities.cs
index 719b2e27..7e02d907 100644
--- a/src/ImageSharp.Web/PathUtilities.cs
+++ b/src/ImageSharp.Web/PathUtilities.cs
@@ -15,7 +15,7 @@ internal static class PathUtilities
internal static string EnsureTrailingSlash(string path)
{
if (!string.IsNullOrEmpty(path) &&
- path[path.Length - 1] != Path.DirectorySeparatorChar)
+ path[^1] != Path.DirectorySeparatorChar)
{
return path + Path.DirectorySeparatorChar;
}
diff --git a/src/ImageSharp.Web/Processors/IImageWebProcessor.cs b/src/ImageSharp.Web/Processors/IImageWebProcessor.cs
index df0cdb22..f5d27825 100644
--- a/src/ImageSharp.Web/Processors/IImageWebProcessor.cs
+++ b/src/ImageSharp.Web/Processors/IImageWebProcessor.cs
@@ -15,7 +15,7 @@ public interface IImageWebProcessor
///
/// Gets the collection of recognized command keys.
///
- IEnumerable Commands { get; }
+ public IEnumerable Commands { get; }
///
/// Processes the image based on the given commands.
@@ -28,7 +28,7 @@ public interface IImageWebProcessor
/// The to use as the current parsing culture.
///
/// The .
- FormattedImage Process(
+ public FormattedImage Process(
FormattedImage image,
ILogger logger,
CommandCollection commands,
@@ -48,5 +48,5 @@ FormattedImage Process(
/// The to use as the current parsing culture.
///
/// The indicating whether a 32 bit True Color pixel format is required.
- bool RequiresTrueColorPixelFormat(CommandCollection commands, CommandParser parser, CultureInfo culture);
+ public bool RequiresTrueColorPixelFormat(CommandCollection commands, CommandParser parser, CultureInfo culture);
}
diff --git a/src/ImageSharp.Web/Processors/ResizeWebProcessor.cs b/src/ImageSharp.Web/Processors/ResizeWebProcessor.cs
index 4004bfba..ebe44123 100644
--- a/src/ImageSharp.Web/Processors/ResizeWebProcessor.cs
+++ b/src/ImageSharp.Web/Processors/ResizeWebProcessor.cs
@@ -264,7 +264,7 @@ private static ushort GetExifOrientation(FormattedImage image, CommandCollection
return ExifOrientationMode.Unknown;
}
- image.TryGetExifOrientation(out ushort orientation);
+ _ = image.TryGetExifOrientation(out ushort orientation);
return orientation;
}
diff --git a/src/ImageSharp.Web/Processors/WebProcessingExtensions.cs b/src/ImageSharp.Web/Processors/WebProcessingExtensions.cs
index ada16b3d..4f0bba55 100644
--- a/src/ImageSharp.Web/Processors/WebProcessingExtensions.cs
+++ b/src/ImageSharp.Web/Processors/WebProcessingExtensions.cs
@@ -50,11 +50,11 @@ public static FormattedImage Process(
///
public static IReadOnlyList<(int Index, IImageWebProcessor Processor)> OrderBySupportedCommands(this IEnumerable processors, CommandCollection commands)
{
- List<(int Index, IImageWebProcessor Processor)> indexedProcessors = new();
+ List<(int Index, IImageWebProcessor Processor)> indexedProcessors = [];
foreach (IImageWebProcessor processor in processors)
{
// Get index of first supported command
- int index = commands.FindIndex(c => processor.IsSupportedCommand(c));
+ int index = commands.FindIndex(processor.IsSupportedCommand);
if (index != -1)
{
indexedProcessors.Add((index, processor));
diff --git a/src/ImageSharp.Web/Providers/IImageProvider.cs b/src/ImageSharp.Web/Providers/IImageProvider.cs
index 6de0c68d..b291e765 100644
--- a/src/ImageSharp.Web/Providers/IImageProvider.cs
+++ b/src/ImageSharp.Web/Providers/IImageProvider.cs
@@ -14,12 +14,12 @@ public interface IImageProvider
///
/// Gets the processing behavior.
///
- ProcessingBehavior ProcessingBehavior { get; }
+ public ProcessingBehavior ProcessingBehavior { get; }
///
/// Gets or sets the method used by the resolver to identify itself as the correct resolver to use.
///
- Func Match { get; set; }
+ public Func Match { get; set; }
///
/// Gets a value indicating whether the current request passes sanitizing rules.
@@ -28,12 +28,12 @@ public interface IImageProvider
///
/// The
///
- bool IsValidRequest(HttpContext context);
+ public bool IsValidRequest(HttpContext context);
///
/// Gets the image resolver associated with the context.
///
/// The current HTTP request context.
/// The .
- Task GetAsync(HttpContext context);
+ public Task GetAsync(HttpContext context);
}
diff --git a/src/ImageSharp.Web/RequestAuthorizationUtilities.cs b/src/ImageSharp.Web/RequestAuthorizationUtilities.cs
index 970a2e89..8876689a 100644
--- a/src/ImageSharp.Web/RequestAuthorizationUtilities.cs
+++ b/src/ImageSharp.Web/RequestAuthorizationUtilities.cs
@@ -62,7 +62,7 @@ public RequestAuthorizationUtilities(
{
foreach (string command in processor.Commands)
{
- commands.Add(command);
+ _ = commands.Add(command);
}
}
@@ -78,7 +78,7 @@ public void StripUnknownCommands(CommandCollection commands)
if (commands?.Count > 0)
{
// Strip out any unknown commands, if needed.
- List keys = new(commands.Keys);
+ List keys = [.. commands.Keys];
for (int i = keys.Count - 1; i >= 0; i--)
{
if (!this.knownCommands.Contains(keys[i]))
@@ -207,7 +207,7 @@ private static void ToComponents(
}
}
- private HttpContext ToHttpContext(HostString host, PathString path, QueryString queryString, QueryCollection query)
+ private DefaultHttpContext ToHttpContext(HostString host, PathString path, QueryString queryString, QueryCollection query)
{
DefaultHttpContext context = new() { RequestServices = this.serviceProvider };
HttpRequest request = context.Request;
diff --git a/src/ImageSharp.Web/Resolvers/IImageCacheResolver.cs b/src/ImageSharp.Web/Resolvers/IImageCacheResolver.cs
index b629bb86..8ac95a72 100644
--- a/src/ImageSharp.Web/Resolvers/IImageCacheResolver.cs
+++ b/src/ImageSharp.Web/Resolvers/IImageCacheResolver.cs
@@ -12,11 +12,11 @@ public interface IImageCacheResolver
/// Asynchronously gets metadata associated with this image.
///
/// The .
- Task GetMetaDataAsync();
+ public Task GetMetaDataAsync();
///
/// Asynchronously gets the input image stream.
///
/// The .
- Task OpenReadAsync();
+ public Task OpenReadAsync();
}
diff --git a/src/ImageSharp.Web/Resolvers/IImageResolver.cs b/src/ImageSharp.Web/Resolvers/IImageResolver.cs
index 72d6dfb0..55730536 100644
--- a/src/ImageSharp.Web/Resolvers/IImageResolver.cs
+++ b/src/ImageSharp.Web/Resolvers/IImageResolver.cs
@@ -12,11 +12,11 @@ public interface IImageResolver
/// Asynchronously gets metadata associated with this image.
///
/// The .
- Task GetMetaDataAsync();
+ public Task GetMetaDataAsync();
///
/// Asynchronously gets the input image stream.
///
/// The .
- Task OpenReadAsync();
+ public Task OpenReadAsync();
}
diff --git a/src/ImageSharp.Web/ServiceCollectionExtensions.cs b/src/ImageSharp.Web/ServiceCollectionExtensions.cs
new file mode 100644
index 00000000..1b758add
--- /dev/null
+++ b/src/ImageSharp.Web/ServiceCollectionExtensions.cs
@@ -0,0 +1,125 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using Microsoft.Extensions.DependencyInjection;
+using SixLabors.ImageSharp.Web;
+using SixLabors.ImageSharp.Web.Caching;
+using SixLabors.ImageSharp.Web.Commands;
+using SixLabors.ImageSharp.Web.Commands.Converters;
+using SixLabors.ImageSharp.Web.Middleware;
+using SixLabors.ImageSharp.Web.Processors;
+using SixLabors.ImageSharp.Web.Providers;
+using SixLabors.ImageSharp.Web.Synchronization;
+
+namespace SixLabors.ImageSharp.Web;
+
+///
+/// Extension methods for to simplify middleware service registration.
+///
+public static class ServiceCollectionExtensions
+{
+ ///
+ /// Adds ImageSharp services to the specified with the default options.
+ ///
+ /// The to add services to.
+ /// An that can be used to further configure the ImageSharp services.
+ public static IImageSharpBuilder AddImageSharp(this IServiceCollection services)
+ => AddImageSharp(services, _ => { });
+
+ ///
+ /// Adds ImageSharp services to the specified with the given options.
+ ///
+ /// The to add services to.
+ /// An to configure the provided .
+ /// An that can be used to further configure the ImageSharp services.
+ public static IImageSharpBuilder AddImageSharp(
+ this IServiceCollection services,
+ Action setupAction)
+ {
+ Guard.NotNull(services, nameof(services));
+ Guard.NotNull(setupAction, nameof(setupAction));
+
+ IImageSharpBuilder builder = new ImageSharpBuilder(services);
+
+ AddDefaultServices(builder, setupAction);
+
+ return builder;
+ }
+
+ private static void AddDefaultServices(
+ IImageSharpBuilder builder,
+ Action setupAction)
+ {
+ _ = builder.Services.Configure(setupAction);
+
+ _ = builder.Services.AddSingleton();
+
+ _ = builder.Services.AddSingleton>();
+
+ _ = builder.SetRequestParser();
+
+ _ = builder.Services.AddSingleton();
+
+ _ = builder.SetCache();
+
+ _ = builder.SetCacheKey();
+
+ _ = builder.SetCacheHash();
+
+ _ = builder.AddProvider();
+
+ _ = builder.AddProcessor()
+ .AddProcessor()
+ .AddProcessor()
+ .AddProcessor()
+ .AddProcessor();
+
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+ _ = builder.AddConverter>();
+
+ _ = builder.AddConverter();
+ _ = builder.AddConverter();
+
+ _ = builder.Services.AddSingleton();
+ }
+}
diff --git a/src/ImageSharp.Web/Synchronization/AsyncKeyLock.cs b/src/ImageSharp.Web/Synchronization/AsyncKeyLock.cs
index 13cd5b95..c6a98349 100644
--- a/src/ImageSharp.Web/Synchronization/AsyncKeyLock.cs
+++ b/src/ImageSharp.Web/Synchronization/AsyncKeyLock.cs
@@ -25,7 +25,7 @@ public sealed class AsyncKeyLock : IDisposable
/// The maximum number of locks that should be pooled for reuse.
public AsyncKeyLock(int maxPoolSize = 64)
{
- this.pool = new ConcurrentBag();
+ this.pool = [];
this.activeLocks = new RefCountedConcurrentDictionary(this.CreateLeasedLock, this.ReturnLeasedLock);
this.maxPoolSize = maxPoolSize;
}
diff --git a/src/ImageSharp.Web/Synchronization/AsyncKeyReaderWriterLock.cs b/src/ImageSharp.Web/Synchronization/AsyncKeyReaderWriterLock.cs
index 94557389..894fd67d 100644
--- a/src/ImageSharp.Web/Synchronization/AsyncKeyReaderWriterLock.cs
+++ b/src/ImageSharp.Web/Synchronization/AsyncKeyReaderWriterLock.cs
@@ -25,7 +25,7 @@ public class AsyncKeyReaderWriterLock
/// The maximum number of locks that should be pooled for reuse.
public AsyncKeyReaderWriterLock(int maxPoolSize = 64)
{
- this.pool = new ConcurrentBag();
+ this.pool = [];
this.activeLocks = new RefCountedConcurrentDictionary(this.CreateLeasedLock, this.ReturnLeasedLock);
this.maxPoolSize = maxPoolSize;
}
diff --git a/src/ImageSharp.Web/TagHelpers/ImageTagHelper.cs b/src/ImageSharp.Web/TagHelpers/ImageTagHelper.cs
index cf7c675e..8f402b18 100644
--- a/src/ImageSharp.Web/TagHelpers/ImageTagHelper.cs
+++ b/src/ImageSharp.Web/TagHelpers/ImageTagHelper.cs
@@ -198,7 +198,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
output.CopyHtmlAttribute(SrcAttributeName, context);
this.ProcessUrlAttribute(SrcAttributeName, output);
- CommandCollection commands = new();
+ CommandCollection commands = [];
this.AddProcessingCommands(context, output, commands, this.parserCulture);
if (commands.Count > 0)
diff --git a/tests/ImageSharp.Web.Benchmarks/Caching/CacheHashBaseline.cs b/tests/ImageSharp.Web.Benchmarks/Caching/CacheHashBaseline.cs
index f91b3239..9c21dabf 100644
--- a/tests/ImageSharp.Web.Benchmarks/Caching/CacheHashBaseline.cs
+++ b/tests/ImageSharp.Web.Benchmarks/Caching/CacheHashBaseline.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using SixLabors.ImageSharp.Web.Caching;
@@ -20,18 +21,15 @@ public string Create(string value, uint length)
// {
// throw new ArgumentOutOfRangeException(nameof(length), $"Value must be greater than or equal to {2} and less than or equal to {64}.");
// }
- using (var hashAlgorithm = SHA256.Create())
+ // Concatenate the hash bytes into one long string.
+ int len = (int)length;
+ byte[] hash = SHA256.HashData(Encoding.ASCII.GetBytes(value));
+ StringBuilder sb = new(len);
+ for (int i = 0; i < len / 2; i++)
{
- // Concatenate the hash bytes into one long string.
- int len = (int)length;
- byte[] hash = hashAlgorithm.ComputeHash(Encoding.ASCII.GetBytes(value));
- var sb = new StringBuilder(len);
- for (int i = 0; i < len / 2; i++)
- {
- sb.Append(hash[i].ToString("X2"));
- }
-
- return sb.ToString();
+ sb.Append(hash[i].ToString("X2", CultureInfo.InvariantCulture));
}
+
+ return sb.ToString();
}
}
diff --git a/tests/ImageSharp.Web.Benchmarks/Caching/CacheHashBenchmarks.cs b/tests/ImageSharp.Web.Benchmarks/Caching/CacheHashBenchmarks.cs
index 3e816a73..c6d3438c 100644
--- a/tests/ImageSharp.Web.Benchmarks/Caching/CacheHashBenchmarks.cs
+++ b/tests/ImageSharp.Web.Benchmarks/Caching/CacheHashBenchmarks.cs
@@ -13,8 +13,8 @@ public class CacheHashBenchmarks
{
private const string URL = "http://testwebsite.com/image-12345.jpeg?width=400";
private static readonly IOptions MWOptions = Options.Create(new ImageSharpMiddlewareOptions());
- private static readonly SHA256CacheHash Sha256Hasher = new SHA256CacheHash(MWOptions);
- private static readonly CacheHashBaseline NaiveSha256Hasher = new CacheHashBaseline();
+ private static readonly SHA256CacheHash Sha256Hasher = new(MWOptions);
+ private static readonly CacheHashBaseline NaiveSha256Hasher = new();
[Benchmark(Baseline = true, Description = "Baseline Sha256Hasher")]
public string HashUsingBaselineHash() => NaiveSha256Hasher.Create(URL, 12);
diff --git a/tests/ImageSharp.Web.Benchmarks/Caching/CacheKeyBenchmarks.cs b/tests/ImageSharp.Web.Benchmarks/Caching/CacheKeyBenchmarks.cs
index b04d5fb6..96238e36 100644
--- a/tests/ImageSharp.Web.Benchmarks/Caching/CacheKeyBenchmarks.cs
+++ b/tests/ImageSharp.Web.Benchmarks/Caching/CacheKeyBenchmarks.cs
@@ -17,11 +17,11 @@ public class CacheKeyBenchmarks
{ "width", "400" }
};
- private static readonly ICacheKey LegacyV1CacheKey = new LegacyV1CacheKey();
- private static readonly ICacheKey UriRelativeCacheKey = new UriRelativeCacheKey();
- private static readonly ICacheKey UriAbsoluteCacheKey = new UriAbsoluteCacheKey();
- private static readonly ICacheKey UriRelativeLowerInvariantCacheKey = new UriRelativeLowerInvariantCacheKey();
- private static readonly ICacheKey UriAbsoluteLowerInvariantCacheKey = new UriAbsoluteLowerInvariantCacheKey();
+ private static readonly LegacyV1CacheKey LegacyV1CacheKey = new();
+ private static readonly UriRelativeCacheKey UriRelativeCacheKey = new();
+ private static readonly UriAbsoluteCacheKey UriAbsoluteCacheKey = new();
+ private static readonly UriRelativeLowerInvariantCacheKey UriRelativeLowerInvariantCacheKey = new();
+ private static readonly UriAbsoluteLowerInvariantCacheKey UriAbsoluteLowerInvariantCacheKey = new();
[Benchmark(Baseline = true, Description = nameof(LegacyV1CacheKey))]
public string CreateUsingBaseline() => LegacyV1CacheKey.Create(Context, Commands);
@@ -55,9 +55,9 @@ public class CacheKeyBenchmarks
| UriAbsoluteLowerInvariantCacheKey | 475.4 ns | 4.18 ns | 3.71 ns | 0.71 | 0.02 | 0.0763 | 320 B |
*/
- private static HttpContext CreateContext()
+ private static DefaultHttpContext CreateContext()
{
- var httpContext = new DefaultHttpContext();
+ DefaultHttpContext httpContext = new();
httpContext.Request.Scheme = Uri.UriSchemeHttp;
httpContext.Request.Host = new HostString("testwebsite.com");
httpContext.Request.PathBase = "/images";
diff --git a/tests/ImageSharp.Web.Benchmarks/Caching/StringJoinBenchmarks.cs b/tests/ImageSharp.Web.Benchmarks/Caching/StringJoinBenchmarks.cs
index 775d705d..b01dcca4 100644
--- a/tests/ImageSharp.Web.Benchmarks/Caching/StringJoinBenchmarks.cs
+++ b/tests/ImageSharp.Web.Benchmarks/Caching/StringJoinBenchmarks.cs
@@ -26,7 +26,7 @@ public string JoinUsingStringBuilder()
const char separator = '/';
// Each key substring char + separator + key
- var sb = new StringBuilder((this.CacheFolderDepth * 2) + Key.Length);
+ StringBuilder sb = new StringBuilder((this.CacheFolderDepth * 2) + Key.Length);
ReadOnlySpan paths = keySpan.Slice(0, this.CacheFolderDepth);
for (int i = 0; i < paths.Length; i++)
{
diff --git a/tests/ImageSharp.Web.Benchmarks/Caching/ToHexBenchmarks.cs b/tests/ImageSharp.Web.Benchmarks/Caching/ToHexBenchmarks.cs
index ec6ec7b2..baf2fafa 100644
--- a/tests/ImageSharp.Web.Benchmarks/Caching/ToHexBenchmarks.cs
+++ b/tests/ImageSharp.Web.Benchmarks/Caching/ToHexBenchmarks.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Globalization;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
@@ -18,10 +19,10 @@ public class ToHexBenchmarks
public string StringBuilderToHex()
{
const int len = 12;
- var sb = new StringBuilder(len);
+ StringBuilder sb = new(len);
for (int i = 0; i < len / 2; i++)
{
- sb.Append(Bytes[i].ToString("x2"));
+ sb.Append(Bytes[i].ToString("x2", CultureInfo.InvariantCulture));
}
return sb.ToString();
@@ -52,19 +53,16 @@ public string CustomToHex()
}
[Benchmark(Description = "HexEncoder.Encode with LUT")]
- public string CustomToHexUnsafe() => HexEncoder.Encode(new Span(Bytes).Slice(0, 6));
+ public string CustomToHexUnsafe() => HexEncoder.Encode(new Span(Bytes)[..6]);
private static byte[] Hash()
{
- using (var hashAlgorithm = SHA256.Create())
- {
- // Concatenate the hash bytes into one long string.
- string value = "http://testwebsite.com/image-12345.jpeg?width=400";
- int byteCount = Encoding.ASCII.GetByteCount(value);
- byte[] buffer = new byte[byteCount];
- Encoding.ASCII.GetBytes(value, 0, value.Length, buffer, 0);
- return hashAlgorithm.ComputeHash(buffer, 0, byteCount);
- }
+ // Concatenate the hash bytes into one long string.
+ string value = "http://testwebsite.com/image-12345.jpeg?width=400";
+ int byteCount = Encoding.ASCII.GetByteCount(value);
+ byte[] buffer = new byte[byteCount];
+ Encoding.ASCII.GetBytes(value, 0, value.Length, buffer, 0);
+ return SHA256.HashData(buffer.AsSpan(0, byteCount));
}
/*
diff --git a/tests/ImageSharp.Web.Benchmarks/ImageSharp.Web.Benchmarks.csproj b/tests/ImageSharp.Web.Benchmarks/ImageSharp.Web.Benchmarks.csproj
index e1db5d1a..8912cfb8 100644
--- a/tests/ImageSharp.Web.Benchmarks/ImageSharp.Web.Benchmarks.csproj
+++ b/tests/ImageSharp.Web.Benchmarks/ImageSharp.Web.Benchmarks.csproj
@@ -1,4 +1,4 @@
-
+
Exe
@@ -9,15 +9,26 @@
false
+
+
+
+
+
+ CA1822;CA1001
+
+
- net7.0;net6.0
+ net8.0;net10.0
- net6.0
+ net8.0
diff --git a/tests/ImageSharp.Web.Tests/Caching/CacheHashTests.cs b/tests/ImageSharp.Web.Tests/Caching/CacheHashTests.cs
index ea2f4d25..fcca1041 100644
--- a/tests/ImageSharp.Web.Tests/Caching/CacheHashTests.cs
+++ b/tests/ImageSharp.Web.Tests/Caching/CacheHashTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Globalization;
using System.Text;
using Microsoft.Extensions.Options;
using SixLabors.ImageSharp.Web.Caching;
@@ -12,14 +13,14 @@ namespace SixLabors.ImageSharp.Web.Tests.Caching;
public class CacheHashTests
{
private static readonly IOptions Options = MSOptions.Create(new ImageSharpMiddlewareOptions());
- private static readonly ICacheHash CacheHash = new SHA256CacheHash(Options);
+ private static readonly SHA256CacheHash CacheHash = new(Options);
[Fact]
public void CacheHashProducesIdenticalResults()
{
- const string Input = "http://testwebsite.com/image-12345.jpeg?width=400";
- string expected = CacheHash.Create(Input, 8);
- string actual = CacheHash.Create(Input, 8);
+ const string input = "http://testwebsite.com/image-12345.jpeg?width=400";
+ string expected = CacheHash.Create(input, 8);
+ string actual = CacheHash.Create(input, 8);
Assert.Equal(expected, actual);
}
@@ -27,10 +28,10 @@ public void CacheHashProducesIdenticalResults()
[Fact]
public void CacheHashProducesDifferentResults()
{
- const string Input = "http://testwebsite.com/image-12345.jpeg?width=400";
- const string Input2 = "http://testwebsite.com/image-23456.jpeg?width=400";
- string expected = CacheHash.Create(Input, 8);
- string actual = CacheHash.Create(Input2, 8);
+ const string input = "http://testwebsite.com/image-12345.jpeg?width=400";
+ const string input2 = "http://testwebsite.com/image-23456.jpeg?width=400";
+ string expected = CacheHash.Create(input, 8);
+ string actual = CacheHash.Create(input2, 8);
Assert.NotEqual(expected, actual);
}
@@ -38,28 +39,28 @@ public void CacheHashProducesDifferentResults()
[Fact]
public void CacheHashLengthIsIdentical()
{
- const int Length = 12;
- const string Input = "http://testwebsite.com/image-12345.jpeg?width=400";
- const string Input2 = "http://testwebsite.com/image-12345.jpeg";
+ const int length = 12;
+ const string input = "http://testwebsite.com/image-12345.jpeg?width=400";
+ const string input2 = "http://testwebsite.com/image-12345.jpeg";
string input3 = CreateLongString();
- int expected = CacheHash.Create(Input, Length).Length;
- int actual = CacheHash.Create(Input2, Length).Length;
- int actual2 = CacheHash.Create(input3, Length).Length;
+ int expected = CacheHash.Create(input, length).Length;
+ int actual = CacheHash.Create(input2, length).Length;
+ int actual2 = CacheHash.Create(input3, length).Length;
Assert.Equal(expected, actual);
- Assert.Equal(Length, actual);
- Assert.Equal(Length, actual2);
+ Assert.Equal(length, actual);
+ Assert.Equal(length, actual2);
}
private static string CreateLongString()
{
- const int Length = 2048;
- var sb = new StringBuilder(Length);
+ const int length = 2048;
+ StringBuilder sb = new(length);
- for (int i = 0; i < Length; i++)
+ for (int i = 0; i < length; i++)
{
- sb.Append(i.ToString());
+ sb.Append(i.ToString(CultureInfo.InvariantCulture));
}
return sb.ToString();
diff --git a/tests/ImageSharp.Web.Tests/Caching/CacheKeyTests.cs b/tests/ImageSharp.Web.Tests/Caching/CacheKeyTests.cs
index 90317b67..2d82b596 100644
--- a/tests/ImageSharp.Web.Tests/Caching/CacheKeyTests.cs
+++ b/tests/ImageSharp.Web.Tests/Caching/CacheKeyTests.cs
@@ -9,17 +9,17 @@ namespace SixLabors.ImageSharp.Web.Tests.Caching;
public class CacheKeyTests
{
- private static readonly ICacheKey LegacyV1CacheKey = new LegacyV1CacheKey();
- private static readonly ICacheKey UriRelativeCacheKey = new UriRelativeCacheKey();
- private static readonly ICacheKey UriAbsoluteCacheKey = new UriAbsoluteCacheKey();
- private static readonly ICacheKey UriRelativeLowerInvariantCacheKey = new UriRelativeLowerInvariantCacheKey();
- private static readonly ICacheKey UriAbsoluteLowerInvariantCacheKey = new UriAbsoluteLowerInvariantCacheKey();
+ private static readonly LegacyV1CacheKey LegacyV1CacheKey = new();
+ private static readonly UriRelativeCacheKey UriRelativeCacheKey = new();
+ private static readonly UriAbsoluteCacheKey UriAbsoluteCacheKey = new();
+ private static readonly UriRelativeLowerInvariantCacheKey UriRelativeLowerInvariantCacheKey = new();
+ private static readonly UriAbsoluteLowerInvariantCacheKey UriAbsoluteLowerInvariantCacheKey = new();
[Fact]
public void UriRelativeCacheKey_Is_Relative()
{
HttpContext context = CreateHttpContext();
- var commands = new CommandCollection()
+ CommandCollection commands = new()
{
{ "Width", "400" }
};
@@ -34,7 +34,7 @@ public void UriRelativeCacheKey_Is_Relative()
public void UriRelativeLowerInvariantCacheKey_Is_RelativeAndLowercase()
{
HttpContext context = CreateHttpContext();
- var commands = new CommandCollection()
+ CommandCollection commands = new()
{
{ "Width", "400" }
};
@@ -49,7 +49,7 @@ public void UriRelativeLowerInvariantCacheKey_Is_RelativeAndLowercase()
public void UriAbsoluteCacheKey_Is_Absolute()
{
HttpContext context = CreateHttpContext();
- var commands = new CommandCollection()
+ CommandCollection commands = new()
{
{ "Width", "400" }
};
@@ -64,7 +64,7 @@ public void UriAbsoluteCacheKey_Is_Absolute()
public void UriAbsoluteLowerInvariantCacheKey_Is_AbsoluteAndLowercase()
{
HttpContext context = CreateHttpContext();
- var commands = new CommandCollection()
+ CommandCollection commands = new()
{
{ "Width", "400" }
};
@@ -79,7 +79,7 @@ public void UriAbsoluteLowerInvariantCacheKey_Is_AbsoluteAndLowercase()
public void LegacyV1CacheKey_Matches_V1_Behavior()
{
HttpContext context = CreateHttpContext();
- var commands = new CommandCollection()
+ CommandCollection commands = new()
{
{ "Width", "400" }
};
@@ -90,9 +90,9 @@ public void LegacyV1CacheKey_Matches_V1_Behavior()
Assert.Equal(expected, actual);
}
- private static HttpContext CreateHttpContext()
+ private static DefaultHttpContext CreateHttpContext()
{
- var httpContext = new DefaultHttpContext();
+ DefaultHttpContext httpContext = new();
httpContext.Request.Scheme = Uri.UriSchemeHttp;
httpContext.Request.Host = new HostString("Testwebsite.com");
httpContext.Request.PathBase = "/Images";
diff --git a/tests/ImageSharp.Web.Tests/Caching/HexEncoderTests.cs b/tests/ImageSharp.Web.Tests/Caching/HexEncoderTests.cs
index 21eb5203..de513fb7 100644
--- a/tests/ImageSharp.Web.Tests/Caching/HexEncoderTests.cs
+++ b/tests/ImageSharp.Web.Tests/Caching/HexEncoderTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using SixLabors.ImageSharp.Web.Caching;
@@ -13,10 +14,10 @@ public class HexEncoderTests
public void HexEncoderOutputIsCorrect()
{
byte[] hash = Hash();
- var sb = new StringBuilder(hash.Length * 2);
+ StringBuilder sb = new(hash.Length * 2);
for (int i = 0; i < hash.Length; i++)
{
- sb.Append(hash[i].ToString("x2"));
+ sb.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture));
}
string expected = sb.ToString();
@@ -27,14 +28,11 @@ public void HexEncoderOutputIsCorrect()
private static byte[] Hash()
{
- using (var hashAlgorithm = SHA256.Create())
- {
- // Concatenate the hash bytes into one long string.
- const string Value = "http://testwebsite.com/image-12345.jpeg?width=400";
- int byteCount = Encoding.ASCII.GetByteCount(Value);
- byte[] buffer = new byte[byteCount];
- Encoding.ASCII.GetBytes(Value, 0, Value.Length, buffer, 0);
- return hashAlgorithm.ComputeHash(buffer, 0, byteCount);
- }
+ // Concatenate the hash bytes into one long string.
+ const string value = "http://testwebsite.com/image-12345.jpeg?width=400";
+ int byteCount = Encoding.ASCII.GetByteCount(value);
+ byte[] buffer = new byte[byteCount];
+ Encoding.ASCII.GetBytes(value, 0, value.Length, buffer, 0);
+ return SHA256.HashData(buffer.AsSpan(0, byteCount));
}
}
diff --git a/tests/ImageSharp.Web.Tests/Caching/ImageCacheMetadataTests.cs b/tests/ImageSharp.Web.Tests/Caching/ImageCacheMetadataTests.cs
index 93358615..72c7ad19 100644
--- a/tests/ImageSharp.Web.Tests/Caching/ImageCacheMetadataTests.cs
+++ b/tests/ImageSharp.Web.Tests/Caching/ImageCacheMetadataTests.cs
@@ -7,8 +7,8 @@ namespace SixLabors.ImageSharp.Web.Tests.Caching;
public class ImageCacheMetaDataTests
{
- private static readonly DateTime SourceLastWriteTimeUtc = new DateTime(1980, 11, 3);
- private static readonly DateTime CacheLastWriteTimeUtc = new DateTime(1980, 11, 4);
+ private static readonly DateTime SourceLastWriteTimeUtc = new(1980, 11, 3);
+ private static readonly DateTime CacheLastWriteTimeUtc = new(1980, 11, 4);
private static readonly TimeSpan MaxAge = TimeSpan.FromDays(7);
private const string ContentType = "image/jpeg";
private const long ContentLength = 1234;
@@ -20,7 +20,7 @@ public class ImageCacheMetaDataTests
[Fact]
public void ConstructorAssignsProperties()
{
- var meta = new ImageCacheMetadata(
+ ImageCacheMetadata meta = new(
SourceLastWriteTimeUtc,
CacheLastWriteTimeUtc,
ContentType,
@@ -37,13 +37,13 @@ public void ConstructorAssignsProperties()
[Fact]
public void EqualityChecksAreCorrect()
{
- var meta = new ImageCacheMetadata(
+ ImageCacheMetadata meta = new(
SourceLastWriteTimeUtc,
CacheLastWriteTimeUtc,
ContentType,
MaxAge,
ContentLength);
- var meta2 = new ImageCacheMetadata(
+ ImageCacheMetadata meta2 = new(
meta.SourceLastWriteTimeUtc,
meta.CacheLastWriteTimeUtc,
meta.ContentType,
@@ -52,7 +52,7 @@ public void EqualityChecksAreCorrect()
Assert.Equal(meta, meta2);
- var meta3 = new ImageCacheMetadata(
+ ImageCacheMetadata meta3 = new(
SourceLastWriteTimeUtc,
CacheLastWriteTimeUtc,
"image/png",
@@ -61,4 +61,25 @@ public void EqualityChecksAreCorrect()
Assert.NotEqual(meta, meta3);
}
+
+ [Fact]
+ public async Task WriteAsyncRoundTripsViaReadAsync()
+ {
+ ImageCacheMetadata metadata = new(
+ SourceLastWriteTimeUtc,
+ CacheLastWriteTimeUtc,
+ ContentType,
+ MaxAge,
+ ContentLength);
+
+ MemoryStream stream = new();
+ await metadata.WriteAsync(stream);
+
+ byte[] data = stream.ToArray();
+
+ await using MemoryStream readStream = new(data);
+ ImageCacheMetadata roundTrip = await ImageCacheMetadata.ReadAsync(readStream);
+
+ Assert.Equal(metadata, roundTrip);
+ }
}
diff --git a/tests/ImageSharp.Web.Tests/Commands/CommandParserTests.cs b/tests/ImageSharp.Web.Tests/Commands/CommandParserTests.cs
index a8b7ed70..29a293c3 100644
--- a/tests/ImageSharp.Web.Tests/Commands/CommandParserTests.cs
+++ b/tests/ImageSharp.Web.Tests/Commands/CommandParserTests.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Web.Tests.Commands;
public class CommandParserTests
{
private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;
- private static readonly CultureInfo Dk = new CultureInfo("da-DK");
+ private static readonly CultureInfo Dk = new("da-DK");
private const double Pi = 3.14159265358979;
private static readonly string PiStringInv = Pi.ToString(CultureInfo.InvariantCulture);
@@ -63,7 +63,7 @@ public class CommandParserTests
{ (long)RoundedPi, PiStringInv, Inv },
{ (ulong)RoundedPi, PiStringInv, Inv },
{ (float)Pi, PiStringInv, Inv },
- { (double)Pi, PiStringInv, Inv },
+ { Pi, PiStringInv, Inv },
{ (decimal)Pi, PiStringInv, Inv },
};
@@ -79,7 +79,7 @@ public class CommandParserTests
{ (long)RoundedPi, PiStringDk, Dk },
{ (ulong)RoundedPi, PiStringDk, Dk },
{ (float)Pi, PiStringDk, Dk },
- { (double)Pi, PiStringDk, Dk },
+ { Pi, PiStringDk, Dk },
{ (decimal)Pi, PiStringDk, Dk },
};
@@ -169,7 +169,7 @@ public void CommandParserCanConvert(T expected, string param, CultureInfo cul
[Fact]
public void CommandParseThrowsCorrectly()
{
- var emptyParser = new CommandParser(Array.Empty());
+ CommandParser emptyParser = new(Array.Empty());
Assert.Throws(
() => emptyParser.ParseValue("true", CultureInfo.InvariantCulture));
@@ -177,8 +177,8 @@ public void CommandParseThrowsCorrectly()
private static CommandParser GetCommandParser()
{
- var converters = new List
- {
+ List converters =
+ [
new IntegralNumberConverter(),
new IntegralNumberConverter(),
new IntegralNumberConverter(),
@@ -224,7 +224,7 @@ private static CommandParser GetCommandParser()
new ListConverter(),
new ListConverter(),
new ListConverter()
- };
+ ];
return new CommandParser(converters);
}
@@ -232,12 +232,14 @@ private static CommandParser GetCommandParser()
private static string ToNumericList(CultureInfo culture, params T[] values)
where T : IConvertible
{
- var sb = new StringBuilder();
- var ls = culture.TextInfo.ListSeparator[0];
+ StringBuilder sb = new();
+ char ls = culture.TextInfo.ListSeparator[0];
for (int i = 0; i < values.Length; i++)
{
+#pragma warning disable CA1305 // Specify IFormatProvider
sb.AppendFormat(values[i].ToString(culture) + ls);
+#pragma warning restore CA1305 // Specify IFormatProvider
}
return sb.ToString().TrimEnd(ls);
diff --git a/tests/ImageSharp.Web.Tests/Commands/PresetOnlyQueryCollectionRequestParserTests.cs b/tests/ImageSharp.Web.Tests/Commands/PresetOnlyQueryCollectionRequestParserTests.cs
index 39446044..a1f4f06f 100644
--- a/tests/ImageSharp.Web.Tests/Commands/PresetOnlyQueryCollectionRequestParserTests.cs
+++ b/tests/ImageSharp.Web.Tests/Commands/PresetOnlyQueryCollectionRequestParserTests.cs
@@ -85,9 +85,9 @@ public void PresetOnlyQueryCollectionRequestParserCommandsWithoutMatchingPreset(
Assert.Equal(expected, actual);
}
- private static HttpContext CreateHttpContext(string query)
+ private static DefaultHttpContext CreateHttpContext(string query)
{
- var httpContext = new DefaultHttpContext();
+ DefaultHttpContext httpContext = new();
httpContext.Request.Path = "/testwebsite.com/image-12345.jpeg";
httpContext.Request.QueryString = new QueryString(query);
return httpContext;
diff --git a/tests/ImageSharp.Web.Tests/Commands/QueryCollectionUriParserTests.cs b/tests/ImageSharp.Web.Tests/Commands/QueryCollectionUriParserTests.cs
index 1b01577d..8a2a5d2d 100644
--- a/tests/ImageSharp.Web.Tests/Commands/QueryCollectionUriParserTests.cs
+++ b/tests/ImageSharp.Web.Tests/Commands/QueryCollectionUriParserTests.cs
@@ -23,9 +23,9 @@ public void QueryCollectionParserExtractsCommands()
Assert.Equal(expected, actual);
}
- private static HttpContext CreateHttpContext()
+ private static DefaultHttpContext CreateHttpContext()
{
- var httpContext = new DefaultHttpContext();
+ DefaultHttpContext httpContext = new();
httpContext.Request.Path = "/testwebsite.com/image-12345.jpeg";
// Duplicate height param to test replacements
diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockCacheHash.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeCacheHash.cs
similarity index 86%
rename from tests/ImageSharp.Web.Tests/DependencyInjection/MockCacheHash.cs
rename to tests/ImageSharp.Web.Tests/DependencyInjection/FakeCacheHash.cs
index 56657f77..0f820c44 100644
--- a/tests/ImageSharp.Web.Tests/DependencyInjection/MockCacheHash.cs
+++ b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeCacheHash.cs
@@ -5,7 +5,7 @@
namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection;
-public class MockCacheHash : ICacheHash
+public class FakeCacheHash : ICacheHash
{
public string Create(string value, uint length) => null;
}
diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockCacheKey.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeCacheKey.cs
similarity index 90%
rename from tests/ImageSharp.Web.Tests/DependencyInjection/MockCacheKey.cs
rename to tests/ImageSharp.Web.Tests/DependencyInjection/FakeCacheKey.cs
index 3a19b217..6280f271 100644
--- a/tests/ImageSharp.Web.Tests/DependencyInjection/MockCacheKey.cs
+++ b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeCacheKey.cs
@@ -7,7 +7,7 @@
namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection;
-public class MockCacheKey : ICacheKey
+public class FakeCacheKey : ICacheKey
{
public string Create(HttpContext context, CommandCollection commands) => null;
}
diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockCommandConverter.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeCommandConverter.cs
similarity index 78%
rename from tests/ImageSharp.Web.Tests/DependencyInjection/MockCommandConverter.cs
rename to tests/ImageSharp.Web.Tests/DependencyInjection/FakeCommandConverter.cs
index 2bc47c0a..8283c8bd 100644
--- a/tests/ImageSharp.Web.Tests/DependencyInjection/MockCommandConverter.cs
+++ b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeCommandConverter.cs
@@ -7,9 +7,9 @@
namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection;
-public class MockCommandConverter : ICommandConverter
+public class FakeCommandConverter : ICommandConverter
{
- public Type Type => typeof(MockCommandConverter);
+ public Type Type => typeof(FakeCommandConverter);
public object ConvertFrom(
CommandParser parser,
diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockImageCache.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeImageCache.cs
similarity index 91%
rename from tests/ImageSharp.Web.Tests/DependencyInjection/MockImageCache.cs
rename to tests/ImageSharp.Web.Tests/DependencyInjection/FakeImageCache.cs
index abfc656b..6e8e58a3 100644
--- a/tests/ImageSharp.Web.Tests/DependencyInjection/MockImageCache.cs
+++ b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeImageCache.cs
@@ -6,7 +6,7 @@
namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection;
-public class MockImageCache : IImageCache
+public class FakeImageCache : IImageCache
{
public Task GetAsync(string key) => Task.FromResult(null);
diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockImageProvider.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeImageProvider.cs
similarity index 92%
rename from tests/ImageSharp.Web.Tests/DependencyInjection/MockImageProvider.cs
rename to tests/ImageSharp.Web.Tests/DependencyInjection/FakeImageProvider.cs
index 602f10f5..eacd412e 100644
--- a/tests/ImageSharp.Web.Tests/DependencyInjection/MockImageProvider.cs
+++ b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeImageProvider.cs
@@ -7,7 +7,7 @@
namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection;
-public class MockImageProvider : IImageProvider
+public class FakeImageProvider : IImageProvider
{
public ProcessingBehavior ProcessingBehavior { get; set; } = ProcessingBehavior.All;
diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockRequestParser.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeRequestParser.cs
similarity index 86%
rename from tests/ImageSharp.Web.Tests/DependencyInjection/MockRequestParser.cs
rename to tests/ImageSharp.Web.Tests/DependencyInjection/FakeRequestParser.cs
index d9c2ad24..9cc128ea 100644
--- a/tests/ImageSharp.Web.Tests/DependencyInjection/MockRequestParser.cs
+++ b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeRequestParser.cs
@@ -6,7 +6,7 @@
namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection;
-public class MockRequestParser : IRequestParser
+public class FakeRequestParser : IRequestParser
{
public CommandCollection ParseRequestCommands(HttpContext context) => null;
}
diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockWebProcessor.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeWebProcessor.cs
similarity index 93%
rename from tests/ImageSharp.Web.Tests/DependencyInjection/MockWebProcessor.cs
rename to tests/ImageSharp.Web.Tests/DependencyInjection/FakeWebProcessor.cs
index e2328def..a68432b6 100644
--- a/tests/ImageSharp.Web.Tests/DependencyInjection/MockWebProcessor.cs
+++ b/tests/ImageSharp.Web.Tests/DependencyInjection/FakeWebProcessor.cs
@@ -8,7 +8,7 @@
namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection;
-public class MockWebProcessor : IImageWebProcessor
+public class FakeWebProcessor : IImageWebProcessor
{
public IEnumerable Commands => Array.Empty();
diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/ServiceRegistrationExtensionsTests.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/ServiceRegistrationExtensionsTests.cs
index 4a22a158..7098c147 100644
--- a/tests/ImageSharp.Web.Tests/DependencyInjection/ServiceRegistrationExtensionsTests.cs
+++ b/tests/ImageSharp.Web.Tests/DependencyInjection/ServiceRegistrationExtensionsTests.cs
@@ -6,7 +6,6 @@
using SixLabors.ImageSharp.Web.Caching;
using SixLabors.ImageSharp.Web.Commands;
using SixLabors.ImageSharp.Web.Commands.Converters;
-using SixLabors.ImageSharp.Web.DependencyInjection;
using SixLabors.ImageSharp.Web.Processors;
using SixLabors.ImageSharp.Web.Providers;
@@ -39,12 +38,12 @@ private static bool IsServiceImplementationFactory(Se
(descriptor.ImplementationFactory?.GetMethodInfo().ReturnType == typeof(TImplementation) ||
descriptor.ImplementationFactory?.Invoke(null)?.GetType() == typeof(TImplementation)); // OK to invoke the factory in tests
- private static IReadOnlyList GetCollection(IServiceCollection serviceDescriptors) => serviceDescriptors.Where(x => x.ServiceType == typeof(T)).ToList();
+ private static List GetCollection(IServiceCollection serviceDescriptors) => [.. serviceDescriptors.Where(x => x.ServiceType == typeof(T))];
[Fact]
public void DefaultServicesAreRegistered()
{
- var services = new ServiceCollection();
+ ServiceCollection services = new();
services.AddImageSharp();
Assert.Single(services, IsService);
@@ -104,178 +103,178 @@ public void DefaultServicesAreRegistered()
[Fact]
public void CanSetRequestParser()
{
- var services = new ServiceCollection();
+ ServiceCollection services = new();
IImageSharpBuilder builder = services.AddImageSharp();
- builder.SetRequestParser();
+ builder.SetRequestParser();
Assert.Single(services, IsService);
- Assert.Single(services, IsServiceImplementationType);
+ Assert.Single(services, IsServiceImplementationType);
- builder.SetRequestParser(_ => new MockRequestParser());
+ builder.SetRequestParser(_ => new FakeRequestParser());
Assert.Single(services, IsService);
- Assert.Single(services, IsServiceImplementationFactory);
+ Assert.Single(services, IsServiceImplementationFactory);
}
[Fact]
public void CanSetCache()
{
- var services = new ServiceCollection();
+ ServiceCollection services = new();
IImageSharpBuilder builder = services.AddImageSharp();
- builder.SetCache();
+ builder.SetCache();
Assert.Single(services, IsService);
- Assert.Single(services, IsServiceImplementationType);
+ Assert.Single(services, IsServiceImplementationType);
- builder.SetCache(_ => new MockImageCache());
+ builder.SetCache(_ => new FakeImageCache());
Assert.Single(services, IsService);
- Assert.Single(services, IsServiceImplementationFactory);
+ Assert.Single(services, IsServiceImplementationFactory);
}
[Fact]
public void CanSetCacheKey()
{
- var services = new ServiceCollection();
+ ServiceCollection services = new();
IImageSharpBuilder builder = services.AddImageSharp();
- builder.SetCacheKey();
+ builder.SetCacheKey();
Assert.Single(services, IsService);
- Assert.Single(services, IsServiceImplementationType);
+ Assert.Single(services, IsServiceImplementationType);
- builder.SetCacheKey(_ => new MockCacheKey());
+ builder.SetCacheKey(_ => new FakeCacheKey());
Assert.Single(services, IsService);
- Assert.Single(services, IsServiceImplementationFactory);
+ Assert.Single(services, IsServiceImplementationFactory);
}
[Fact]
public void CanSetCacheHash()
{
- var services = new ServiceCollection();
+ ServiceCollection services = new();
IImageSharpBuilder builder = services.AddImageSharp();
- builder.SetCacheHash();
+ builder.SetCacheHash();
Assert.Single(services, IsService);
- Assert.Single(services, IsServiceImplementationType);
+ Assert.Single(services, IsServiceImplementationType);
- builder.SetCacheHash(_ => new MockCacheHash());
+ builder.SetCacheHash(_ => new FakeCacheHash());
Assert.Single(services, IsService);
- Assert.Single(services, IsServiceImplementationFactory