WTelegramClient/src/Compat.cs

100 lines
3.5 KiB
C#
Raw Normal View History

using System;
using System.Buffers.Binary;
using System.Collections.Generic;
2021-11-10 01:20:54 +01:00
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Numerics;
using System.Security.Cryptography;
#if NETCOREAPP2_1_OR_GREATER
namespace WTelegram
{
static class Compat
{
2021-08-16 22:52:33 +02:00
internal static BigInteger BigEndianInteger(byte[] value) => new(value, true, true);
internal static IPEndPoint IPEndPoint_Parse(string addr) => IPEndPoint.Parse(addr);
}
}
2022-08-13 01:20:53 +02:00
#else // Compatibility shims for methods missing in netstandard2.0:
namespace WTelegram
{
static class Compat
{
internal static BigInteger BigEndianInteger(byte[] value)
{
var data = new byte[value.Length + 1];
value.CopyTo(data, 1);
Array.Reverse(data);
return new BigInteger(data);
}
2022-04-01 21:48:28 +02:00
internal static byte[] ToByteArray(this BigInteger bigInteger, bool isUnsigned, bool isBigEndian)
{
if (!isBigEndian || !isUnsigned) throw new ArgumentException("Unexpected parameters to ToByteArray");
var result = bigInteger.ToByteArray();
if (result[^1] == 0) result = result[0..^1];
Array.Reverse(result);
return result;
}
internal static long GetBitLength(this BigInteger bigInteger)
{
var bytes = bigInteger.ToByteArray();
var length = bytes.LongLength * 8L;
int lastByte = bytes[^1];
while ((lastByte & 0x80) == 0) { length--; lastByte = (lastByte << 1) + 1; }
return length;
}
public static V GetValueOrDefault<K, V>(this Dictionary<K, V> dictionary, K key, V defaultValue = default)
=> dictionary.TryGetValue(key, out V value) ? value : defaultValue;
2022-04-01 21:48:28 +02:00
public static void Deconstruct<K, V>(this KeyValuePair<K, V> kvp, out K key, out V value) { key = kvp.Key; value = kvp.Value; }
internal static IPEndPoint IPEndPoint_Parse(string addr)
{
int colon = addr.LastIndexOf(':');
return new IPEndPoint(IPAddress.Parse(addr[0..colon]), int.Parse(addr[(colon + 1)..]));
}
internal static void ImportFromPem(this RSA rsa, string pem)
{
var header = pem.IndexOf("-----BEGIN RSA PUBLIC KEY-----");
var footer = pem.IndexOf("-----END RSA PUBLIC KEY-----");
if (header == -1 || footer <= header) throw new ArgumentException("Invalid RSA Public Key");
byte[] bytes = System.Convert.FromBase64String(pem[(header+30)..footer]);
if (bytes.Length != 270 || BinaryPrimitives.ReadInt64BigEndian(bytes) != 0x3082010A02820101 || bytes[265] != 0x02 || bytes[266] != 0x03)
throw new ArgumentException("Unrecognized sequence in RSA Public Key");
rsa.ImportParameters(new RSAParameters { Modulus = bytes[8..265], Exponent = bytes[267..270] });
}
}
}
static class Convert
{
internal static string ToHexString(byte[] data) => BitConverter.ToString(data).Replace("-", "");
2022-04-01 21:48:28 +02:00
internal static byte[] FromHexString(string hex) => Enumerable.Range(0, hex.Length / 2).Select(i => System.Convert.ToByte(hex.Substring(i * 2, 2), 16)).ToArray();
}
#endif
#if NETSTANDARD2_0
namespace System.Runtime.CompilerServices
{
internal static class RuntimeHelpers
{
public static T[] GetSubArray<T>(T[] array, Range range)
{
if (array == null) throw new ArgumentNullException();
var (offset, length) = range.GetOffsetAndLength(array.Length);
if (length == 0) return Array.Empty<T>();
var dest = typeof(T).IsValueType || typeof(T[]) == array.GetType() ? new T[length]
: (T[])Array.CreateInstance(array.GetType().GetElementType()!, length);
Array.Copy(array, offset, dest, 0, length);
return dest;
}
}
2021-11-10 01:20:54 +01:00
[EditorBrowsable(EditorBrowsableState.Never)]
internal class IsExternalInit { }
}
#endif