identifier.clj
Branches > main > 0ae9a0a > files / src / net / bowmap / server / packet / identifier.clj
(ns net.bowmap.server.packet.identifier
(:require
[clojure.string :as str]
[net.bowmap.server.packet.schema.minecraft :as mc]))
(def namespace-regex #"^[a-z0-9.\-_]+$")
(def name-regex #"^#?[a-z0-9.\-_:]+$")
(defn identifier?
"Returns whether 'x' is a valid protocol identifier - a namspace qualified keyword.
Colons in the name of an identifier may used to separate directories.
If the identifier's name starts with a number, it must be prefixed with a '#'.
Identifiers in the 'minecraft' namespace should use the fully qualified minecraft
schema namespace, rather than :minecraft/name."
[x]
(and (qualified-keyword? x)
(re-matches namespace-regex (namespace x))
(re-matches name-regex (name x))))
(defn encode-namespace
"Encodes an identifier namespace into a valid protocol namespace."
[identifier]
(if (= (namespace identifier) mc/minecraft-namespace)
"minecraft"
(namespace identifier)))
(defn encode-name
"Encodes an identifier name into a valid protocol name."
[identifier]
(-> (name identifier)
(str/replace-first #"^#" "")
(str/replace ":" "/")))
(defn encode-identifier
"Encodes an identifier as a protocol identifier string."
[identifier]
(str (encode-namespace identifier) ":" (encode-name identifier)))
(defn decode-namespace
"Decodes an encoded identifier namespace into a valid identifier object namespace."
[encoded-namespace]
(if (= encoded-namespace "minecraft")
mc/minecraft-namespace
encoded-namespace))
(defn decode-name
"Decodes an encoded identifier name into a valid identifier object name."
[encoded-name]
(-> encoded-name
(str/replace #"/" ":")
(str/replace #"^([0-9])" "#$1")))
(defn decode-identifier
"Returns an identifier from an encoded string namespace and name.
Throws if the encoded values are not valid identifiers."
[namespace name]
(let [identifier (keyword (decode-namespace namespace) (decode-name name))]
(if (identifier? identifier)
identifier
(throw (ex-info "Cannot decode that value into an identifier."
{:namespace namespace :name name})))))
(defn tag
"Returns the protocol tag of an identifier, which is the encoded identifier
preceded by a '#'."
[identifier]
(apply str "#" (encode-identifier identifier)))