types icon indicating copy to clipboard operation
types copied to clipboard

✨ New `DomainName` type

Open LVMVRQUXL opened this issue 1 year ago • 0 comments

📝 Description

We would like to introduce an experimental type named DomainName, representing a domain name in the Internet, in the kotools.types.web package with the following minimum API:

interface DomainName {
    companion object {
        val regex: Regex // Should be inaccessible for Java sources due to the unavailability of 'kotlin.text.Regex' for this language.
        fun create(text: String): DomainName
        fun createOrNull(text: String): DomainName?
    }

    override fun equals(other: Any?): Boolean
    override fun hashCode(): Int
    override fun toString(): String
}

Data validation

Accordingly to the RFC-1035, a domain name should match the following regular expression: ^(?:[A-Za-z][A-Za-z\d-]{0,61}[A-Za-z\d]\.)*[A-Za-z][A-Za-z\d-]{0,61}[A-Za-z\d]$.

Here's the explanation associated to each symbol used in this regular expression:

  • ^ Beginning. Matches the beginning of the string, or the beginning of a line if the multiline flag (m) is enabled.
  • (?:) Non-capturing group. Groups multiple tokens together without creating a capture group.
  • [] Character set. Match any character in the set.
  • A-Z Range. Matches a character in the range "A" to "Z" (char code 65 to 90). Case sensitive.
  • a-z Range. Matches a character in the range "a" to "z" (char code 97 to 122). Case sensitive.
  • \d Digit. Matches any digit character (0-9).
  • - Character. Matches a "-" character (char code 45).
  • {0,61} Quantifier. Match between 0 and 61 of the preceding token.
  • \. Escaped character. Matches a "." character (char code 46).
  • $ End. Matches the end of the string, or the end of a line if the multiline flag (m) is enabled.

Here's an example of calling the create(String) function with a valid input from Kotlin code:

val domain: DomainName = DomainName.create("kotools.org")
println(domain) // types.kotools.org

Serialization and deserialization

The serialization and the deserialization processes of this type should behave like for the String type.

Here's an example of Kotlin code that encodes and decodes this type using the JavaScript Object Notation (JSON) format from kotlinx.serialization:

val domain: DomainName = DomainName.create("kotools.org")
val encoded: String = Json.encodeToString(domain)
println(encoded) // "kotools.org"
val decoded: DomainName = Json.decodeFromString(encoded)
println(decoded == domain) // true

🔗 Dependencies

This issue is blocked by the following items:

  • [x] #394

✅ Checklist

  • [ ] Add the type with a private constructor, update the public API binaries and the unreleased changelog.
  • [ ] Add the regex property, test its behavior with Kotlin, update the public API binaries.
  • [ ] Refactor the EmailAddress.Companion.regex property for using the new DomainName.Companion.regex property, update the unreleased changelog.
  • [ ] Add the create(String) function, test its behavior with Kotlin and its compatibility with Java, update the public API binaries and the unreleased changelog.
  • [ ] Add the createOrNull(String) function, test its behavior with Kotlin and its compatibility with Java, update the public API binaries.
  • [ ] Override the toString() function, test its behavior with Kotlin and its compatibility with Java, update the public API binaries.
  • [ ] Override the equals(Any?) and hashCode() functions, test their behavior with Kotlin and their compatibility with Java, update the public API binaries.
  • [ ] Make the type serializable, test its serialization and deserialization processes behavior with Kotlin, then update the public API binaries.
  • [ ] Create an issue for stabilizing this type.

LVMVRQUXL avatar Dec 14 '23 01:12 LVMVRQUXL