aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoroledfish <88390729+oledfish@users.noreply.github.com>2022-01-16 21:33:18 -0300
committerGitHub <noreply@github.com>2022-01-16 21:33:18 -0300
commit3b075a58027be4a2a3bdf662c70934f6cafafe87 (patch)
treeb4c226f25f843c3f2685c92e1edc3b3999716d34 /src
parent86a5e72a65df638df2cde349ccd2ad8c5d40f88c (diff)
parentef0708d876434a99ec647473c37295fab45a35fb (diff)
Merge branch 'jellyfin:master' into additional-episode-orders
Diffstat (limited to 'src')
-rw-r--r--src/Jellyfin.Extensions/Jellyfin.Extensions.csproj15
-rw-r--r--src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs10
-rw-r--r--src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs18
-rw-r--r--src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs11
-rw-r--r--src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs20
-rw-r--r--src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs13
-rw-r--r--src/Jellyfin.Extensions/Json/JsonDefaults.cs6
-rw-r--r--src/Jellyfin.Extensions/ReadOnlyListExtension.cs61
-rw-r--r--src/Jellyfin.Extensions/ShuffleExtensions.cs4
-rw-r--r--src/Jellyfin.Extensions/SplitStringExtensions.cs4
-rw-r--r--src/Jellyfin.Extensions/StringExtensions.cs34
11 files changed, 140 insertions, 56 deletions
diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
index 981b796e0..90d2a0da6 100644
--- a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
+++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
@@ -1,17 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFramework>net5.0</TargetFramework>
+ <TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
+ <PublishRepositoryUrl>true</PublishRepositoryUrl>
+ <EmbedUntrackedSources>true</EmbedUntrackedSources>
+ <IncludeSymbols>true</IncludeSymbols>
+ <SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
+ <PackageId>Jellyfin.Extensions</PackageId>
+ <VersionPrefix>10.8.0</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>
+ <PropertyGroup Condition=" '$(Stability)'=='Unstable'">
+ <!-- Include all symbols in the main nupkg until Azure Artifact Feed starts supporting ingesting NuGet symbol packages. -->
+ <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
+ </PropertyGroup>
+
<ItemGroup>
<Compile Include="../../SharedVersion.cs" />
</ItemGroup>
@@ -19,7 +30,7 @@
<!-- Code Analyzers-->
<ItemGroup>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs
index c39805aa3..321cfa502 100644
--- a/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs
+++ b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs
@@ -9,7 +9,7 @@ namespace Jellyfin.Extensions.Json.Converters
/// Convert delimited string to array of type.
/// </summary>
/// <typeparam name="T">Type to convert to.</typeparam>
- public abstract class JsonDelimitedArrayConverter<T> : JsonConverter<T[]?>
+ public abstract class JsonDelimitedArrayConverter<T> : JsonConverter<T[]>
{
private readonly TypeConverter _typeConverter;
@@ -31,9 +31,9 @@ namespace Jellyfin.Extensions.Json.Converters
{
if (reader.TokenType == JsonTokenType.String)
{
- // GetString can't return null here because we already handled it above
- var stringEntries = reader.GetString()?.Split(Delimiter, StringSplitOptions.RemoveEmptyEntries);
- if (stringEntries == null || stringEntries.Length == 0)
+ // null got handled higher up the call stack
+ var stringEntries = reader.GetString()!.Split(Delimiter, StringSplitOptions.RemoveEmptyEntries);
+ if (stringEntries.Length == 0)
{
return Array.Empty<T>();
}
@@ -44,7 +44,7 @@ namespace Jellyfin.Extensions.Json.Converters
{
try
{
- parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim());
+ parsedValues[i] = _typeConverter.ConvertFromInvariantString(stringEntries[i].Trim()) ?? throw new FormatException();
convertedCount++;
}
catch (FormatException)
diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs
index be94dd519..ea6d141cb 100644
--- a/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs
+++ b/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs
@@ -12,15 +12,19 @@ namespace Jellyfin.Extensions.Json.Converters
{
/// <inheritdoc />
public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
- {
- var guidStr = reader.GetString();
- return guidStr == null ? Guid.Empty : new Guid(guidStr);
- }
+ => reader.TokenType == JsonTokenType.Null
+ ? Guid.Empty
+ : ReadInternal(ref reader);
+
+ // TODO: optimize by parsing the UTF8 bytes instead of converting to string first
+ internal static Guid ReadInternal(ref Utf8JsonReader reader)
+ => Guid.Parse(reader.GetString()!); // null got handled higher up the call stack
/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options)
- {
- writer.WriteStringValue(value.ToString("N", CultureInfo.InvariantCulture));
- }
+ => WriteInternal(writer, value);
+
+ internal static void WriteInternal(Utf8JsonWriter writer, Guid value)
+ => writer.WriteStringValue(value.ToString("N", CultureInfo.InvariantCulture));
}
}
diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs
index 6192d1598..b477bcb66 100644
--- a/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs
+++ b/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs
@@ -1,5 +1,4 @@
using System;
-using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -12,21 +11,19 @@ namespace Jellyfin.Extensions.Json.Converters
{
/// <inheritdoc />
public override Guid? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
- {
- var guidStr = reader.GetString();
- return guidStr == null ? null : new Guid(guidStr);
- }
+ => JsonGuidConverter.ReadInternal(ref reader);
/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, Guid? value, JsonSerializerOptions options)
{
- if (value == null || value == Guid.Empty)
+ if (value == Guid.Empty)
{
writer.WriteNullValue();
}
else
{
- writer.WriteStringValue(value.Value.ToString("N", CultureInfo.InvariantCulture));
+ // null got handled higher up the call stack
+ JsonGuidConverter.WriteInternal(writer, value!.Value);
}
}
}
diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs
index 6de238b39..28437023f 100644
--- a/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs
+++ b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs
@@ -15,13 +15,10 @@ namespace Jellyfin.Extensions.Json.Converters
/// <inheritdoc />
public override TStruct? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
- if (reader.TokenType == JsonTokenType.Null)
- {
- return null;
- }
-
// Token is empty string.
- if (reader.TokenType == JsonTokenType.String && ((reader.HasValueSequence && reader.ValueSequence.IsEmpty) || reader.ValueSpan.IsEmpty))
+ if (reader.TokenType == JsonTokenType.String
+ && ((reader.HasValueSequence && reader.ValueSequence.IsEmpty)
+ || (!reader.HasValueSequence && reader.ValueSpan.IsEmpty)))
{
return null;
}
@@ -31,15 +28,6 @@ namespace Jellyfin.Extensions.Json.Converters
/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, TStruct? value, JsonSerializerOptions options)
- {
- if (value.HasValue)
- {
- JsonSerializer.Serialize(writer, value.Value, options);
- }
- else
- {
- writer.WriteNullValue();
- }
- }
+ => JsonSerializer.Serialize(writer, value!.Value, options); // null got handled higher up the call stack
}
}
diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs
index 1a7a8c4f5..36b36c9b4 100644
--- a/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs
+++ b/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs
@@ -13,20 +13,11 @@ namespace Jellyfin.Extensions.Json.Converters
{
/// <inheritdoc />
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
- {
- return reader.TokenType switch
- {
- JsonTokenType.Null => null,
- JsonTokenType.String => reader.GetString(),
- _ => GetRawValue(reader)
- };
- }
+ => reader.TokenType == JsonTokenType.String ? reader.GetString() : GetRawValue(reader);
/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options)
- {
- writer.WriteStringValue(value);
- }
+ => writer.WriteStringValue(value);
private static string GetRawValue(Utf8JsonReader reader)
{
diff --git a/src/Jellyfin.Extensions/Json/JsonDefaults.cs b/src/Jellyfin.Extensions/Json/JsonDefaults.cs
index f4ec91123..2cd89dc3b 100644
--- a/src/Jellyfin.Extensions/Json/JsonDefaults.cs
+++ b/src/Jellyfin.Extensions/Json/JsonDefaults.cs
@@ -25,7 +25,7 @@ namespace Jellyfin.Extensions.Json
/// -> AddJellyfinApi
/// -> AddJsonOptions.
/// </summary>
- private static readonly JsonSerializerOptions _jsonSerializerOptions = new ()
+ private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
{
ReadCommentHandling = JsonCommentHandling.Disallow,
WriteIndented = false,
@@ -44,12 +44,12 @@ namespace Jellyfin.Extensions.Json
}
};
- private static readonly JsonSerializerOptions _pascalCaseJsonSerializerOptions = new (_jsonSerializerOptions)
+ private static readonly JsonSerializerOptions _pascalCaseJsonSerializerOptions = new(_jsonSerializerOptions)
{
PropertyNamingPolicy = null
};
- private static readonly JsonSerializerOptions _camelCaseJsonSerializerOptions = new (_jsonSerializerOptions)
+ private static readonly JsonSerializerOptions _camelCaseJsonSerializerOptions = new(_jsonSerializerOptions)
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
diff --git a/src/Jellyfin.Extensions/ReadOnlyListExtension.cs b/src/Jellyfin.Extensions/ReadOnlyListExtension.cs
new file mode 100644
index 000000000..7785cfb49
--- /dev/null
+++ b/src/Jellyfin.Extensions/ReadOnlyListExtension.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+
+namespace Jellyfin.Extensions
+{
+ /// <summary>
+ /// Static extensions for the <see cref="IReadOnlyList{T}"/> interface.
+ /// </summary>
+ public static class ReadOnlyListExtension
+ {
+ /// <summary>
+ /// Finds the index of the desired item.
+ /// </summary>
+ /// <param name="source">The source list.</param>
+ /// <param name="value">The value to fine.</param>
+ /// <typeparam name="T">The type of item to find.</typeparam>
+ /// <returns>Index if found, else -1.</returns>
+ public static int IndexOf<T>(this IReadOnlyList<T> source, T value)
+ {
+ if (source is IList<T> list)
+ {
+ return list.IndexOf(value);
+ }
+
+ for (int i = 0; i < source.Count; i++)
+ {
+ if (Equals(value, source[i]))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Finds the index of the predicate.
+ /// </summary>
+ /// <param name="source">The source list.</param>
+ /// <param name="match">The value to find.</param>
+ /// <typeparam name="T">The type of item to find.</typeparam>
+ /// <returns>Index if found, else -1.</returns>
+ public static int FindIndex<T>(this IReadOnlyList<T> source, Predicate<T> match)
+ {
+ if (source is List<T> list)
+ {
+ return list.FindIndex(match);
+ }
+
+ for (int i = 0; i < source.Count; i++)
+ {
+ if (match(source[i]))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+ }
+}
diff --git a/src/Jellyfin.Extensions/ShuffleExtensions.cs b/src/Jellyfin.Extensions/ShuffleExtensions.cs
index 4e481983f..33c492053 100644
--- a/src/Jellyfin.Extensions/ShuffleExtensions.cs
+++ b/src/Jellyfin.Extensions/ShuffleExtensions.cs
@@ -8,8 +8,6 @@ namespace Jellyfin.Extensions
/// </summary>
public static class ShuffleExtensions
{
- private static readonly Random _rng = new Random();
-
/// <summary>
/// Shuffles the items in a list.
/// </summary>
@@ -17,7 +15,7 @@ namespace Jellyfin.Extensions
/// <typeparam name="T">The type.</typeparam>
public static void Shuffle<T>(this IList<T> list)
{
- list.Shuffle(_rng);
+ list.Shuffle(Random.Shared);
}
/// <summary>
diff --git a/src/Jellyfin.Extensions/SplitStringExtensions.cs b/src/Jellyfin.Extensions/SplitStringExtensions.cs
index 5fa5c0123..1d1c377f5 100644
--- a/src/Jellyfin.Extensions/SplitStringExtensions.cs
+++ b/src/Jellyfin.Extensions/SplitStringExtensions.cs
@@ -43,7 +43,7 @@ namespace Jellyfin.Extensions
/// <param name="separator">The separator to split on.</param>
/// <returns>The enumerator struct.</returns>
[Pure]
- public static Enumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator);
+ public static Enumerator SpanSplit(this string str, char separator) => new(str.AsSpan(), separator);
/// <summary>
/// Creates a new span split enumerator.
@@ -52,7 +52,7 @@ namespace Jellyfin.Extensions
/// <param name="separator">The separator to split on.</param>
/// <returns>The enumerator struct.</returns>
[Pure]
- public static Enumerator Split(this ReadOnlySpan<char> str, char separator) => new (str, separator);
+ public static Enumerator Split(this ReadOnlySpan<char> str, char separator) => new(str, separator);
/// <summary>
/// Provides an enumerator for the substrings seperated by the separator.
diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs
index acc695ed2..3a7707253 100644
--- a/src/Jellyfin.Extensions/StringExtensions.cs
+++ b/src/Jellyfin.Extensions/StringExtensions.cs
@@ -27,5 +27,39 @@ namespace Jellyfin.Extensions
return count;
}
+
+ /// <summary>
+ /// Returns the part on the left of the <c>needle</c>.
+ /// </summary>
+ /// <param name="haystack">The string to seek.</param>
+ /// <param name="needle">The needle to find.</param>
+ /// <returns>The part left of the <paramref name="needle" />.</returns>
+ public static ReadOnlySpan<char> LeftPart(this ReadOnlySpan<char> haystack, char needle)
+ {
+ var pos = haystack.IndexOf(needle);
+ return pos == -1 ? haystack : haystack[..pos];
+ }
+
+ /// <summary>
+ /// Returns the part on the right of the <c>needle</c>.
+ /// </summary>
+ /// <param name="haystack">The string to seek.</param>
+ /// <param name="needle">The needle to find.</param>
+ /// <returns>The part right of the <paramref name="needle" />.</returns>
+ public static ReadOnlySpan<char> RightPart(this ReadOnlySpan<char> haystack, char needle)
+ {
+ var pos = haystack.LastIndexOf(needle);
+ if (pos == -1)
+ {
+ return haystack;
+ }
+
+ if (pos == haystack.Length - 1)
+ {
+ return ReadOnlySpan<char>.Empty;
+ }
+
+ return haystack[(pos + 1)..];
+ }
}
}