A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using System.Diagnostics.CodeAnalysis;
6using System.Runtime.CompilerServices;
7using osu.Framework.Bindables;
8using osuTK;
9using osu.Framework.Graphics;
10
11#nullable enable
12
13namespace osu.Framework.Utils
14{
15 public static class Validation
16 {
17 /// <summary>
18 /// Returns whether the two coordinates of a <see cref="Vector2"/> are not infinite or NaN.
19 /// <para>For further information, see <seealso cref="float.IsFinite(float)"/>.</para>
20 /// </summary>
21 /// <param name="toCheck">The <see cref="Vector2"/> to check.</param>
22 /// <returns>False if X or Y are Infinity or NaN, true otherwise. </returns>
23 public static bool IsFinite(Vector2 toCheck) => float.IsFinite(toCheck.X) && float.IsFinite(toCheck.Y);
24
25 /// <summary>
26 /// Returns whether the components of a <see cref="MarginPadding"/> are not infinite or NaN.
27 /// <para>For further information, see <seealso cref="float.IsFinite(float)"/>.</para>
28 /// </summary>
29 /// <param name="toCheck">The <see cref="MarginPadding"/> to check.</param>
30 /// <returns>False if either component of <paramref name="toCheck"/> are Infinity or NaN, true otherwise. </returns>
31 public static bool IsFinite(MarginPadding toCheck) => float.IsFinite(toCheck.Top) && float.IsFinite(toCheck.Bottom) && float.IsFinite(toCheck.Left) && float.IsFinite(toCheck.Right);
32
33 /// <summary>
34 /// Attempts to parse <paramref name="uriString"/> as an absolute or relative <see cref="Uri"/> in a platform-agnostic manner.
35 /// </summary>
36 /// <remarks>
37 /// This method is a workaround for inconsistencies across .NET and mono runtimes;
38 /// on mono runtimes paths starting with <c>/</c> are considered absolute as per POSIX,
39 /// and on .NET such paths are considered to be relative.
40 /// This method uses the .NET behaviour.
41 /// For more info, see <a href="https://www.mono-project.com/docs/faq/known-issues/urikind-relativeorabsolute/">Mono documentation</a>.
42 /// </remarks>
43 /// <param name="uriString">The string representation of the URI to parse.</param>
44 /// <param name="result">The resultant parsed URI, if parsing succeeded.</param>
45 /// <returns><see langword="true"/> if parsing succeeded; <see langword="false"/> otherwise.</returns>
46 public static bool TryParseUri(string uriString, [NotNullWhen(true)] out Uri? result)
47 {
48#pragma warning disable RS0030 // Bypassing banned API check, as it'll actually be used properly here
49 UriKind kind = uriString.StartsWith('/') ? UriKind.Relative : UriKind.RelativeOrAbsolute;
50#pragma warning restore RS0030
51 return Uri.TryCreate(uriString, kind, out result);
52 }
53
54 /// <summary>
55 /// Whether the specified type <typeparamref name="T"/> is a number type supported by <see cref="BindableNumber{T}"/>.
56 /// </summary>
57 /// <remarks>
58 /// Directly comparing typeof(T) to type literal is recognized pattern of JIT and very fast.
59 /// Just a pointer comparison for reference types, or constant for value types.
60 /// The check will become NOP in usages after optimization.
61 /// </remarks>
62 /// <typeparam name="T">The type to check for.</typeparam>
63 /// <returns><see langword="true"/> if the type is supported; <see langword="false"/> otherwise.</returns>
64 [MethodImpl(MethodImplOptions.AggressiveInlining)]
65 public static bool IsSupportedBindableNumberType<T>() =>
66 typeof(T) == typeof(sbyte)
67 || typeof(T) == typeof(byte)
68 || typeof(T) == typeof(short)
69 || typeof(T) == typeof(ushort)
70 || typeof(T) == typeof(int)
71 || typeof(T) == typeof(uint)
72 || typeof(T) == typeof(long)
73 || typeof(T) == typeof(ulong)
74 || typeof(T) == typeof(float)
75 || typeof(T) == typeof(double);
76 }
77}