From 191a27fd142af7a14ca6ad1abcd293f09e63f6ad Mon Sep 17 00:00:00 2001 From: Uko Kokņevičs Date: Mon, 13 Oct 2025 05:21:41 +0300 Subject: Move serializing stuff from bot/impl to a new file --- src/serializing.lisp | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/serializing.lisp (limited to 'src/serializing.lisp') diff --git a/src/serializing.lisp b/src/serializing.lisp new file mode 100644 index 0000000..7fafb3a --- /dev/null +++ b/src/serializing.lisp @@ -0,0 +1,68 @@ +;; SPDX-License-Identifier: EUPL-1.2 +;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs +(defpackage :ukkoclot/serializing + (:use :c2cl :iterate) + (:import-from :log) + (:import-from :ukkoclot/strings :lisp->snake-case) + (:local-nicknames + (:jzon :com.inuoe.jzon)) + (:export :fixup-args :fixup-value :parse-value :try-parse-value)) +(in-package :ukkoclot/serializing) + +(defun fixup-args (args) + (iter (for (key . value) in args) + (collect + (cons (string-downcase (lisp->snake-case (symbol-name 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 (car 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 (car type) 'or) + (iter (for el-type in (cdr 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)))) + +(defun try-parse-value (type json) + (handler-case (values t (parse-value type json)) + (error () (values nil nil)))) -- cgit v1.2.3