identifier.clj
Branches > main > 0afd85a > 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 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 string namespace."
[identifier]
(if (= (namespace identifier) mc/minecraft-namespace)
"minecraft"
(namespace identifier)))
(defn encode-name
"Encodes an identifier name into a string name."
[identifier]
(-> (name identifier)
(str/replace-first #"^#" "")
(str/replace ":" "/")))
(defn encode-identifier
"Encodes an identifier as a 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 a tag reference to the identifier."
[identifier]
(tagged-literal `tag identifier))
(defn tag? [x]
(and (tagged-literal? x)
(= `tag (:tag x))))
(defn encode-tag
"Encodes a tag reference as a string: the encoded identifier preceded by '#'."
[{:keys! [form]}]
(str "#" (encode-identifier form)))