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

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

package io.konform.validation.jsonschema

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

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

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

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

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


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
    }
}

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

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

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

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

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 }
}

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 }
}


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


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


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}")
    }
}


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}")
    }
}

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

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

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