All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.io.konform.validation.jsonschema.JsonSchema.kt Maven / Gradle / Ivy

There is a newer version: 0.10.0
Show newest version
package io.konform.validation.jsonschema

import io.konform.validation.Constraint
import io.konform.validation.ValidationBuilder
import kotlin.math.roundToInt

public inline fun  ValidationBuilder<*>.type(): Constraint<*> =
    addConstraint(
        "must be of the correct type",
    ) { it is T }

public fun  ValidationBuilder.enum(vararg allowed: T): Constraint =
    addConstraint(
        "must be one of: {0}",
        allowed.joinToString("', '", "'", "'"),
    ) { it in allowed }

public inline fun > ValidationBuilder.enum(): Constraint {
    val enumNames = enumValues().map { it.name }
    return addConstraint(
        "must be one of: {0}",
        enumNames.joinToString("', '", "'", "'"),
    ) { it in enumNames }
}

public fun  ValidationBuilder.const(expected: T): Constraint =
    addConstraint(
        "must be {0}",
        expected?.let { "'$it'" } ?: "null",
    ) { expected == it }

public fun  ValidationBuilder.multipleOf(factor: Number): Constraint {
    val factorAsDouble = factor.toDouble()
    require(factorAsDouble > 0) { "multipleOf requires the factor to be strictly larger than 0" }
    return addConstraint("must be a multiple of '{0}'", factor.toString()) {
        val division = it.toDouble() / factorAsDouble
        division.compareTo(division.roundToInt()) == 0
    }
}

public fun  ValidationBuilder.maximum(maximumInclusive: Number): Constraint =
    addConstraint(
        "must be at most '{0}'",
        maximumInclusive.toString(),
    ) { it.toDouble() <= maximumInclusive.toDouble() }

public fun  ValidationBuilder.exclusiveMaximum(maximumExclusive: Number): Constraint =
    addConstraint(
        "must be less than '{0}'",
        maximumExclusive.toString(),
    ) { it.toDouble() < maximumExclusive.toDouble() }

public fun  ValidationBuilder.minimum(minimumInclusive: Number): Constraint =
    addConstraint(
        "must be at least '{0}'",
        minimumInclusive.toString(),
    ) { it.toDouble() >= minimumInclusive.toDouble() }

public fun  ValidationBuilder.exclusiveMinimum(minimumExclusive: Number): Constraint =
    addConstraint(
        "must be greater than '{0}'",
        minimumExclusive.toString(),
    ) { it.toDouble() > minimumExclusive.toDouble() }

public fun ValidationBuilder.minLength(length: Int): Constraint {
    require(length >= 0) { IllegalArgumentException("minLength requires the length to be >= 0") }
    return addConstraint(
        "must have at least {0} characters",
        length.toString(),
    ) { it.length >= length }
}

public fun ValidationBuilder.maxLength(length: Int): Constraint {
    require(length >= 0) { IllegalArgumentException("maxLength requires the length to be >= 0") }
    return addConstraint(
        "must have at most {0} characters",
        length.toString(),
    ) { it.length <= length }
}

public fun ValidationBuilder.pattern(pattern: String): Constraint = pattern(pattern.toRegex())

/** Enforces the string must be UUID hex format. */
public fun ValidationBuilder.uuid(): Constraint =
    pattern("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$") hint "must be a valid UUID string"

public fun ValidationBuilder.pattern(pattern: Regex): Constraint =
    addConstraint(
        "must match the expected pattern",
        pattern.toString(),
    ) { it.matches(pattern) }

public inline fun  ValidationBuilder.minItems(minSize: Int): Constraint =
    addConstraint(
        "must have at least {0} items",
        minSize.toString(),
    ) {
        when (it) {
            is Iterable<*> -> it.count() >= minSize
            is Array<*> -> it.count() >= minSize
            is Map<*, *> -> it.count() >= minSize
            else -> throw IllegalStateException("minItems can not be applied to type ${T::class}")
        }
    }

public inline fun  ValidationBuilder.maxItems(maxSize: Int): Constraint =
    addConstraint(
        "must have at most {0} items",
        maxSize.toString(),
    ) {
        when (it) {
            is Iterable<*> -> it.count() <= maxSize
            is Array<*> -> it.count() <= maxSize
            is Map<*, *> -> it.count() <= maxSize
            else -> throw IllegalStateException("maxItems can not be applied to type ${T::class}")
        }
    }

public inline fun > ValidationBuilder.minProperties(minSize: Int): Constraint =
    minItems(minSize) hint "must have at least {0} properties"

public inline fun > ValidationBuilder.maxProperties(maxSize: Int): Constraint =
    maxItems(maxSize) hint "must have at most {0} properties"

public inline fun  ValidationBuilder.uniqueItems(unique: Boolean): Constraint =
    addConstraint(
        "all items must be unique",
    ) {
        !unique ||
            when (it) {
                is Iterable<*> -> it.distinct().count() == it.count()
                is Array<*> -> it.distinct().count() == it.count()
                else -> throw IllegalStateException("uniqueItems can not be applied to type ${T::class}")
            }
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy