Cleaned up TypeReaders
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -27,94 +26,56 @@ namespace Discord.Commands
|
|||||||
_map = new CommandMap();
|
_map = new CommandMap();
|
||||||
_typeReaders = new ConcurrentDictionary<Type, TypeReader>
|
_typeReaders = new ConcurrentDictionary<Type, TypeReader>
|
||||||
{
|
{
|
||||||
[typeof(string)] = new GenericTypeReader((m, s) => Task.FromResult(TypeReaderResult.FromSuccess(s))),
|
[typeof(string)] = new SimpleTypeReader<string>(),
|
||||||
[typeof(byte)] = new GenericTypeReader((m, s) =>
|
[typeof(byte)] = new SimpleTypeReader<byte>(),
|
||||||
{
|
[typeof(sbyte)] = new SimpleTypeReader<sbyte>(),
|
||||||
byte value;
|
[typeof(ushort)] = new SimpleTypeReader<ushort>(),
|
||||||
if (byte.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
[typeof(short)] = new SimpleTypeReader<short>(),
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Byte"));
|
[typeof(uint)] = new SimpleTypeReader<uint>(),
|
||||||
}),
|
[typeof(int)] = new SimpleTypeReader<int>(),
|
||||||
[typeof(sbyte)] = new GenericTypeReader((m, s) =>
|
[typeof(ulong)] = new SimpleTypeReader<ulong>(),
|
||||||
{
|
[typeof(long)] = new SimpleTypeReader<long>(),
|
||||||
sbyte value;
|
[typeof(float)] = new SimpleTypeReader<float>(),
|
||||||
if (sbyte.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
[typeof(double)] = new SimpleTypeReader<double>(),
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse SByte"));
|
[typeof(decimal)] = new SimpleTypeReader<decimal>(),
|
||||||
}),
|
[typeof(DateTime)] = new SimpleTypeReader<DateTime>(),
|
||||||
[typeof(ushort)] = new GenericTypeReader((m, s) =>
|
[typeof(DateTimeOffset)] = new SimpleTypeReader<DateTimeOffset>(),
|
||||||
{
|
|
||||||
ushort value;
|
//TODO: Do we want to support any other interfaces?
|
||||||
if (ushort.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse UInt16"));
|
//[typeof(IMentionable)] = new GeneralTypeReader(),
|
||||||
}),
|
//[typeof(ISnowflakeEntity)] = new GeneralTypeReader(),
|
||||||
[typeof(short)] = new GenericTypeReader((m, s) =>
|
//[typeof(IEntity<ulong>)] = new GeneralTypeReader(),
|
||||||
{
|
|
||||||
short value;
|
|
||||||
if (short.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Int16"));
|
|
||||||
}),
|
|
||||||
[typeof(uint)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
uint value;
|
|
||||||
if (uint.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse UInt32"));
|
|
||||||
}),
|
|
||||||
[typeof(int)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
int value;
|
|
||||||
if (int.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Int32"));
|
|
||||||
}),
|
|
||||||
[typeof(ulong)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
ulong value;
|
|
||||||
if (ulong.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse UInt64"));
|
|
||||||
}),
|
|
||||||
[typeof(long)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
long value;
|
|
||||||
if (long.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Int64"));
|
|
||||||
}),
|
|
||||||
[typeof(float)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
float value;
|
|
||||||
if (float.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Single"));
|
|
||||||
}),
|
|
||||||
[typeof(double)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
double value;
|
|
||||||
if (double.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Double"));
|
|
||||||
}),
|
|
||||||
[typeof(decimal)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
decimal value;
|
|
||||||
if (decimal.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse Decimal"));
|
|
||||||
}),
|
|
||||||
[typeof(DateTime)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
DateTime value;
|
|
||||||
if (DateTime.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse DateTime"));
|
|
||||||
}),
|
|
||||||
[typeof(DateTimeOffset)] = new GenericTypeReader((m, s) =>
|
|
||||||
{
|
|
||||||
DateTimeOffset value;
|
|
||||||
if (DateTimeOffset.TryParse(s, out value)) return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
|
||||||
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse DateTimeOffset"));
|
|
||||||
}),
|
|
||||||
|
|
||||||
[typeof(IMessage)] = new MessageTypeReader(),
|
[typeof(IMessage)] = new MessageTypeReader(),
|
||||||
|
//[typeof(IAttachment)] = new xxx(),
|
||||||
|
//[typeof(IEmbed)] = new xxx(),
|
||||||
|
|
||||||
[typeof(IChannel)] = new ChannelTypeReader<IChannel>(),
|
[typeof(IChannel)] = new ChannelTypeReader<IChannel>(),
|
||||||
|
[typeof(IDMChannel)] = new ChannelTypeReader<IDMChannel>(),
|
||||||
|
[typeof(IGroupChannel)] = new ChannelTypeReader<IGroupChannel>(),
|
||||||
[typeof(IGuildChannel)] = new ChannelTypeReader<IGuildChannel>(),
|
[typeof(IGuildChannel)] = new ChannelTypeReader<IGuildChannel>(),
|
||||||
|
[typeof(IMessageChannel)] = new ChannelTypeReader<IMessageChannel>(),
|
||||||
|
[typeof(IPrivateChannel)] = new ChannelTypeReader<IPrivateChannel>(),
|
||||||
[typeof(ITextChannel)] = new ChannelTypeReader<ITextChannel>(),
|
[typeof(ITextChannel)] = new ChannelTypeReader<ITextChannel>(),
|
||||||
[typeof(IVoiceChannel)] = new ChannelTypeReader<IVoiceChannel>(),
|
[typeof(IVoiceChannel)] = new ChannelTypeReader<IVoiceChannel>(),
|
||||||
|
|
||||||
|
//[typeof(IGuild)] = new GuildTypeReader<IGuild>(),
|
||||||
|
//[typeof(IUserGuild)] = new GuildTypeReader<IUserGuild>(),
|
||||||
|
//[typeof(IGuildIntegration)] = new xxx(),
|
||||||
|
|
||||||
[typeof(IRole)] = new RoleTypeReader(),
|
[typeof(IRole)] = new RoleTypeReader(),
|
||||||
|
|
||||||
|
//[typeof(IInvite)] = new InviteTypeReader<IInvite>(),
|
||||||
|
//[typeof(IInviteMetadata)] = new InviteTypeReader<IInviteMetadata>(),
|
||||||
|
|
||||||
[typeof(IUser)] = new UserTypeReader<IUser>(),
|
[typeof(IUser)] = new UserTypeReader<IUser>(),
|
||||||
[typeof(IGuildUser)] = new UserTypeReader<IGuildUser>()
|
[typeof(IGroupUser)] = new UserTypeReader<IGroupUser>(),
|
||||||
|
[typeof(IGuildUser)] = new UserTypeReader<IGuildUser>(),
|
||||||
|
//[typeof(ISelfUser)] = new UserTypeReader<ISelfUser>(),
|
||||||
|
//[typeof(IPresence)] = new UserTypeReader<IPresence>(),
|
||||||
|
//[typeof(IVoiceState)] = new UserTypeReader<IVoiceState>(),
|
||||||
|
//[typeof(IConnection)] = new xxx(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
src/Discord.Net.Commands/PrimitiveParsers.cs
Normal file
33
src/Discord.Net.Commands/PrimitiveParsers.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
|
namespace Discord.Commands
|
||||||
|
{
|
||||||
|
internal delegate bool TryParseDelegate<T>(string str, out T value);
|
||||||
|
|
||||||
|
internal static class PrimitiveParsers
|
||||||
|
{
|
||||||
|
private static readonly IReadOnlyDictionary<Type, Delegate> _parsers;
|
||||||
|
|
||||||
|
static PrimitiveParsers()
|
||||||
|
{
|
||||||
|
var parserBuilder = ImmutableDictionary.CreateBuilder<Type, Delegate>();
|
||||||
|
parserBuilder[typeof(string)] = (TryParseDelegate<string>)delegate(string str, out string value) { value = str; return true; };
|
||||||
|
parserBuilder[typeof(sbyte)] = (TryParseDelegate<sbyte>)sbyte.TryParse;
|
||||||
|
parserBuilder[typeof(byte)] = (TryParseDelegate<byte>)byte.TryParse;
|
||||||
|
parserBuilder[typeof(short)] = (TryParseDelegate<short>)short.TryParse;
|
||||||
|
parserBuilder[typeof(ushort)] = (TryParseDelegate<ushort>)ushort.TryParse;
|
||||||
|
parserBuilder[typeof(int)] = (TryParseDelegate<int>)int.TryParse;
|
||||||
|
parserBuilder[typeof(uint)] = (TryParseDelegate<uint>)uint.TryParse;
|
||||||
|
parserBuilder[typeof(long)] = (TryParseDelegate<long>)long.TryParse;
|
||||||
|
parserBuilder[typeof(ulong)] = (TryParseDelegate<ulong>)ulong.TryParse;
|
||||||
|
parserBuilder[typeof(DateTime)] = (TryParseDelegate<DateTime>)DateTime.TryParse;
|
||||||
|
parserBuilder[typeof(DateTimeOffset)] = (TryParseDelegate<DateTimeOffset>)DateTimeOffset.TryParse;
|
||||||
|
_parsers = parserBuilder.ToImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TryParseDelegate<T> Get<T>() => (TryParseDelegate<T>)_parsers[typeof(T)];
|
||||||
|
public static Delegate Get(Type type) => _parsers[type];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,31 +7,13 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Discord.Commands
|
namespace Discord.Commands
|
||||||
{
|
{
|
||||||
delegate bool TryParseDelegate<T>(string str, out T value);
|
|
||||||
|
|
||||||
internal static class EnumTypeReader
|
internal static class EnumTypeReader
|
||||||
{
|
{
|
||||||
private static readonly IReadOnlyDictionary<Type, object> _parsers;
|
|
||||||
|
|
||||||
static EnumTypeReader()
|
|
||||||
{
|
|
||||||
var parserBuilder = ImmutableDictionary.CreateBuilder<Type, object>();
|
|
||||||
parserBuilder[typeof(sbyte)] = (TryParseDelegate<sbyte>)sbyte.TryParse;
|
|
||||||
parserBuilder[typeof(byte)] = (TryParseDelegate<byte>)byte.TryParse;
|
|
||||||
parserBuilder[typeof(short)] = (TryParseDelegate<short>)short.TryParse;
|
|
||||||
parserBuilder[typeof(ushort)] = (TryParseDelegate<ushort>)ushort.TryParse;
|
|
||||||
parserBuilder[typeof(int)] = (TryParseDelegate<int>)int.TryParse;
|
|
||||||
parserBuilder[typeof(uint)] = (TryParseDelegate<uint>)uint.TryParse;
|
|
||||||
parserBuilder[typeof(long)] = (TryParseDelegate<long>)long.TryParse;
|
|
||||||
parserBuilder[typeof(ulong)] = (TryParseDelegate<ulong>)ulong.TryParse;
|
|
||||||
_parsers = parserBuilder.ToImmutable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TypeReader GetReader(Type type)
|
public static TypeReader GetReader(Type type)
|
||||||
{
|
{
|
||||||
Type baseType = Enum.GetUnderlyingType(type);
|
Type baseType = Enum.GetUnderlyingType(type);
|
||||||
var constructor = typeof(EnumTypeReader<>).MakeGenericType(baseType).GetTypeInfo().DeclaredConstructors.First();
|
var constructor = typeof(EnumTypeReader<>).MakeGenericType(baseType).GetTypeInfo().DeclaredConstructors.First();
|
||||||
return (TypeReader)constructor.Invoke(new object[] { type, _parsers[baseType] });
|
return (TypeReader)constructor.Invoke(new object[] { type, PrimitiveParsers.Get(baseType) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Discord.Commands
|
|
||||||
{
|
|
||||||
internal class GenericTypeReader : TypeReader
|
|
||||||
{
|
|
||||||
private readonly Func<IMessage, string, Task<TypeReaderResult>> _action;
|
|
||||||
|
|
||||||
public GenericTypeReader(Func<IMessage, string, Task<TypeReaderResult>> action)
|
|
||||||
{
|
|
||||||
_action = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<TypeReaderResult> Read(IMessage context, string input) => _action(context, input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
23
src/Discord.Net.Commands/Readers/SimpleTypeReader.cs
Normal file
23
src/Discord.Net.Commands/Readers/SimpleTypeReader.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Discord.Commands
|
||||||
|
{
|
||||||
|
internal class SimpleTypeReader<T> : TypeReader
|
||||||
|
{
|
||||||
|
private readonly TryParseDelegate<T> _tryParse;
|
||||||
|
|
||||||
|
public SimpleTypeReader()
|
||||||
|
{
|
||||||
|
_tryParse = PrimitiveParsers.Get<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<TypeReaderResult> Read(IMessage context, string input)
|
||||||
|
{
|
||||||
|
T value;
|
||||||
|
if (_tryParse(input, out value))
|
||||||
|
return Task.FromResult(TypeReaderResult.FromSuccess(value));
|
||||||
|
else
|
||||||
|
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, $"Failed to parse {typeof(T).Name}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user