;; SPDX-License-Identifier: EUPL-1.2 ;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs (defpackage :ukkoclot/src/serializing (:use :c2cl :iterate) (:import-from :log) (:import-from :serapeum :->) (:import-from :str) (:local-nicknames (:jzon :com.inuoe.jzon)) (:export :fixup-args :fixup-value :parse-value :try-parse-value)) (in-package :ukkoclot/src/serializing) ;; TODO: Better types, input is an (alist t t) output is an (alist string t) (-> fixup-args (list) list) (defun fixup-args (args) (iter (for (key . value) in args) (collect (cons (str:snake-case key) (fixup-value value))))) (defgeneric fixup-value (value) (:documentation "Fixup outgoing /top-level/ `value' before passing it to telegram.") (:method (value) (jzon:stringify value :pretty *print-pretty*)) (:method ((value null)) value) (:method ((value number)) value) (:method ((value pathname)) value) (:method ((value string)) value)) (defgeneric parse-value (type json) (:documentation "Parse incoming value of `type' from the parsed `json'.") (:method (type json) (log:error "I don't know how to parse simple type ~A!" type) (error "I don't know how to parse simple type ~A!" type)) (:method ((type (eql 'boolean)) json) (check-type json boolean) json) (:method ((type (eql 'integer)) json) (check-type json integer) json) (:method ((type (eql 'null)) json) (check-type json null) json) (:method ((type (eql 'string)) json) (check-type json string) json)) (defmethod parse-value ((type cons) json) (cond ((and (eq (first type) 'array) (null (cddr type))) (when json (let ((element-type (cadr type))) (iter (for element in-vector json) (collect (parse-value element-type element) result-type vector))))) ((eq (first type) 'or) (iter (for el-type in (rest type)) (multiple-value-bind (success res) (try-parse-value el-type json) (when success (return res))) (finally (error "Failed to parse ~S as ~A!" json type)))) (t (error "I don't know how to parse complex type ~A!" type)))) (-> try-parse-value (t t) (values boolean t &optional)) (defun try-parse-value (type json) (handler-case (values t (parse-value type json)) (error () (values nil nil))))