Skip to content

Commit

Permalink
feat: enum converters
Browse files Browse the repository at this point in the history
  • Loading branch information
qixils committed Jan 12, 2024
1 parent d14eff6 commit 1e9a878
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 20 deletions.
17 changes: 16 additions & 1 deletion src/main/java/dev/qixils/quasicord/converter/Converter.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import net.dv8tion.jda.api.interactions.Interaction;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;

/**
* An interface for converting a user-provided value to a different type.
Expand Down Expand Up @@ -38,10 +39,24 @@ public interface Converter<I, O> {
*
* @param interaction the interaction being invoked
* @param input the user input
* @param targetClass the class to convert to
* @return converted value
*/
@NonNull
O convert(@NonNull Interaction interaction, @NonNull I input);
O convert(@NonNull Interaction interaction, @NonNull I input, @NonNull Class<? extends O> targetClass);

/**
* Converts an input to the output type.
*
* @param interaction the interaction being invoked
* @param input the user input
* @return converted value
*/
@NonNull
@ApiStatus.NonExtendable
default O convert(@NonNull Interaction interaction, @NonNull I input) {
return convert(interaction, input, getOutputClass());
}

/**
* Determines whether this converter can be converted to in a converter chain.
Expand Down
32 changes: 27 additions & 5 deletions src/main/java/dev/qixils/quasicord/converter/ConverterImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,42 @@

public class ConverterImpl<I, O> extends AbstractConverter<I, O> {

private final @NonNull BiFunction<Interaction, I, O> converter;
@FunctionalInterface
public interface ConverterImplStep<I, O> {
/**
* Converts an input to the output type.
*
* @param interaction the interaction being invoked
* @param input the user input
* @param targetClass the class to convert to
* @return converted value
*/
@NonNull
O convert(@NonNull Interaction interaction, @NonNull I input, @NonNull Class<? extends O> targetClass);
}

private final @NonNull ConverterImplStep<I, O> converter;

public ConverterImpl(
@NonNull Class<I> inputClass,
@NonNull Class<O> outputClass,
@NonNull ConverterImplStep<I, O> converter
) {
super(inputClass, outputClass);
this.converter = converter;
}

public ConverterImpl(
@NonNull Class<I> inputClass,
@NonNull Class<O> outputClass,
@NonNull BiFunction<Interaction, I, O> converter
) {
super(inputClass, outputClass);
this.converter = converter;
this(inputClass, outputClass, (ctx, i, t) -> converter.apply(ctx, i));
}

