-
Notifications
You must be signed in to change notification settings - Fork 0
Add new configuration types and serializers for numeric and boolean values #353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
74e183f
✨ feat(config): add new configuration types for numeric and boolean v…
twisti-dev 63bee17
```
twisti-dev 3c9eed6
🔧 chore(abi): update api dump
twisti-dev d239a3f
✨ feat(config): add serializers for various configuration types and c…
twisti-dev 637d9cf
✨ feat(config): add ConfigDuration type and update duration constraints
twisti-dev eb80024
✨ feat(config): add new validation annotations for configuration values
twisti-dev d3bf30c
🔧 chore(abi): update api dump
twisti-dev 75a8ce0
🔧 chore: update version to 3.13.0 in gradle.properties
twisti-dev c6fcd2d
🔧 chore: downgrade version from 3.13.0 to 3.12.0 in gradle.properties
twisti-dev 495bbd9
✨ feat(config): add new configuration types and update serializers
twisti-dev 2e45982
♻️ refactor(serializers): simplify key serialization logic in Registr…
twisti-dev b05371c
Potential fix for pull request finding
twisti-dev c50eafb
fix: address review feedback - SerializationException, AnnotatedType,…
Copilot 52f43db
fix: use PrimitiveToPrimitive for all non-parameterized fastutil prim…
Copilot b52a1d9
🐛 fix(ExistingFile): handle potential exception in string to Path con…
twisti-dev 41f99b8
✨ feat(serializers): add fastutil Int2IntMap for integer key-value pairs
twisti-dev 48c45d7
🔧 chore(abi): update api dump
twisti-dev 5de7d75
🐛 fix(PathSerializer): handle InvalidPathException during path deseri…
twisti-dev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
10 changes: 10 additions & 0 deletions
10
...re/src/main/kotlin/dev/slne/surf/api/core/config/constraints/CollectionConstraintUtils.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| internal fun Any?.configSizeOrNull(): Int? = when (this) { | ||
| null -> null | ||
| is Collection<*> -> size | ||
| is Map<*, *> -> size | ||
| is Array<*> -> size | ||
| is CharSequence -> length | ||
| else -> null | ||
| } |
27 changes: 27 additions & 0 deletions
27
...-core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/Contains.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
|
|
||
| /** | ||
| * Requires a string config value to contain a specific substring. | ||
| * | ||
| * This annotation ensures that the annotated string contains the specified substring. | ||
| * If the validation fails, a `SerializationException` is thrown with a descriptive error message. | ||
| * | ||
| * @property value The substring that must be present in the string value. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class Contains(val value: String) { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<Contains, String?> { | ||
| override fun make(data: Contains, type: Type): Constraint<String?> = { value -> | ||
| if (value != null && !value.contains(data.value)) { | ||
| throw SerializationException("String must contain '${data.value}'") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
43 changes: 43 additions & 0 deletions
43
...core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/Directory.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
| import kotlin.io.path.exists | ||
| import kotlin.io.path.isDirectory | ||
|
|
||
| /** | ||
| * Ensures that a configuration value represents a valid, existing directory. | ||
| * | ||
| * This annotation validates that the annotated value points to a directory that exists on the filesystem. | ||
| * If the value does not exist, or if it does not represent a directory, validation will fail with a | ||
| * `SerializationException`. | ||
| * | ||
| * This constraint supports different types of input, such as `Path`, `File`, and `String`, converting | ||
| * them to a `Path` internally using the helper method `asPathOrNull`. | ||
| * | ||
| * Constraints: | ||
| * - The value must point to an existing directory. | ||
| * - The value must be convertible to a `Path` object. | ||
| * | ||
| * Intended for use on fields in configuration classes. | ||
| * | ||
| * Validation failure will throw a `SerializationException` with a descriptive message indicating the | ||
| * problem with the directory path. | ||
| * | ||
| * Associated factory implementation provides the actual validation logic. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class Directory { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<Directory, Any?> { | ||
| override fun make(data: Directory, type: Type): Constraint<Any?> = Constraint { value -> | ||
| val path = value.asPathOrNull() ?: return@Constraint | ||
| if (!path.exists() || !path.isDirectory()) { | ||
| throw SerializationException("Path must point to an existing directory: $path") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
27 changes: 27 additions & 0 deletions
27
...surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/DisallowValues.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
|
|
||
| /** | ||
| * Prevents specific values from being assigned to the annotated field. | ||
| * | ||
| * This annotation is used to define a set of disallowed string values for a field. If the annotated field's | ||
| * value matches any of the specified disallowed values (case-insensitive), a `SerializationException` is thrown. | ||
| * | ||
| * @property values The array of string values that are disallowed. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class DisallowValues(vararg val values: String) { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<DisallowValues, Any?> { | ||
| override fun make(data: DisallowValues, type: Type): Constraint<Any?> = { value -> | ||
| if (value != null && data.values.any { it.equals(value.toString(), ignoreCase = true) }) { | ||
| throw SerializationException("Value '$value' is not allowed") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
27 changes: 27 additions & 0 deletions
27
...-core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/EndsWith.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
|
|
||
| /** | ||
| * Validates that a string config value ends with a specified suffix. | ||
| * | ||
| * This annotation ensures that the annotated string ends with the provided suffix. | ||
| * If the validation fails, a `SerializationException` is thrown with a descriptive error message. | ||
| * | ||
| * @property suffix The suffix that the string value must end with. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class EndsWith(val suffix: String) { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<EndsWith, String?> { | ||
| override fun make(data: EndsWith, type: Type): Constraint<String?> = { value -> | ||
| if (value != null && !value.endsWith(data.suffix)) { | ||
| throw SerializationException("String must end with '${data.suffix}'") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
52 changes: 52 additions & 0 deletions
52
...e/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/ExistingFile.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.io.File | ||
| import java.lang.reflect.Type | ||
| import java.nio.file.Path | ||
| import kotlin.io.path.exists | ||
| import kotlin.io.path.isRegularFile | ||
|
|
||
| /** | ||
| * Requires that the annotated field refers to an existing file. | ||
| * | ||
| * This annotation ensures that the value of the annotated field corresponds to | ||
| * a valid file path that exists and is a regular file. If the validation fails, | ||
| * a `SerializationException` is thrown with a descriptive error message. | ||
| * | ||
| * The value can be: | ||
| * - A `Path` object. | ||
| * - A `File` object. | ||
| * - A `String` representing the file path. | ||
| * | ||
| * If the value is not convertible to a file path or the file does not exist | ||
| * or is not a regular file, the validation fails. | ||
| * | ||
| * This annotation is typically used for configuration values to ensure | ||
| * that specified file paths are valid at runtime. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class ExistingFile { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<ExistingFile, Any?> { | ||
| override fun make(data: ExistingFile, type: Type): Constraint<Any?> = Constraint { value -> | ||
| val path = value.asPathOrNull() ?: return@Constraint | ||
| if (!path.exists() || !path.isRegularFile()) { | ||
| throw SerializationException("Path must point to an existing file: $path") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| internal fun Any?.asPathOrNull(): Path? { | ||
| return when (this) { | ||
| null -> null | ||
| is Path -> this | ||
| is File -> toPath() | ||
| is String -> runCatching { Path.of(this) }.getOrNull() | ||
| else -> null | ||
| } | ||
| } | ||
29 changes: 29 additions & 0 deletions
29
...re/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/MaxDuration.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import dev.slne.surf.api.core.config.type.ConfigDuration | ||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
|
|
||
| /** | ||
| * Annotation for constraining a `ConfigDuration`'s value to a maximum duration. | ||
| * | ||
| * This annotation ensures that the duration value of the annotated field does not exceed | ||
| * the specified number of seconds. If the validation fails, a `SerializationException` | ||
| * is thrown with a descriptive error message. | ||
| * | ||
| * @property seconds The maximum duration in seconds that the annotated field can have. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class MaxDuration(val seconds: Long) { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<MaxDuration, ConfigDuration?> { | ||
| override fun make(data: MaxDuration, type: Type): Constraint<ConfigDuration?> = { value -> | ||
| if (value != null && value.value.inWholeSeconds > data.seconds) { | ||
| throw SerializationException("Duration is too long: ${value.value}, expected <= ${data.seconds}s") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
28 changes: 28 additions & 0 deletions
28
...core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/MaxLength.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
|
|
||
| /** | ||
| * Validates that a string config value does not exceed a specified maximum length. | ||
| * | ||
| * This annotation is used to ensure that the length of the annotated string | ||
| * is less than or equal to the specified maximum value. If the validation fails, | ||
| * a `SerializationException` is thrown with a descriptive error message. | ||
| * | ||
| * @property max The maximum allowed length for the string value. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class MaxLength(val max: Int) { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<MaxLength, String?> { | ||
| override fun make(data: MaxLength, type: Type): Constraint<String?> = { value -> | ||
| if (value != null && value.length > data.max) { | ||
| throw SerializationException("String is too long: ${value.length}, expected <= ${data.max}") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
39 changes: 39 additions & 0 deletions
39
...core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/MaxNumber.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
|
|
||
| /** | ||
| * Validates that a numeric configuration value is less than or equal to [max]. | ||
| * | ||
| * `null` values are ignored, so this can also be used with nullable numeric fields. | ||
| * | ||
| * Usage: | ||
| * ```kotlin | ||
| * @ConfigSerializable | ||
| * data class RateLimitConfig( | ||
| * @field:MaxNumber(100.0) | ||
| * val percentage: Double = 50.0 | ||
| * ) | ||
| * ``` | ||
| * | ||
| * @property max The inclusive maximum value. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class MaxNumber(val max: Double) { | ||
| companion object { | ||
|
|
||
| /** | ||
| * Configurate constraint factory for [MaxNumber]. | ||
| */ | ||
| internal object Factory : Constraint.Factory<MaxNumber, Number?> { | ||
| override fun make(data: MaxNumber, type: Type): Constraint<Number?> = { number -> | ||
| if (number != null && number.toDouble() > data.max) { | ||
| throw SerializationException(type, "Number is too big: $number, expected <= ${data.max}") | ||
| } | ||
|
twisti-dev marked this conversation as resolved.
|
||
| } | ||
| } | ||
| } | ||
| } | ||
29 changes: 29 additions & 0 deletions
29
...i-core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/MaxSize.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
|
|
||
| /** | ||
| * Specifies a maximum size constraint for collections, maps, arrays, or strings. | ||
| * | ||
| * This annotation enforces that the size or length of the annotated value does not exceed | ||
| * the specified maximum. If the validation fails, a `SerializationException` is thrown | ||
| * with a descriptive error message. | ||
| * | ||
| * @property max The maximum allowed size or length for the annotated value. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class MaxSize(val max: Int) { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<MaxSize, Any?> { | ||
| override fun make(data: MaxSize, type: Type): Constraint<Any?> = { value -> | ||
| val size = value.configSizeOrNull() | ||
| if (size != null && size > data.max) { | ||
| throw SerializationException("Collection size is too large: $size, expected <= ${data.max}") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
29 changes: 29 additions & 0 deletions
29
...re/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/config/constraints/MinDuration.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package dev.slne.surf.api.core.config.constraints | ||
|
|
||
| import dev.slne.surf.api.core.config.type.ConfigDuration | ||
| import org.spongepowered.configurate.objectmapping.meta.Constraint | ||
| import org.spongepowered.configurate.serialize.SerializationException | ||
| import java.lang.reflect.Type | ||
|
|
||
| /** | ||
| * Specifies a minimum duration constraint for configuration values annotated with this annotation. | ||
| * | ||
| * This annotation ensures that durations provided in the configuration meet or exceed | ||
| * the specified minimum value in seconds. If the validation fails, a `SerializationException` | ||
| * is thrown with a descriptive error message. | ||
| * | ||
| * @property seconds The minimum allowed duration in seconds. | ||
| */ | ||
| @Target(AnnotationTarget.FIELD) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class MinDuration(val seconds: Long) { | ||
| companion object { | ||
| internal object Factory : Constraint.Factory<MinDuration, ConfigDuration?> { | ||
| override fun make(data: MinDuration, type: Type): Constraint<ConfigDuration?> = { value -> | ||
| if (value != null && value.value.inWholeSeconds < data.seconds) { | ||
| throw SerializationException("Duration is too short: ${value.value}, expected >= ${data.seconds}s") | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.