mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-01-15 23:58:57 +00:00
Merge branch 'master' into keyframe_extraction_v1
# Conflicts: # Jellyfin.Api/Controllers/DynamicHlsController.cs # MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs # MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
This commit is contained in:
@@ -30,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>
|
||||
|
||||
|
||||
@@ -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()) ?? throw new FormatException();
|
||||
parsedValues[i] = _typeConverter.ConvertFromInvariantString(stringEntries[i].Trim()) ?? throw new FormatException();
|
||||
convertedCount++;
|
||||
}
|
||||
catch (FormatException)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
61
src/Jellyfin.Extensions/ReadOnlyListExtension.cs
Normal file
61
src/Jellyfin.Extensions/ReadOnlyListExtension.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user