@Override
public @NonNull O convert(@NonNull Interaction interaction, @NonNull I input) {
return converter.apply(interaction, input);
public @NonNull O convert(@NonNull Interaction interaction, @NonNull I input, @NonNull Class<? extends O> targetClass) {
return converter.convert(interaction, input, targetClass);
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@
import org.checkerframework.checker.nullness.qual.Nullable;

import java.time.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.*;

import static dev.qixils.quasicord.converter.ConverterImpl.identity;

Expand Down Expand Up @@ -76,6 +73,8 @@ public ConverterRegistry(@NonNull Quasicord library) {
register(new ConverterImpl<>(Number.class, Byte.class, (it, b) -> b.byteValue()));
// misc
register(new ConverterImpl<>(User.class, Member.class, (it, u) -> Objects.requireNonNull(Objects.requireNonNull(it.getGuild()).getMember(u))));
register(new ConverterImpl<>(Integer.class, Enum.class, (ctx, i, tc) -> tc.getEnumConstants()[i]));
register(new ConverterImpl<>(String.class, Enum.class, (ctx, i, tc) -> Arrays.stream(tc.getEnumConstants()).filter(e -> e.name().equals(i)).findFirst().orElseThrow()));
}

@NonNull
Expand Down Expand Up @@ -180,10 +179,10 @@ private ChainConverter(@NonNull Class<I> inputClass, @NonNull Class<O> outputCla

@SuppressWarnings({"unchecked", "rawtypes"}) // i'm sorry JVM
@Override
public @NonNull O convert(@NonNull Interaction interaction, @NonNull I input) {
public @NonNull O convert(@NonNull Interaction interaction, @NonNull I input, @NonNull Class<? extends O> targetClass) {
Object result = input;
for (Converter converter : converters)
result = converter.convert(interaction, result);
result = converter.convert(interaction, result, targetClass); // TODO: does passing targetClass unconditionally make sense here?
return (O) result;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
public interface VoidConverter<O> extends Converter<Void, O> {

@Override
default @NonNull O convert(@NonNull Interaction interaction, @Nullable Void input) {
default @NonNull O convert(@NonNull Interaction interaction, @Nullable Void input, @NonNull Class<? extends O> targetClass) {
return convert(interaction);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class DurationConverter implements Converter<String, Duration> {
private static final @NonNull Pattern RELATIVE_TIME_PATTERN = Pattern.compile("^\\d+[A-Za-z]+");

@Override
public @NonNull Duration convert(@NonNull Interaction interaction, @NonNull String input) {
public @NonNull Duration convert(@NonNull Interaction interaction, @NonNull String input, @NonNull Class<? extends Duration> targetClass) {
List<String> arguments = new ArrayList<>(Arrays.asList(input.split(" ")));
arguments.removeIf(s -> RELATIVE_TIME_IGNORED_TOKENS.contains(s.toLowerCase(Locale.ENGLISH)));
String strippedInput = String.join("", arguments);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public LocaleConverter(@NonNull Quasicord library) {
}

@Override
public @NonNull Locale convert(@NonNull Interaction it, @NonNull String input) {
public @NonNull Locale convert(@NonNull Interaction it, @NonNull String input, @org.checkerframework.checker.nullness.qual.NonNull Class<? extends Locale> targetClass) {
try {
return new Locale.Builder().setLanguageTag(input).build();
} catch (IllformedLocaleException ignored) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class ZoneIdConverter implements Converter<String, ZoneId> {
private final @NonNull Class<ZoneId> outputClass = ZoneId.class;

@Override
public @NonNull ZoneId convert(@NonNull Interaction it, @NonNull String input) {
public @NonNull ZoneId convert(@NonNull Interaction it, @NonNull String input, @org.checkerframework.checker.nullness.qual.NonNull Class<? extends ZoneId> targetClass) {
try {
return ZoneId.of(input);
} catch (Exception ignored) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public ZonedDateTimeConverter(@NonNull Quasicord library) {
}

@Override
public @NonNull ZonedDateTime convert(@NonNull Interaction interaction, @NonNull String input) {
public @NonNull ZonedDateTime convert(@NonNull Interaction interaction, @NonNull String input, @NonNull Class<? extends ZonedDateTime> targetClass) {
TimeZoneConfig config = library.getDatabaseManager().getById(interaction.getUser().getIdLong(), TimeZoneConfig.class).block();
ZoneId zone = config == null ? ZoneOffset.UTC : config.getTimeZone();
ZonedDateTime now = ZonedDateTime.now(zone);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public record ConverterData(@NonNull Converter<?, ?> converter, @Nullable String optName) {
public record ConverterData(@NonNull Converter<?, ?> converter, @Nullable String optName, @NonNull Class<?> targetClass) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ else if (option.type() == OptionType.STRING)
branch.root().addOptions(opt);
}

converters[i] = new ConverterData(converter, optNameStr);
converters[i] = new ConverterData(converter, optNameStr, parameter.getType());
}
}

Expand Down Expand Up @@ -224,7 +224,7 @@ else if (inputClass == Member.class) {
}

else throw new IllegalArgumentException("Could not accept interaction option of type " + option.getType() + " for a converter from " + inputClass.getName());
args[i] = converter.convert(interaction, input);
args[i] = converter.convert(interaction, input, converterData.targetClass());
}

// invoke and handle
Expand Down

0 comments on commit 1e9a878

Please sign in to comment.