blob: b40ac75b44187bbdb3de10c3132e22a1a19c71f8 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
;; SPDX-License-Identifier: EUPL-1.2
;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
(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))))
|