changelog shortlog graph tags branches files raw help

Mercurial > demo / changeset: refactor1

changeset 22: ba323d8c0f93
parent 21: 1059e7b52e47
child 23: dc7e11694976
author: ellis <ellis@rwest.io>
date: Sat, 03 Jun 2023 22:48:46 -0400
files: Cargo.toml Dockerfile build.rs cbindgen.toml cfg.lisp db.lisp default.cfg demo.asd demo.lisp ffi.lisp ffi/build.py ffi/demo.h ffi/quiche.h gen.rs install.lisp lib.rs makefile obj/Cargo.toml obj/proc_macros/Cargo.toml obj/proc_macros/src/derive.rs obj/proc_macros/src/lib.rs obj/src/auth.rs obj/src/cfg.rs obj/src/database.rs obj/src/err.rs obj/src/hash.rs obj/src/id.rs obj/src/lib.rs obj/src/network.rs obj/src/types.rs package.lisp pkg.lisp readme.org rs.lisp src/build.rs src/cbindgen.toml src/cfg.lisp src/crates/obj/Cargo.toml src/crates/obj/proc_macros/Cargo.toml src/crates/obj/proc_macros/src/derive.rs src/crates/obj/proc_macros/src/lib.rs src/crates/obj/src/auth.rs src/crates/obj/src/cfg.rs src/crates/obj/src/database.rs src/crates/obj/src/err.rs src/crates/obj/src/hash.rs src/crates/obj/src/id.rs src/crates/obj/src/lib.rs src/crates/obj/src/network.rs src/crates/obj/src/types.rs src/crates/ui/Cargo.toml src/crates/ui/build.rs src/crates/ui/config.slint src/crates/ui/img/ayo.jpeg src/crates/ui/img/treez.png src/crates/ui/index.html src/crates/ui/lib.rs src/crates/ui/main.rs src/crates/ui/pages.slint src/crates/ui/pages/about.slint src/crates/ui/pages/controls.slint src/crates/ui/pages/list_view.slint src/crates/ui/pages/page.slint src/crates/ui/pages/table_view.slint src/crates/ui/pages/text_edit.slint src/crates/ui/sidebar.slint src/crates/ui/ui.slint src/db.lisp src/demo.lisp src/ffi.lisp src/gen.rs src/lib.rs src/rs.lisp src/tests.lisp src/tests/demo_test.c src/tests/demo_test.py src/tests/prime-test.lisp src/tk.lisp src/ui.lisp tests.lisp tests/demo_test.c tests/demo_test.py tests/prime-test.lisp tk.lisp tools/ci.nu tools/deps.nu tools/scripts/check.ros tools/scripts/db.ros tools/scripts/demo.ros tools/scripts/pack.ros tools/scripts/test.ros tools/vc.nu ui.lisp ui/Cargo.toml ui/build.rs ui/config.slint ui/img/ayo.jpeg ui/img/treez.png ui/index.html ui/lib.rs ui/main.rs ui/pages.slint ui/pages/about.slint ui/pages/controls.slint ui/pages/list_view.slint ui/pages/page.slint ui/pages/table_view.slint ui/pages/text_edit.slint ui/sidebar.slint ui/ui.slint
description: refactor1
     1.1--- a/Cargo.toml	Sat Jun 03 19:57:46 2023 -0400
     1.2+++ b/Cargo.toml	Sat Jun 03 22:48:46 2023 -0400
     1.3@@ -1,14 +1,2 @@
     1.4-[package]
     1.5-name = "demo"
     1.6-version = "0.1.0"
     1.7-build = "build.rs"
     1.8-[lib]
     1.9-path = "lib.rs"
    1.10-crate-type = ["rlib","cdylib"]
    1.11 [workspace]
    1.12-members = ["obj","ui"]
    1.13-[dependencies]
    1.14-libc = "0.2"
    1.15-obj = {version = "0.1.0",path = "obj"}
    1.16-[build-dependencies]
    1.17-cbindgen = "0.24.3"
    1.18\ No newline at end of file
    1.19+members = ["src/crates/obj","src/crates/ui"]
     2.1--- a/Dockerfile	Sat Jun 03 19:57:46 2023 -0400
     2.2+++ b/Dockerfile	Sat Jun 03 22:48:46 2023 -0400
     2.3@@ -1,38 +1,10 @@
     2.4-ARG ROSWELL_IMAGE=fukamachi/roswell
     2.5-ARG ROSWELL_VERSION
     2.6-ARG OS=debian
     2.7-FROM fukamachi/roswell:latest-$OS AS build-env
     2.8-ARG OS
     2.9+ARG OS=archlinux
    2.10 ARG VERSION
    2.11 ADD https://github.com/sbcl/sbcl/archive/sbcl-$VERSION.tar.gz sbcl.tar.gz
    2.12 
    2.13 RUN set -x; \
    2.14-  arch="$(case $(uname -m) in amd64|x86_64) echo x86-64;; aarch64) echo arm64;; *) uname -m ;; esac)"; \
    2.15-  if [ "$OS" = "alpine" ]; then \
    2.16-    apk add --update build-base linux-headers zstd-dev; \
    2.17-  else \
    2.18-    apt-get update && apt-get -y install --no-install-recommends \
    2.19-      build-essential \
    2.20-      zlib1g-dev \
    2.21-      libzstd-dev \
    2.22-      time; \
    2.23-  fi; \
    2.24-  ros install sbcl-bin/2.2.7 && \
    2.25   tar xvfz sbcl.tar.gz && rm sbcl.tar.gz && cd "sbcl-sbcl-${VERSION}" && \
    2.26-  echo "\"$VERSION\"" > version.lisp-expr && \
    2.27-  (sh make.sh \
    2.28-      --with-sb-core-compression \
    2.29-      "--xc-host=ros -L sbcl-bin without-roswell=t --no-rc run" \
    2.30-      "--prefix=$HOME/.roswell/impls/$arch/linux/sbcl-bin/$VERSION/" || true) \
    2.31-    && sh install.sh && \
    2.32-    rm -f "/root/.roswell/impls/$arch/linux/sbcl-bin/$VERSION/lib/sbcl/sbcl.core.old" \
    2.33-      && rm -f "/root/.roswell/impls/$arch/linux/sbcl-bin/$VERSION/bin/sbcl.old" \
    2.34-      && find "/root/.roswell/impls/$arch/linux/sbcl-bin" -maxdepth 1 -mindepth 1 | grep -v "/sbcl-bin/$VERSION$" | xargs rm -rf || true \
    2.35-      && rm -rf "/root/.roswell/impls/log"
    2.36-
    2.37-FROM $ROSWELL_IMAGE:$ROSWELL_VERSION-$OS
    2.38-# hadolint ignore=DL3010
    2.39-COPY --from=build-env /root/.roswell/impls /root/.roswell/impls
    2.40+  echo "\"$VERSION\"" > version.s && \
    2.41 
    2.42 ARG BUILD_DATE
    2.43 ARG VCS_REF
    2.44@@ -41,25 +13,7 @@
    2.45 
    2.46 LABEL org.label-schema.build-date=$BUILD_DATE \
    2.47       org.label-schema.vcs-ref=$VCS_REF \
    2.48-      org.label-schema.vcs-url="https://github.com/fukamachi/dockerfiles" \
    2.49       org.label-schema.version=$VERSION \
    2.50       org.label-schema.schema-version="1.0"
    2.51 
    2.52-# hadolint ignore=DL3018
    2.53-RUN set -x; \
    2.54-  if [ "$OS" = "alpine" ]; then \
    2.55-    apk add --update --no-cache zstd-libs; \
    2.56-  fi; \
    2.57-  printf "setup.time\t0\t%s\n" "$(( $(date +%s) + 2208988800 ))" > ~/.roswell/config && \
    2.58-  printf "sbcl-bin.version\t0\t%s\n" "$VERSION" >> ~/.roswell/config && \
    2.59-  printf "default.lisp\t0\tsbcl-bin\n" >> ~/.roswell/config && \
    2.60-  ros setup && \
    2.61-  ros -e '(mapc (function ql-dist:uninstall) (ql-dist:installed-releases t))' \
    2.62-    && rm -f /root/.roswell/lisp/quicklisp/tmp/quicklisp.tar \
    2.63-    && rm -rf /root/.roswell/archives/* /root/.roswell/src/sbcl-* /root/.cache/common-lisp/sbcl-*/root/.roswell/lisp/quicklisp/dists/quicklisp/software
    2.64-
    2.65-RUN set -x; \
    2.66-  printf '#!/bin/sh\nexec ros run -- "$@"\n' > /usr/local/bin/sbcl \
    2.67-  && chmod u+x /usr/local/bin/sbcl
    2.68-
    2.69 ENTRYPOINT ["/usr/local/bin/sbcl"]
    2.70\ No newline at end of file
     3.1--- a/build.rs	Sat Jun 03 19:57:46 2023 -0400
     3.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3@@ -1,17 +0,0 @@
     3.4-use std::env;
     3.5-use std::fs::create_dir;
     3.6-use std::path::PathBuf;
     3.7-fn main() {
     3.8-  let crate_dir: PathBuf = env::var("CARGO_MANIFEST_DIR")
     3.9-    .expect("CARGO_MANIFEST_DIR env var is not defined")
    3.10-    .into();
    3.11-  // let mpk_py = "build.py";
    3.12-  let build_dir = crate_dir.join("ffi/");
    3.13-  if !build_dir.exists() {
    3.14-    create_dir(&build_dir).unwrap();
    3.15-  }
    3.16-  cbindgen::generate(crate_dir)
    3.17-    .expect("Unable to find cbindgen.toml configuration file")
    3.18-    .write_to_file(build_dir.join("demo.h"));
    3.19-  
    3.20-}
     4.1--- a/cbindgen.toml	Sat Jun 03 19:57:46 2023 -0400
     4.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3@@ -1,14 +0,0 @@
     4.4-include_guard = "demo_h"
     4.5-autogen_warning = "/* DO NOT TOUCH */"
     4.6-include_version = true
     4.7-language = "C"
     4.8-cpp_compat = true
     4.9-line_length = 88
    4.10-documentation = true	
    4.11-[parse]
    4.12-parse_deps = true
    4.13-include = ["obj","fig","libc"]
    4.14-extra_bindings = ["obj","fig","libc"]
    4.15-#expand = ["demo","obj"]
    4.16-#[parse.expand]
    4.17-#crates = ["demo"]
    4.18\ No newline at end of file
     6.1--- a/db.lisp	Sat Jun 03 19:57:46 2023 -0400
     6.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3@@ -1,197 +0,0 @@
     6.4-(in-package :demo)
     6.5-
     6.6-(define-foreign-library rocksdb
     6.7-  (:win32 "rocksdb")
     6.8-  (t (:default "librocksdb")))
     6.9-
    6.10-(use-foreign-library rocksdb)
    6.11-
    6.12-(defcfun ("rocksdb_options_create" create-options) :pointer)
    6.13-(defcfun ("rocksdb_options_destroy" destroy-options) :void (options :pointer))
    6.14-(defcfun ("rocksdb_options_increase_parallelism" increase-parallelism) :void (opt :pointer) (total-threads :int))
    6.15-(defcfun ("rocksdb_options_optimize_level_style_compaction" optimize-level-style-compaction) :void (opt :pointer) (memtable_memory_budget :uint64))
    6.16-(defcfun ("rocksdb_options_set_create_if_missing" set-create-if-missing) :void (opt :pointer) (val :boolean))
    6.17-
    6.18-(defcfun ("rocksdb_writeoptions_create" create-writeoptions) :pointer)
    6.19-(defcfun ("rocksdb_writeoptions_destroy" destroy-writeoptions) :void (opt :pointer))
    6.20-(defcfun ("rocksdb_readoptions_create" create-readoptions) :pointer)
    6.21-(defcfun ("rocksdb_readoptions_destroy" destroy-readoptions) :void (opt :pointer))
    6.22-
    6.23-(defcfun ("rocksdb_open" open-db*) :pointer (opt :pointer) (name :string) (errptr :pointer))
    6.24-(defcfun ("rocksdb_close" close-db) :void (opt :pointer))
    6.25-(defcfun ("rocksdb_cancel_all_background_work" cancel-all-background-work) :void (db :pointer) (wait :boolean))
    6.26-
    6.27-(defcfun ("rocksdb_put" put*) :void (db :pointer) (options :pointer) (key :pointer) (keylen :unsigned-int) (val :pointer) (vallen :unsigned-int) (errptr :pointer))
    6.28-(defcfun ("rocksdb_get" get*) :pointer (db :pointer) (options :pointer) (key :pointer) (keylen :unsigned-int) (vallen :pointer) (errptr :pointer))
    6.29-
    6.30-(defcfun ("rocksdb_create_iterator" create-iter*) :pointer (db :pointer) (opt :pointer))
    6.31-(defcfun ("rocksdb_iter_destroy" destroy-iter) :void (iter :pointer))
    6.32-(defcfun ("rocksdb_iter_seek_to_first" move-iter-to-first) :void (iter :pointer))
    6.33-(defcfun ("rocksdb_iter_valid" valid-iter-p) :boolean (iter :pointer))
    6.34-(defcfun ("rocksdb_iter_next" move-iter-forward) :void (iter :pointer))
    6.35-(defcfun ("rocksdb_iter_prev" move-iter-backward) :void (iter :pointer))
    6.36-(defcfun ("rocksdb_iter_key" iter-key*) :pointer (iter :pointer) (klen-ptr :pointer))
    6.37-(defcfun ("rocksdb_iter_value" iter-value*) :pointer (iter :pointer) (vlen-ptr :pointer))
    6.38-
    6.39-(define-condition unable-to-open-db (error)
    6.40-  ((db-path :initarg :db-path
    6.41-            :reader db-path)
    6.42-   (error-message :initarg :error-message
    6.43-                  :reader error-message)))
    6.44-
    6.45-(defmethod print-object ((obj unable-to-open-db) stream)
    6.46-  (print-unreadable-object (obj stream :type t :identity t)
    6.47-    (format stream "error-message=~A" (error-message obj))))
    6.48-
    6.49-(define-condition unable-to-put-key-value-to-db (error)
    6.50-  ((db :initarg :db
    6.51-       :reader db)
    6.52-   (key :initarg :key
    6.53-        :reader key)
    6.54-   (val :initarg :val
    6.55-        :reader val)
    6.56-   (error-message :initarg :error-message
    6.57-                  :reader error-message)))
    6.58-
    6.59-(define-condition unable-to-get-value-to-db (error)
    6.60-  ((db :initarg :db
    6.61-       :reader db)
    6.62-   (key :initarg :key
    6.63-        :reader key)
    6.64-   (error-message :initarg :error-message
    6.65-                  :reader error-message)))
    6.66-
    6.67-(defun open-db (db-path &optional opt)
    6.68-  (unless opt
    6.69-    (setq opt (create-options)))
    6.70-  (let ((errptr (foreign-alloc :pointer)))
    6.71-    (setf (mem-ref errptr :pointer) (null-pointer))
    6.72-    (let* ((db-path (if (pathnamep db-path)
    6.73-                        (namestring db-path)
    6.74-                        db-path))
    6.75-           (db (open-db* opt db-path errptr))
    6.76-           (err (mem-ref errptr :pointer)))
    6.77-      (unless (null-pointer-p err)
    6.78-        (error 'unable-to-open-db
    6.79-               :db-path db-path
    6.80-               :error-message (foreign-string-to-lisp err)))
    6.81-      db)))
    6.82-
    6.83-(defmacro clone-octets-to-foreign (lisp-array foreign-array)
    6.84-  (let ((i (gensym)))
    6.85-    `(loop for ,i from 0 below (length ,lisp-array)
    6.86-           do (setf (mem-aref ,foreign-array :unsigned-char ,i)
    6.87-                    (aref ,lisp-array ,i)))))
    6.88-
    6.89-(defmacro clone-octets-from-foreign (foreign-array lisp-array len)
    6.90-  (let ((i (gensym)))
    6.91-    `(loop for ,i from 0 below ,len
    6.92-           do (setf (aref ,lisp-array ,i)
    6.93-                    (mem-aref ,foreign-array :unsigned-char ,i)))))
    6.94-
    6.95-(defun put-kv (db key val &optional opt)
    6.96-  (unless opt
    6.97-    (setq opt (create-writeoptions)))
    6.98-  (with-foreign-objects ((errptr :pointer)
    6.99-                         (key* :unsigned-char (length key))
   6.100-                         (val* :unsigned-char (length val)))
   6.101-    (clone-octets-to-foreign key key*)
   6.102-    (clone-octets-to-foreign val val*)
   6.103-    (setf (mem-ref errptr :pointer) (null-pointer))
   6.104-    (put* db
   6.105-          opt
   6.106-          key*
   6.107-          (length key)
   6.108-          val*
   6.109-          (length val)
   6.110-          errptr)
   6.111-    (let ((err (mem-ref errptr :pointer)))
   6.112-      (unless (null-pointer-p err)
   6.113-        (error 'unable-to-put-key-value-to-db
   6.114-               :db db
   6.115-               :key key
   6.116-               :val val
   6.117-               :error-message (foreign-string-to-lisp err))))))
   6.118-
   6.119-(defun put-kv-str (db key val &optional opt)
   6.120-  (let ((key-octets (babel:string-to-octets key))
   6.121-        (val-octets (babel:string-to-octets val)))
   6.122-    (put-kv db key-octets val-octets opt)))
   6.123-
   6.124-(defun get-kv (db key &optional opt)
   6.125-  (unless opt
   6.126-    (setq opt (create-readoptions)))
   6.127-
   6.128-  (with-foreign-objects ((val-len-ptr :unsigned-int)
   6.129-                         (errptr :pointer)
   6.130-                         (key* :unsigned-char (length key)))
   6.131-    (clone-octets-to-foreign key key*)
   6.132-    (setf (mem-ref errptr :pointer) (null-pointer))
   6.133-    (let ((val (get* db
   6.134-                     opt
   6.135-                     key*
   6.136-                     (length key)
   6.137-                     val-len-ptr
   6.138-                     errptr)))
   6.139-      (let ((err (mem-ref errptr :pointer)))
   6.140-        (unless (null-pointer-p err)
   6.141-          (error 'unable-to-get-value-to-db
   6.142-                 :db db
   6.143-                 :key key
   6.144-                 :error-message (foreign-string-to-lisp err)))
   6.145-        
   6.146-        (unless (null-pointer-p val)
   6.147-          (let* ((val-len (mem-ref val-len-ptr :unsigned-int))
   6.148-                 (val* (make-array val-len
   6.149-                                      :element-type '(unsigned-byte 8))))
   6.150-            (clone-octets-from-foreign val val* val-len)
   6.151-            val*))))))
   6.152-
   6.153-(defun get-kv-str (db key &optional opt)
   6.154-  (let ((key-octets (babel:string-to-octets key)))
   6.155-    (let ((#1=val-octets (get-kv db key-octets opt)))
   6.156-      (when #1#
   6.157-        (babel:octets-to-string #1#)))))
   6.158-
   6.159-(defun create-iter (db &optional opt)
   6.160-  (unless opt
   6.161-    (setq opt (create-readoptions)))
   6.162-  (create-iter* db opt))
   6.163-
   6.164-(defun iter-key (iter)
   6.165-  (with-foreign-objects ((klen-ptr :unsigned-int))
   6.166-    (setf (mem-ref klen-ptr :unsigned-int) 0)
   6.167-    (let* ((key-ptr (iter-key* iter klen-ptr))
   6.168-           (klen (mem-ref klen-ptr :unsigned-int))
   6.169-           (key (make-array klen :element-type '(unsigned-byte 8))))
   6.170-      (clone-octets-from-foreign key-ptr key klen)
   6.171-      key)))
   6.172-
   6.173-(defun iter-key-str (iter)
   6.174-  (let ((#1=key-octets (iter-key iter)))
   6.175-    (when #1#
   6.176-      (babel:octets-to-string #1#))))
   6.177-
   6.178-(defun iter-value (iter)
   6.179-  (with-foreign-objects ((len-ptr :unsigned-int))
   6.180-    (setf (mem-ref len-ptr :unsigned-int) 0)
   6.181-    (let* ((value-ptr (iter-value* iter len-ptr))
   6.182-           (vlen (mem-ref len-ptr :unsigned-int))
   6.183-           (value* (make-array vlen :element-type '(unsigned-byte 8))))
   6.184-      (clone-octets-from-foreign value-ptr value* vlen)
   6.185-      value*)))
   6.186-
   6.187-(defun iter-value-str (iter)
   6.188-  (let ((#1=val-octets (iter-value iter)))
   6.189-    (when #1#
   6.190-      (babel:octets-to-string #1#))))
   6.191-
   6.192-(defmacro with-open-db ((db-var db-path &optional opt) &body body)
   6.193-  `(let ((,db-var (open-db ,db-path ,opt)))
   6.194-     (unwind-protect (progn ,@body)
   6.195-       (close-db ,db-var))))
   6.196-
   6.197-(defmacro with-iter ((iter-var db &optional opt) &body body)
   6.198-  `(let ((,iter-var (create-iter ,db ,opt)))
   6.199-     (unwind-protect (progn ,@body)
   6.200-       (destroy-iter ,iter-var))))
     7.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2+++ b/default.cfg	Sat Jun 03 22:48:46 2023 -0400
     7.3@@ -0,0 +1,11 @@
     7.4+;;; default-config.se --- Default demo configuration -*- mode: lisp-data -*-
     7.5+
     7.6+;; The configuration for this demo is specified in S-Expressions.
     7.7+;; Check 'docs/config.org' for available options.
     7.8+(:service "weather"
     7.9+ :host "localhost"
    7.10+ :port 8888
    7.11+ :client (:name "guest"
    7.12+	  :type "docker"
    7.13+	  :mode "release"
    7.14+	  :theme "dark"))
     8.1--- a/demo.asd	Sat Jun 03 19:57:46 2023 -0400
     8.2+++ b/demo.asd	Sat Jun 03 22:48:46 2023 -0400
     8.3@@ -31,13 +31,8 @@
     8.4   :build-pathname "demo"
     8.5   :entry-point "demo:main")
     8.6 
     8.7-;; (asdf:defsystem "cl-demo:tests"
     8.8-  ;; :depends-on ("cl-demo" "fiveam")
     8.9+;; (asdf:defsystem "demo.tests"
    8.10+  ;; :depends-on ("demo" "fiveam")
    8.11   ;; :components ((:file "tests"))
    8.12-  ;; :perform (test-op (o c) (symbol-call :fiveam '#:run! :cl-demo))
    8.13+  ;; :perform (test-op (o c) (symbol-call :fiveam '#:run! "demo:main"))
    8.14   ;; )
    8.15-
    8.16-;; (deploy:define-library cl+ssl::libssl
    8.17-;;   :path "/usr/local/Cellar/openssl@3/3.1.1/lib/libssl.dylib")
    8.18-;; (deploy:define-library cl+ssl::libcrypto
    8.19-;;   :path "/usr/local/Cellar/openssl@3/3.1.1/lib/libcrypto.dylib")
     9.1--- a/demo.lisp	Sat Jun 03 19:57:46 2023 -0400
     9.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3@@ -1,45 +0,0 @@
     9.4-;; demo.lisp
     9.5-(in-package :demo)
     9.6-
     9.7-(defparameter demo-path (merge-pathnames "cl-demo" (uiop:temporary-directory)))
     9.8-
     9.9-(defvar db-path (merge-pathnames "db" demo-path))
    9.10-
    9.11-(defun cli-opts ()
    9.12-  "Returns the top-level CLI options."
    9.13-  (list
    9.14-   (cli:make-option
    9.15-    :string
    9.16-    :description "demo app to run"
    9.17-    :short-name #\x
    9.18-    :long-name "app"
    9.19-    :initial-value "client"
    9.20-    :env-vars '("DEMO_APP")
    9.21-    :key :app)
    9.22-   (cli:make-option
    9.23-    :string
    9.24-    :description "path to config"
    9.25-    :short-name #\c
    9.26-    :long-name "config"
    9.27-    :initial-value "$DEMO_PATH/.fig"
    9.28-    :env-vars '("DEMO_CONFIG"))))
    9.29-
    9.30-(defun cli-handler (cmd)
    9.31-  "Handler for the `demo' command."
    9.32-  (let ((app (cli:getopt cmd :app)))
    9.33-    (format t "running: ~A!~%" app)))
    9.34-
    9.35-(defun cli-cmd ()
    9.36-  "Our demo command."
    9.37-  (cli:make-command
    9.38-   :name "demo"
    9.39-   :description "A collection of demos"
    9.40-   :version "1.0.0"
    9.41-   :authors '("ellis <ellis@rwest.io>")
    9.42-   :license "WTFPL"
    9.43-   :options (cli-opts)
    9.44-   :handler #'cli-handler))
    9.45-
    9.46-(defun main ()
    9.47-  "A demo of some common-lisp functionality."
    9.48-  (cli:run (cli-cmd)))
    10.1--- a/ffi.lisp	Sat Jun 03 19:57:46 2023 -0400
    10.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3@@ -1,28 +0,0 @@
    10.4-(in-package :demo)
    10.5-(defparameter quiche-lib-path #p"./ffi/libquiche.dylib")
    10.6-;;(defparameter rocksdb-lib-path #p"./ffi/librocksdb.dylib")
    10.7-(defparameter demo-lib-path (find-rs-cdylib "libdemo.dylib"))
    10.8-(defmacro find-rs-cdylib (name &optional debug)
    10.9-  "Find the rust dll specified by NAME."
   10.10-  (cond
   10.11-    ((uiop:directory-exists-p (merge-pathnames *cargo-target* "release"))
   10.12-     `,(mkstr "./target/release/" name))
   10.13-    ((uiop:directory-exists-p  (merge-pathnames *cargo-target* "debug"))
   10.14-     `,(mkstr "./target/debug/" name))
   10.15-    (t `(progn
   10.16-	 ,(uiop:run-program '("cargo" "build" (unless debug "--release")) :output t)
   10.17-	 (find-rs-cdylib ,name ,debug)))))
   10.18-
   10.19-(define-foreign-library demo
   10.20-  (:win32 (:default "demo"))
   10.21-  (t (:default "libdemo")))
   10.22-(define-foreign-library quiche
   10.23-  (:win32 (:default "quiche"))
   10.24-  (t (:default "libquiche")))
   10.25-;; (define-foreign-library rocksdb
   10.26-;;   (:win32 (:default "rocksdb"))
   10.27-;;   (t (:default "librocksdb")))
   10.28-
   10.29-(defun load-libdemo () (load-foreign-library (find-rs-cdylib "libdemo.dylib")))
   10.30-(defun install-quiche-lib (&optional path) (load-foreign-library (or path quiche-lib-path)))
   10.31-;; (defun install-rocksdb-lib (&optional path) (load-foreign-library (or path rocksdb-lib-path)))
    11.1--- a/ffi/build.py	Sat Jun 03 19:57:46 2023 -0400
    11.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3@@ -1,48 +0,0 @@
    11.4-try:
    11.5-    from cffi import FFI
    11.6-except ImportError:
    11.7-    print("pip install cffi, included with PyPy")
    11.8-
    11.9-import os
   11.10-import re
   11.11-import pathlib
   11.12-
   11.13-
   11.14-def parse_header(header):
   11.15-    h = open(header, "r").read().lstrip()
   11.16-    cdef = re.sub(
   11.17-        r"^(#|\s*\/*\*|extern).*[\r\n]|.*\"C\"$|^(?:[\t ]*(?:\r?\n|\r))+",
   11.18-        "",
   11.19-        h,
   11.20-        flags=re.MULTILINE,
   11.21-    )
   11.22-    return cdef
   11.23-
   11.24-
   11.25-def init_ffi(cdef):
   11.26-    ffi = FFI()
   11.27-    ffi.set_source(
   11.28-        "_demo",
   11.29-        """
   11.30-        #include "demo.h"
   11.31-        """,
   11.32-#        libraries=["demo"],
   11.33-        library_dirs=["."],
   11.34-        include_dirs=["."],
   11.35-    )
   11.36-
   11.37-    ffi.cdef(cdef)
   11.38-
   11.39-    return ffi
   11.40-
   11.41-
   11.42-def compile(ffi, lib_dir, v):
   11.43-    os.environ["LD_RUN_PATH"] = os.path.abspath(lib_dir)
   11.44-    ffi.compile(verbose=v)
   11.45-
   11.46-
   11.47-if __name__ == "__main__":
   11.48-    build_dir = pathlib.Path(__file__).parent
   11.49-    cdef = parse_header(build_dir / "demo.h")
   11.50-    print(cdef)
   11.51-    compile(init_ffi(cdef), build_dir, True)
    12.1--- a/ffi/demo.h	Sat Jun 03 19:57:46 2023 -0400
    12.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3@@ -1,66 +0,0 @@
    12.4-#ifndef demo_h
    12.5-#define demo_h
    12.6-
    12.7-/* Generated with cbindgen:0.24.3 */
    12.8-
    12.9-/* DO NOT TOUCH */
   12.10-
   12.11-#include <stdarg.h>
   12.12-#include <stdbool.h>
   12.13-#include <stdint.h>
   12.14-#include <stdlib.h>
   12.15-
   12.16-#define KEY_LEN 32
   12.17-
   12.18-#define OUT_LEN 32
   12.19-
   12.20-#define OUT_LEN_HEX (OUT_LEN * 2)
   12.21-
   12.22-typedef struct CustomService CustomService;
   12.23-
   12.24-/**
   12.25- * APPLICATION TYPES
   12.26- */
   12.27-typedef struct Service Service;
   12.28-
   12.29-#ifdef __cplusplus
   12.30-extern "C" {
   12.31-#endif // __cplusplus
   12.32-
   12.33-void free_service(struct Service *ptr);
   12.34-
   12.35-struct Service *service_from_string(const char *ptr);
   12.36-
   12.37-struct Service *service_from_json_string(const char *ptr);
   12.38-
   12.39-char *service_to_json_string(const struct Service *ptr);
   12.40-
   12.41-struct Service *service_from_ron_string(const char *ptr);
   12.42-
   12.43-char *service_to_ron_string(const struct Service *ptr);
   12.44-
   12.45-struct Service *service_decode(const uint8_t *ptr, size_t len);
   12.46-
   12.47-uint8_t *service_encode(const struct Service *ptr);
   12.48-
   12.49-void free_custom_service(struct CustomService *ptr);
   12.50-
   12.51-struct CustomService *custom_service_from_string(const char *ptr);
   12.52-
   12.53-struct CustomService *custom_service_from_json_string(const char *ptr);
   12.54-
   12.55-char *custom_service_to_json_string(const struct CustomService *ptr);
   12.56-
   12.57-struct CustomService *custom_service_from_ron_string(const char *ptr);
   12.58-
   12.59-char *custom_service_to_ron_string(const struct CustomService *ptr);
   12.60-
   12.61-struct CustomService *custom_service_decode(const uint8_t *ptr, size_t len);
   12.62-
   12.63-uint8_t *custom_service_encode(const struct CustomService *ptr);
   12.64-
   12.65-#ifdef __cplusplus
   12.66-} // extern "C"
   12.67-#endif // __cplusplus
   12.68-
   12.69-#endif /* demo_h */
    13.1--- a/ffi/quiche.h	Sat Jun 03 19:57:46 2023 -0400
    13.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3@@ -1,973 +0,0 @@
    13.4-// Copyright (C) 2018-2019, Cloudflare, Inc.
    13.5-// All rights reserved.
    13.6-//
    13.7-// Redistribution and use in source and binary forms, with or without
    13.8-// modification, are permitted provided that the following conditions are
    13.9-// met:
   13.10-//
   13.11-//     * Redistributions of source code must retain the above copyright
   13.12-//       notice, this list of conditions and the following disclaimer.
   13.13-//
   13.14-//     * Redistributions in binary form must reproduce the above copyright
   13.15-//       notice, this list of conditions and the following disclaimer in the
   13.16-//       documentation and/or other materials provided with the distribution.
   13.17-//
   13.18-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
   13.19-// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   13.20-// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   13.21-// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
   13.22-// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   13.23-// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   13.24-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   13.25-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   13.26-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   13.27-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   13.28-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   13.29-
   13.30-#ifndef QUICHE_H
   13.31-#define QUICHE_H
   13.32-
   13.33-#if defined(__cplusplus)
   13.34-extern "C" {
   13.35-#endif
   13.36-
   13.37-#include <stdint.h>
   13.38-#include <stdbool.h>
   13.39-#include <stddef.h>
   13.40-
   13.41-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
   13.42-#include <winsock2.h>
   13.43-#include <ws2tcpip.h>
   13.44-#include <time.h>
   13.45-#else
   13.46-#include <sys/socket.h>
   13.47-#include <sys/time.h>
   13.48-#endif
   13.49-
   13.50-#ifdef __unix__
   13.51-#include <sys/types.h>
   13.52-#endif
   13.53-#ifdef _MSC_VER
   13.54-#include <BaseTsd.h>
   13.55-#define ssize_t SSIZE_T
   13.56-#endif
   13.57-
   13.58-// QUIC transport API.
   13.59-//
   13.60-
   13.61-// The current QUIC wire version.
   13.62-#define QUICHE_PROTOCOL_VERSION 0x00000001
   13.63-
   13.64-// The maximum length of a connection ID.
   13.65-#define QUICHE_MAX_CONN_ID_LEN 20
   13.66-
   13.67-// The minimum length of Initial packets sent by a client.
   13.68-#define QUICHE_MIN_CLIENT_INITIAL_LEN 1200
   13.69-
   13.70-enum quiche_error {
   13.71-    // There is no more work to do.
   13.72-    QUICHE_ERR_DONE = -1,
   13.73-
   13.74-    // The provided buffer is too short.
   13.75-    QUICHE_ERR_BUFFER_TOO_SHORT = -2,
   13.76-
   13.77-    // The provided packet cannot be parsed because its version is unknown.
   13.78-    QUICHE_ERR_UNKNOWN_VERSION = -3,
   13.79-
   13.80-    // The provided packet cannot be parsed because it contains an invalid
   13.81-    // frame.
   13.82-    QUICHE_ERR_INVALID_FRAME = -4,
   13.83-
   13.84-    // The provided packet cannot be parsed.
   13.85-    QUICHE_ERR_INVALID_PACKET = -5,
   13.86-
   13.87-    // The operation cannot be completed because the connection is in an
   13.88-    // invalid state.
   13.89-    QUICHE_ERR_INVALID_STATE = -6,
   13.90-
   13.91-    // The operation cannot be completed because the stream is in an
   13.92-    // invalid state.
   13.93-    QUICHE_ERR_INVALID_STREAM_STATE = -7,
   13.94-
   13.95-    // The peer's transport params cannot be parsed.
   13.96-    QUICHE_ERR_INVALID_TRANSPORT_PARAM = -8,
   13.97-
   13.98-    // A cryptographic operation failed.
   13.99-    QUICHE_ERR_CRYPTO_FAIL = -9,
  13.100-
  13.101-    // The TLS handshake failed.
  13.102-    QUICHE_ERR_TLS_FAIL = -10,
  13.103-
  13.104-    // The peer violated the local flow control limits.
  13.105-    QUICHE_ERR_FLOW_CONTROL = -11,
  13.106-
  13.107-    // The peer violated the local stream limits.
  13.108-    QUICHE_ERR_STREAM_LIMIT = -12,
  13.109-
  13.110-    // The specified stream was stopped by the peer.
  13.111-    QUICHE_ERR_STREAM_STOPPED = -15,
  13.112-
  13.113-    // The specified stream was reset by the peer.
  13.114-    QUICHE_ERR_STREAM_RESET = -16,
  13.115-
  13.116-    // The received data exceeds the stream's final size.
  13.117-    QUICHE_ERR_FINAL_SIZE = -13,
  13.118-
  13.119-    // Error in congestion control.
  13.120-    QUICHE_ERR_CONGESTION_CONTROL = -14,
  13.121-
  13.122-    // Too many identifiers were provided.
  13.123-    QUICHE_ERR_ID_LIMIT = -17,
  13.124-
  13.125-    // Not enough available identifiers.
  13.126-    QUICHE_ERR_OUT_OF_IDENTIFIERS = -18,
  13.127-
  13.128-    // Error in key update.
  13.129-    QUICHE_ERR_KEY_UPDATE = -19,
  13.130-};
  13.131-
  13.132-// Returns a human readable string with the quiche version number.
  13.133-const char *quiche_version(void);
  13.134-
  13.135-// Enables logging. |cb| will be called with log messages
  13.136-int quiche_enable_debug_logging(void (*cb)(const char *line, void *argp),
  13.137-                                void *argp);
  13.138-
  13.139-// Stores configuration shared between multiple connections.
  13.140-typedef struct quiche_config quiche_config;
  13.141-
  13.142-// Creates a config object with the given version.
  13.143-quiche_config *quiche_config_new(uint32_t version);
  13.144-
  13.145-// Configures the given certificate chain.
  13.146-int quiche_config_load_cert_chain_from_pem_file(quiche_config *config,
  13.147-                                                const char *path);
  13.148-
  13.149-// Configures the given private key.
  13.150-int quiche_config_load_priv_key_from_pem_file(quiche_config *config,
  13.151-                                              const char *path);
  13.152-
  13.153-// Specifies a file where trusted CA certificates are stored for the purposes of certificate verification.
  13.154-int quiche_config_load_verify_locations_from_file(quiche_config *config,
  13.155-                                                  const char *path);
  13.156-
  13.157-// Specifies a directory where trusted CA certificates are stored for the purposes of certificate verification.
  13.158-int quiche_config_load_verify_locations_from_directory(quiche_config *config,
  13.159-                                                       const char *path);
  13.160-
  13.161-// Configures whether to verify the peer's certificate.
  13.162-void quiche_config_verify_peer(quiche_config *config, bool v);
  13.163-
  13.164-// Configures whether to send GREASE.
  13.165-void quiche_config_grease(quiche_config *config, bool v);
  13.166-
  13.167-// Enables logging of secrets.
  13.168-void quiche_config_log_keys(quiche_config *config);
  13.169-
  13.170-// Enables sending or receiving early data.
  13.171-void quiche_config_enable_early_data(quiche_config *config);
  13.172-
  13.173-// Configures the list of supported application protocols.
  13.174-int quiche_config_set_application_protos(quiche_config *config,
  13.175-                                         const uint8_t *protos,
  13.176-                                         size_t protos_len);
  13.177-
  13.178-// Sets the `max_idle_timeout` transport parameter, in milliseconds, default is
  13.179-// no timeout.
  13.180-void quiche_config_set_max_idle_timeout(quiche_config *config, uint64_t v);
  13.181-
  13.182-// Sets the `max_udp_payload_size transport` parameter.
  13.183-void quiche_config_set_max_recv_udp_payload_size(quiche_config *config, size_t v);
  13.184-
  13.185-// Sets the maximum outgoing UDP payload size.
  13.186-void quiche_config_set_max_send_udp_payload_size(quiche_config *config, size_t v);
  13.187-
  13.188-// Sets the `initial_max_data` transport parameter.
  13.189-void quiche_config_set_initial_max_data(quiche_config *config, uint64_t v);
  13.190-
  13.191-// Sets the `initial_max_stream_data_bidi_local` transport parameter.
  13.192-void quiche_config_set_initial_max_stream_data_bidi_local(quiche_config *config, uint64_t v);
  13.193-
  13.194-// Sets the `initial_max_stream_data_bidi_remote` transport parameter.
  13.195-void quiche_config_set_initial_max_stream_data_bidi_remote(quiche_config *config, uint64_t v);
  13.196-
  13.197-// Sets the `initial_max_stream_data_uni` transport parameter.
  13.198-void quiche_config_set_initial_max_stream_data_uni(quiche_config *config, uint64_t v);
  13.199-
  13.200-// Sets the `initial_max_streams_bidi` transport parameter.
  13.201-void quiche_config_set_initial_max_streams_bidi(quiche_config *config, uint64_t v);
  13.202-
  13.203-// Sets the `initial_max_streams_uni` transport parameter.
  13.204-void quiche_config_set_initial_max_streams_uni(quiche_config *config, uint64_t v);
  13.205-
  13.206-// Sets the `ack_delay_exponent` transport parameter.
  13.207-void quiche_config_set_ack_delay_exponent(quiche_config *config, uint64_t v);
  13.208-
  13.209-// Sets the `max_ack_delay` transport parameter.
  13.210-void quiche_config_set_max_ack_delay(quiche_config *config, uint64_t v);
  13.211-
  13.212-// Sets the `disable_active_migration` transport parameter.
  13.213-void quiche_config_set_disable_active_migration(quiche_config *config, bool v);
  13.214-
  13.215-enum quiche_cc_algorithm {
  13.216-    QUICHE_CC_RENO = 0,
  13.217-    QUICHE_CC_CUBIC = 1,
  13.218-    QUICHE_CC_BBR = 2,
  13.219-};
  13.220-
  13.221-// Sets the congestion control algorithm used.
  13.222-void quiche_config_set_cc_algorithm(quiche_config *config, enum quiche_cc_algorithm algo);
  13.223-
  13.224-// Configures whether to use HyStart++.
  13.225-void quiche_config_enable_hystart(quiche_config *config, bool v);
  13.226-
  13.227-// Configures whether to enable pacing (enabled by default).
  13.228-void quiche_config_enable_pacing(quiche_config *config, bool v);
  13.229-
  13.230-// Configures max pacing rate to be used.
  13.231-void quiche_config_set_max_pacing_rate(quiche_config *config, uint64_t v);
  13.232-
  13.233-// Configures whether to enable receiving DATAGRAM frames.
  13.234-void quiche_config_enable_dgram(quiche_config *config, bool enabled,
  13.235-                                size_t recv_queue_len,
  13.236-                                size_t send_queue_len);
  13.237-
  13.238-// Sets the maximum connection window.
  13.239-void quiche_config_set_max_connection_window(quiche_config *config, uint64_t v);
  13.240-
  13.241-// Sets the maximum stream window.
  13.242-void quiche_config_set_max_stream_window(quiche_config *config, uint64_t v);
  13.243-
  13.244-// Sets the limit of active connection IDs.
  13.245-void quiche_config_set_active_connection_id_limit(quiche_config *config, uint64_t v);
  13.246-
  13.247-// Sets the initial stateless reset token. |v| must contain 16 bytes, otherwise the behaviour is undefined.
  13.248-void quiche_config_set_stateless_reset_token(quiche_config *config, const uint8_t *v);
  13.249-
  13.250-// Frees the config object.
  13.251-void quiche_config_free(quiche_config *config);
  13.252-
  13.253-// Extracts version, type, source / destination connection ID and address
  13.254-// verification token from the packet in |buf|.
  13.255-int quiche_header_info(const uint8_t *buf, size_t buf_len, size_t dcil,
  13.256-                       uint32_t *version, uint8_t *type,
  13.257-                       uint8_t *scid, size_t *scid_len,
  13.258-                       uint8_t *dcid, size_t *dcid_len,
  13.259-                       uint8_t *token, size_t *token_len);
  13.260-
  13.261-// A QUIC connection.
  13.262-typedef struct quiche_conn quiche_conn;
  13.263-
  13.264-// Creates a new server-side connection.
  13.265-quiche_conn *quiche_accept(const uint8_t *scid, size_t scid_len,
  13.266-                           const uint8_t *odcid, size_t odcid_len,
  13.267-                           const struct sockaddr *local, size_t local_len,
  13.268-                           const struct sockaddr *peer, size_t peer_len,
  13.269-                           quiche_config *config);
  13.270-
  13.271-// Creates a new client-side connection.
  13.272-quiche_conn *quiche_connect(const char *server_name,
  13.273-                            const uint8_t *scid, size_t scid_len,
  13.274-                            const struct sockaddr *local, size_t local_len,
  13.275-                            const struct sockaddr *peer, size_t peer_len,
  13.276-                            quiche_config *config);
  13.277-
  13.278-// Writes a version negotiation packet.
  13.279-ssize_t quiche_negotiate_version(const uint8_t *scid, size_t scid_len,
  13.280-                                 const uint8_t *dcid, size_t dcid_len,
  13.281-                                 uint8_t *out, size_t out_len);
  13.282-
  13.283-// Writes a retry packet.
  13.284-ssize_t quiche_retry(const uint8_t *scid, size_t scid_len,
  13.285-                     const uint8_t *dcid, size_t dcid_len,
  13.286-                     const uint8_t *new_scid, size_t new_scid_len,
  13.287-                     const uint8_t *token, size_t token_len,
  13.288-                     uint32_t version, uint8_t *out, size_t out_len);
  13.289-
  13.290-// Returns true if the given protocol version is supported.
  13.291-bool quiche_version_is_supported(uint32_t version);
  13.292-
  13.293-quiche_conn *quiche_conn_new_with_tls(const uint8_t *scid, size_t scid_len,
  13.294-                                      const uint8_t *odcid, size_t odcid_len,
  13.295-                                      const struct sockaddr *local, size_t local_len,
  13.296-                                      const struct sockaddr *peer, size_t peer_len,
  13.297-                                      quiche_config *config, void *ssl,
  13.298-                                      bool is_server);
  13.299-
  13.300-// Enables keylog to the specified file path. Returns true on success.
  13.301-bool quiche_conn_set_keylog_path(quiche_conn *conn, const char *path);
  13.302-
  13.303-// Enables keylog to the specified file descriptor. Unix only.
  13.304-void quiche_conn_set_keylog_fd(quiche_conn *conn, int fd);
  13.305-
  13.306-// Enables qlog to the specified file path. Returns true on success.
  13.307-bool quiche_conn_set_qlog_path(quiche_conn *conn, const char *path,
  13.308-                          const char *log_title, const char *log_desc);
  13.309-
  13.310-// Enables qlog to the specified file descriptor. Unix only.
  13.311-void quiche_conn_set_qlog_fd(quiche_conn *conn, int fd, const char *log_title,
  13.312-                             const char *log_desc);
  13.313-
  13.314-// Configures the given session for resumption.
  13.315-int quiche_conn_set_session(quiche_conn *conn, const uint8_t *buf, size_t buf_len);
  13.316-
  13.317-typedef struct {
  13.318-    // The remote address the packet was received from.
  13.319-    struct sockaddr *from;
  13.320-    socklen_t from_len;
  13.321-
  13.322-    // The local address the packet was received on.
  13.323-    struct sockaddr *to;
  13.324-    socklen_t to_len;
  13.325-} quiche_recv_info;
  13.326-
  13.327-// Processes QUIC packets received from the peer.
  13.328-ssize_t quiche_conn_recv(quiche_conn *conn, uint8_t *buf, size_t buf_len,
  13.329-                         const quiche_recv_info *info);
  13.330-
  13.331-typedef struct {
  13.332-    // The local address the packet should be sent from.
  13.333-    struct sockaddr_storage from;
  13.334-    socklen_t from_len;
  13.335-
  13.336-    // The remote address the packet should be sent to.
  13.337-    struct sockaddr_storage to;
  13.338-    socklen_t to_len;
  13.339-
  13.340-    // The time to send the packet out.
  13.341-    struct timespec at;
  13.342-} quiche_send_info;
  13.343-
  13.344-// Writes a single QUIC packet to be sent to the peer.
  13.345-ssize_t quiche_conn_send(quiche_conn *conn, uint8_t *out, size_t out_len,
  13.346-                         quiche_send_info *out_info);
  13.347-
  13.348-// Returns the size of the send quantum, in bytes.
  13.349-size_t quiche_conn_send_quantum(const quiche_conn *conn);
  13.350-
  13.351-// Reads contiguous data from a stream.
  13.352-ssize_t quiche_conn_stream_recv(quiche_conn *conn, uint64_t stream_id,
  13.353-                                uint8_t *out, size_t buf_len, bool *fin);
  13.354-
  13.355-// Writes data to a stream.
  13.356-ssize_t quiche_conn_stream_send(quiche_conn *conn, uint64_t stream_id,
  13.357-                                const uint8_t *buf, size_t buf_len, bool fin);
  13.358-
  13.359-// The side of the stream to be shut down.
  13.360-enum quiche_shutdown {
  13.361-    QUICHE_SHUTDOWN_READ = 0,
  13.362-    QUICHE_SHUTDOWN_WRITE = 1,
  13.363-};
  13.364-
  13.365-// Sets the priority for a stream.
  13.366-int quiche_conn_stream_priority(quiche_conn *conn, uint64_t stream_id,
  13.367-                                uint8_t urgency, bool incremental);
  13.368-
  13.369-// Shuts down reading or writing from/to the specified stream.
  13.370-int quiche_conn_stream_shutdown(quiche_conn *conn, uint64_t stream_id,
  13.371-                                enum quiche_shutdown direction, uint64_t err);
  13.372-
  13.373-// Returns the stream's send capacity in bytes.
  13.374-ssize_t quiche_conn_stream_capacity(const quiche_conn *conn, uint64_t stream_id);
  13.375-
  13.376-// Returns true if the stream has data that can be read.
  13.377-bool quiche_conn_stream_readable(const quiche_conn *conn, uint64_t stream_id);
  13.378-
  13.379-// Returns the next stream that has data to read, or -1 if no such stream is
  13.380-// available.
  13.381-int64_t quiche_conn_stream_readable_next(quiche_conn *conn);
  13.382-
  13.383-// Returns true if the stream has enough send capacity.
  13.384-//
  13.385-// On error a value lower than 0 is returned.
  13.386-int quiche_conn_stream_writable(quiche_conn *conn, uint64_t stream_id, size_t len);
  13.387-
  13.388-// Returns the next stream that can be written to, or -1 if no such stream is
  13.389-// available.
  13.390-int64_t quiche_conn_stream_writable_next(quiche_conn *conn);
  13.391-
  13.392-// Returns true if all the data has been read from the specified stream.
  13.393-bool quiche_conn_stream_finished(const quiche_conn *conn, uint64_t stream_id);
  13.394-
  13.395-typedef struct quiche_stream_iter quiche_stream_iter;
  13.396-
  13.397-// Returns an iterator over streams that have outstanding data to read.
  13.398-quiche_stream_iter *quiche_conn_readable(const quiche_conn *conn);
  13.399-
  13.400-// Returns an iterator over streams that can be written to.
  13.401-quiche_stream_iter *quiche_conn_writable(const quiche_conn *conn);
  13.402-
  13.403-// Returns the maximum possible size of egress UDP payloads.
  13.404-size_t quiche_conn_max_send_udp_payload_size(const quiche_conn *conn);
  13.405-
  13.406-// Returns the amount of time until the next timeout event, in nanoseconds.
  13.407-uint64_t quiche_conn_timeout_as_nanos(const quiche_conn *conn);
  13.408-
  13.409-// Returns the amount of time until the next timeout event, in milliseconds.
  13.410-uint64_t quiche_conn_timeout_as_millis(const quiche_conn *conn);
  13.411-
  13.412-// Processes a timeout event.
  13.413-void quiche_conn_on_timeout(quiche_conn *conn);
  13.414-
  13.415-// Closes the connection with the given error and reason.
  13.416-int quiche_conn_close(quiche_conn *conn, bool app, uint64_t err,
  13.417-                      const uint8_t *reason, size_t reason_len);
  13.418-
  13.419-// Returns a string uniquely representing the connection.
  13.420-void quiche_conn_trace_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
  13.421-
  13.422-// Returns the source connection ID.
  13.423-void quiche_conn_source_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
  13.424-
  13.425-// Returns the destination connection ID.
  13.426-void quiche_conn_destination_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
  13.427-
  13.428-// Returns the negotiated ALPN protocol.
  13.429-void quiche_conn_application_proto(const quiche_conn *conn, const uint8_t **out,
  13.430-                                   size_t *out_len);
  13.431-
  13.432-// Returns the peer's leaf certificate (if any) as a DER-encoded buffer.
  13.433-void quiche_conn_peer_cert(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
  13.434-
  13.435-// Returns the serialized cryptographic session for the connection.
  13.436-void quiche_conn_session(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
  13.437-
  13.438-// Returns true if the connection handshake is complete.
  13.439-bool quiche_conn_is_established(const quiche_conn *conn);
  13.440-
  13.441-// Returns true if the connection has a pending handshake that has progressed
  13.442-// enough to send or receive early data.
  13.443-bool quiche_conn_is_in_early_data(const quiche_conn *conn);
  13.444-
  13.445-// Returns whether there is stream or DATAGRAM data available to read.
  13.446-bool quiche_conn_is_readable(const quiche_conn *conn);
  13.447-
  13.448-// Returns true if the connection is draining.
  13.449-bool quiche_conn_is_draining(const quiche_conn *conn);
  13.450-
  13.451-// Returns the number of bidirectional streams that can be created
  13.452-// before the peer's stream count limit is reached.
  13.453-uint64_t quiche_conn_peer_streams_left_bidi(const quiche_conn *conn);
  13.454-
  13.455-// Returns the number of unidirectional streams that can be created
  13.456-// before the peer's stream count limit is reached.
  13.457-uint64_t quiche_conn_peer_streams_left_uni(const quiche_conn *conn);
  13.458-
  13.459-// Returns true if the connection is closed.
  13.460-bool quiche_conn_is_closed(const quiche_conn *conn);
  13.461-
  13.462-// Returns true if the connection was closed due to the idle timeout.
  13.463-bool quiche_conn_is_timed_out(const quiche_conn *conn);
  13.464-
  13.465-// Returns true if a connection error was received, and updates the provided
  13.466-// parameters accordingly.
  13.467-bool quiche_conn_peer_error(const quiche_conn *conn,
  13.468-                            bool *is_app,
  13.469-                            uint64_t *error_code,
  13.470-                            const uint8_t **reason,
  13.471-                            size_t *reason_len);
  13.472-
  13.473-// Returns true if a connection error was queued or sent, and updates the provided
  13.474-// parameters accordingly.
  13.475-bool quiche_conn_local_error(const quiche_conn *conn,
  13.476-                             bool *is_app,
  13.477-                             uint64_t *error_code,
  13.478-                             const uint8_t **reason,
  13.479-                             size_t *reason_len);
  13.480-
  13.481-// Initializes the stream's application data.
  13.482-//
  13.483-// Stream data can only be initialized once. Additional calls to this method
  13.484-// will fail.
  13.485-//
  13.486-// Note that the application is responsible for freeing the data.
  13.487-int quiche_conn_stream_init_application_data(quiche_conn *conn,
  13.488-                                             uint64_t stream_id,
  13.489-                                             void *data);
  13.490-
  13.491-// Returns the stream's application data, if any was initialized.
  13.492-void *quiche_conn_stream_application_data(quiche_conn *conn, uint64_t stream_id);
  13.493-
  13.494-// Fetches the next stream from the given iterator. Returns false if there are
  13.495-// no more elements in the iterator.
  13.496-bool quiche_stream_iter_next(quiche_stream_iter *iter, uint64_t *stream_id);
  13.497-
  13.498-// Frees the given stream iterator object.
  13.499-void quiche_stream_iter_free(quiche_stream_iter *iter);
  13.500-
  13.501-typedef struct {
  13.502-    // The number of QUIC packets received on this connection.
  13.503-    size_t recv;
  13.504-
  13.505-    // The number of QUIC packets sent on this connection.
  13.506-    size_t sent;
  13.507-
  13.508-    // The number of QUIC packets that were lost.
  13.509-    size_t lost;
  13.510-
  13.511-    // The number of sent QUIC packets with retransmitted data.
  13.512-    size_t retrans;
  13.513-
  13.514-    // The number of sent bytes.
  13.515-    uint64_t sent_bytes;
  13.516-
  13.517-    // The number of received bytes.
  13.518-    uint64_t recv_bytes;
  13.519-
  13.520-    // The number of bytes lost.
  13.521-    uint64_t lost_bytes;
  13.522-
  13.523-    // The number of stream bytes retransmitted.
  13.524-    uint64_t stream_retrans_bytes;
  13.525-
  13.526-    // The number of known paths for the connection.
  13.527-    size_t paths_count;
  13.528-
  13.529-    // The maximum idle timeout.
  13.530-    uint64_t peer_max_idle_timeout;
  13.531-
  13.532-    // The maximum UDP payload size.
  13.533-    uint64_t peer_max_udp_payload_size;
  13.534-
  13.535-    // The initial flow control maximum data for the connection.
  13.536-    uint64_t peer_initial_max_data;
  13.537-
  13.538-    // The initial flow control maximum data for local bidirectional streams.
  13.539-    uint64_t peer_initial_max_stream_data_bidi_local;
  13.540-
  13.541-    // The initial flow control maximum data for remote bidirectional streams.
  13.542-    uint64_t peer_initial_max_stream_data_bidi_remote;
  13.543-
  13.544-    // The initial flow control maximum data for unidirectional streams.
  13.545-    uint64_t peer_initial_max_stream_data_uni;
  13.546-
  13.547-    // The initial maximum bidirectional streams.
  13.548-    uint64_t peer_initial_max_streams_bidi;
  13.549-
  13.550-    // The initial maximum unidirectional streams.
  13.551-    uint64_t peer_initial_max_streams_uni;
  13.552-
  13.553-    // The ACK delay exponent.
  13.554-    uint64_t peer_ack_delay_exponent;
  13.555-
  13.556-    // The max ACK delay.
  13.557-    uint64_t peer_max_ack_delay;
  13.558-
  13.559-    // Whether active migration is disabled.
  13.560-    bool peer_disable_active_migration;
  13.561-
  13.562-    // The active connection ID limit.
  13.563-    uint64_t peer_active_conn_id_limit;
  13.564-
  13.565-    // DATAGRAM frame extension parameter, if any.
  13.566-    ssize_t peer_max_datagram_frame_size;
  13.567-} quiche_stats;
  13.568-
  13.569-// Collects and returns statistics about the connection.
  13.570-void quiche_conn_stats(const quiche_conn *conn, quiche_stats *out);
  13.571-
  13.572-typedef struct {
  13.573-    // The local address used by this path.
  13.574-    struct sockaddr_storage local_addr;
  13.575-    socklen_t local_addr_len;
  13.576-
  13.577-    // The peer address seen by this path.
  13.578-    struct sockaddr_storage peer_addr;
  13.579-    socklen_t peer_addr_len;
  13.580-
  13.581-    // The validation state of the path.
  13.582-    ssize_t validation_state;
  13.583-
  13.584-    // Whether this path is active.
  13.585-    bool active;
  13.586-
  13.587-    // The number of QUIC packets received on this path.
  13.588-    size_t recv;
  13.589-
  13.590-    // The number of QUIC packets sent on this path.
  13.591-    size_t sent;
  13.592-
  13.593-    // The number of QUIC packets that were lost on this path.
  13.594-    size_t lost;
  13.595-
  13.596-    // The number of sent QUIC packets with retransmitted data on this path.
  13.597-    size_t retrans;
  13.598-
  13.599-    // The estimated round-trip time of the path (in nanoseconds).
  13.600-    uint64_t rtt;
  13.601-
  13.602-    // The size of the path's congestion window in bytes.
  13.603-    size_t cwnd;
  13.604-
  13.605-    // The number of sent bytes on this path.
  13.606-    uint64_t sent_bytes;
  13.607-
  13.608-    // The number of received bytes on this path.
  13.609-    uint64_t recv_bytes;
  13.610-
  13.611-    // The number of bytes lost on this path.
  13.612-    uint64_t lost_bytes;
  13.613-
  13.614-    // The number of stream bytes retransmitted on this path.
  13.615-    uint64_t stream_retrans_bytes;
  13.616-
  13.617-    // The current PMTU for the path.
  13.618-    size_t pmtu;
  13.619-
  13.620-    // The most recent data delivery rate estimate in bytes/s.
  13.621-    uint64_t delivery_rate;
  13.622-} quiche_path_stats;
  13.623-
  13.624-
  13.625-// Collects and returns statistics about the specified path for the connection.
  13.626-//
  13.627-// The `idx` argument represent the path's index (also see the `paths_count`
  13.628-// field of `quiche_stats`).
  13.629-int quiche_conn_path_stats(const quiche_conn *conn, size_t idx, quiche_path_stats *out);
  13.630-
  13.631-// Returns whether or not this is a server-side connection.
  13.632-bool quiche_conn_is_server(const quiche_conn *conn);
  13.633-
  13.634-// Returns the maximum DATAGRAM payload that can be sent.
  13.635-ssize_t quiche_conn_dgram_max_writable_len(const quiche_conn *conn);
  13.636-
  13.637-// Returns the length of the first stored DATAGRAM.
  13.638-ssize_t quiche_conn_dgram_recv_front_len(const quiche_conn *conn);
  13.639-
  13.640-// Returns the number of items in the DATAGRAM receive queue.
  13.641-ssize_t quiche_conn_dgram_recv_queue_len(const quiche_conn *conn);
  13.642-
  13.643-// Returns the total size of all items in the DATAGRAM receive queue.
  13.644-ssize_t quiche_conn_dgram_recv_queue_byte_size(const quiche_conn *conn);
  13.645-
  13.646-// Returns the number of items in the DATAGRAM send queue.
  13.647-ssize_t quiche_conn_dgram_send_queue_len(const quiche_conn *conn);
  13.648-
  13.649-// Returns the total size of all items in the DATAGRAM send queue.
  13.650-ssize_t quiche_conn_dgram_send_queue_byte_size(const quiche_conn *conn);
  13.651-
  13.652-// Reads the first received DATAGRAM.
  13.653-ssize_t quiche_conn_dgram_recv(quiche_conn *conn, uint8_t *buf,
  13.654-                               size_t buf_len);
  13.655-
  13.656-// Sends data in a DATAGRAM frame.
  13.657-ssize_t quiche_conn_dgram_send(quiche_conn *conn, const uint8_t *buf,
  13.658-                               size_t buf_len);
  13.659-
  13.660-// Purges queued outgoing DATAGRAMs matching the predicate.
  13.661-void quiche_conn_dgram_purge_outgoing(quiche_conn *conn,
  13.662-                                      bool (*f)(uint8_t *, size_t));
  13.663-
  13.664-// Schedule an ack-eliciting packet on the active path.
  13.665-ssize_t quiche_conn_send_ack_eliciting(quiche_conn *conn);
  13.666-
  13.667-// Schedule an ack-eliciting packet on the specified path.
  13.668-ssize_t quiche_conn_send_ack_eliciting_on_path(quiche_conn *conn,
  13.669-                           const struct sockaddr *local, size_t local_len,
  13.670-                           const struct sockaddr *peer, size_t peer_len);
  13.671-
  13.672-// Frees the connection object.
  13.673-void quiche_conn_free(quiche_conn *conn);
  13.674-
  13.675-
  13.676-// HTTP/3 API
  13.677-//
  13.678-
  13.679-// List of ALPN tokens of supported HTTP/3 versions.
  13.680-#define QUICHE_H3_APPLICATION_PROTOCOL "\x02h3\x05h3-29\x05h3-28\x05h3-27"
  13.681-
  13.682-enum quiche_h3_error {
  13.683-    // There is no error or no work to do
  13.684-    QUICHE_H3_ERR_DONE = -1,
  13.685-
  13.686-    // The provided buffer is too short.
  13.687-    QUICHE_H3_ERR_BUFFER_TOO_SHORT = -2,
  13.688-
  13.689-    // Internal error in the HTTP/3 stack.
  13.690-    QUICHE_H3_ERR_INTERNAL_ERROR = -3,
  13.691-
  13.692-    // Endpoint detected that the peer is exhibiting behavior that causes.
  13.693-    // excessive load.
  13.694-    QUICHE_H3_ERR_EXCESSIVE_LOAD = -4,
  13.695-
  13.696-    // Stream ID or Push ID greater that current maximum was
  13.697-    // used incorrectly, such as exceeding a limit, reducing a limit,
  13.698-    // or being reused.
  13.699-    QUICHE_H3_ERR_ID_ERROR= -5,
  13.700-
  13.701-    // The endpoint detected that its peer created a stream that it will not
  13.702-    // accept.
  13.703-    QUICHE_H3_ERR_STREAM_CREATION_ERROR = -6,
  13.704-
  13.705-    // A required critical stream was closed.
  13.706-    QUICHE_H3_ERR_CLOSED_CRITICAL_STREAM = -7,
  13.707-
  13.708-    // No SETTINGS frame at beginning of control stream.
  13.709-    QUICHE_H3_ERR_MISSING_SETTINGS = -8,
  13.710-
  13.711-    // A frame was received which is not permitted in the current state.
  13.712-    QUICHE_H3_ERR_FRAME_UNEXPECTED = -9,
  13.713-
  13.714-    // Frame violated layout or size rules.
  13.715-    QUICHE_H3_ERR_FRAME_ERROR = -10,
  13.716-
  13.717-    // QPACK Header block decompression failure.
  13.718-    QUICHE_H3_ERR_QPACK_DECOMPRESSION_FAILED = -11,
  13.719-
  13.720-    // -12 was previously used for TransportError, skip it
  13.721-
  13.722-    // The underlying QUIC stream (or connection) doesn't have enough capacity
  13.723-    // for the operation to complete. The application should retry later on.
  13.724-    QUICHE_H3_ERR_STREAM_BLOCKED = -13,
  13.725-
  13.726-    // Error in the payload of a SETTINGS frame.
  13.727-    QUICHE_H3_ERR_SETTINGS_ERROR = -14,
  13.728-
  13.729-    // Server rejected request.
  13.730-    QUICHE_H3_ERR_REQUEST_REJECTED = -15,
  13.731-
  13.732-    // Request or its response cancelled.
  13.733-    QUICHE_H3_ERR_REQUEST_CANCELLED = -16,
  13.734-
  13.735-    // Client's request stream terminated without containing a full-formed
  13.736-    // request.
  13.737-    QUICHE_H3_ERR_REQUEST_INCOMPLETE = -17,
  13.738-
  13.739-    // An HTTP message was malformed and cannot be processed.
  13.740-    QUICHE_H3_ERR_MESSAGE_ERROR = -18,
  13.741-
  13.742-    // The TCP connection established in response to a CONNECT request was
  13.743-    // reset or abnormally closed.
  13.744-    QUICHE_H3_ERR_CONNECT_ERROR = -19,
  13.745-
  13.746-    // The requested operation cannot be served over HTTP/3. Peer should retry
  13.747-    // over HTTP/1.1.
  13.748-    QUICHE_H3_ERR_VERSION_FALLBACK = -20,
  13.749-
  13.750-    // The following QUICHE_H3_TRANSPORT_ERR_* errors are propagated
  13.751-    // from the QUIC transport layer.
  13.752-
  13.753-    // See QUICHE_ERR_DONE.
  13.754-    QUICHE_H3_TRANSPORT_ERR_DONE = QUICHE_ERR_DONE - 1000,
  13.755-
  13.756-    // See QUICHE_ERR_BUFFER_TOO_SHORT.
  13.757-    QUICHE_H3_TRANSPORT_ERR_BUFFER_TOO_SHORT = QUICHE_ERR_BUFFER_TOO_SHORT - 1000,
  13.758-
  13.759-    // See QUICHE_ERR_UNKNOWN_VERSION.
  13.760-    QUICHE_H3_TRANSPORT_ERR_UNKNOWN_VERSION = QUICHE_ERR_UNKNOWN_VERSION - 1000,
  13.761-
  13.762-    // See QUICHE_ERR_INVALID_FRAME.
  13.763-    QUICHE_H3_TRANSPORT_ERR_INVALID_FRAME = QUICHE_ERR_INVALID_FRAME - 1000,
  13.764-
  13.765-    // See QUICHE_ERR_INVALID_PACKET.
  13.766-    QUICHE_H3_TRANSPORT_ERR_INVALID_PACKET = QUICHE_ERR_INVALID_PACKET - 1000,
  13.767-
  13.768-    // See QUICHE_ERR_INVALID_STATE.
  13.769-    QUICHE_H3_TRANSPORT_ERR_INVALID_STATE = QUICHE_ERR_INVALID_STATE - 1000,
  13.770-
  13.771-    // See QUICHE_ERR_INVALID_STREAM_STATE.
  13.772-    QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE = QUICHE_ERR_INVALID_STREAM_STATE - 1000,
  13.773-
  13.774-    // See QUICHE_ERR_INVALID_TRANSPORT_PARAM.
  13.775-    QUICHE_H3_TRANSPORT_ERR_INVALID_TRANSPORT_PARAM = QUICHE_ERR_INVALID_TRANSPORT_PARAM - 1000,
  13.776-
  13.777-    // See QUICHE_ERR_CRYPTO_FAIL.
  13.778-    QUICHE_H3_TRANSPORT_ERR_CRYPTO_FAIL = QUICHE_ERR_CRYPTO_FAIL - 1000,
  13.779-
  13.780-    // See QUICHE_ERR_TLS_FAIL.
  13.781-    QUICHE_H3_TRANSPORT_ERR_TLS_FAIL = QUICHE_ERR_TLS_FAIL - 1000,
  13.782-
  13.783-    // See QUICHE_ERR_FLOW_CONTROL.
  13.784-    QUICHE_H3_TRANSPORT_ERR_FLOW_CONTROL = QUICHE_ERR_FLOW_CONTROL - 1000,
  13.785-
  13.786-    // See QUICHE_ERR_STREAM_LIMIT.
  13.787-    QUICHE_H3_TRANSPORT_ERR_STREAM_LIMIT = QUICHE_ERR_STREAM_LIMIT - 1000,
  13.788-
  13.789-    // See QUICHE_ERR_STREAM_STOPPED.
  13.790-    QUICHE_H3_TRANSPORT_ERR_STREAM_STOPPED = QUICHE_ERR_STREAM_STOPPED - 1000,
  13.791-
  13.792-    // See QUICHE_ERR_STREAM_RESET.
  13.793-    QUICHE_H3_TRANSPORT_ERR_STREAM_RESET = QUICHE_ERR_STREAM_RESET - 1000,
  13.794-
  13.795-    // See QUICHE_ERR_FINAL_SIZE.
  13.796-    QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE = QUICHE_ERR_FINAL_SIZE - 1000,
  13.797-
  13.798-    // See QUICHE_ERR_CONGESTION_CONTROL.
  13.799-    QUICHE_H3_TRANSPORT_ERR_CONGESTION_CONTROL = QUICHE_ERR_CONGESTION_CONTROL - 1000,
  13.800-
  13.801-    // See QUICHE_ERR_ID_LIMIT.
  13.802-    QUICHE_H3_TRANSPORT_ERR_ID_LIMIT = QUICHE_ERR_ID_LIMIT - 1000,
  13.803-
  13.804-    // See QUICHE_ERR_OUT_OF_IDENTIFIERS.
  13.805-    QUICHE_H3_TRANSPORT_ERR_OUT_OF_IDENTIFIERS = QUICHE_ERR_OUT_OF_IDENTIFIERS - 1000,
  13.806-
  13.807-    // See QUICHE_ERR_KEY_UPDATE.
  13.808-    QUICHE_H3_TRANSPORT_ERR_KEY_UPDATE = QUICHE_ERR_KEY_UPDATE - 1000,
  13.809-};
  13.810-
  13.811-// Stores configuration shared between multiple connections.
  13.812-typedef struct quiche_h3_config quiche_h3_config;
  13.813-
  13.814-// Creates an HTTP/3 config object with default settings values.
  13.815-quiche_h3_config *quiche_h3_config_new(void);
  13.816-
  13.817-// Sets the `SETTINGS_MAX_FIELD_SECTION_SIZE` setting.
  13.818-void quiche_h3_config_set_max_field_section_size(quiche_h3_config *config, uint64_t v);
  13.819-
  13.820-// Sets the `SETTINGS_QPACK_MAX_TABLE_CAPACITY` setting.
  13.821-void quiche_h3_config_set_qpack_max_table_capacity(quiche_h3_config *config, uint64_t v);
  13.822-
  13.823-// Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting.
  13.824-void quiche_h3_config_set_qpack_blocked_streams(quiche_h3_config *config, uint64_t v);
  13.825-
  13.826-// Sets the `SETTINGS_ENABLE_CONNECT_PROTOCOL` setting.
  13.827-void quiche_h3_config_enable_extended_connect(quiche_h3_config *config, bool enabled);
  13.828-
  13.829-// Frees the HTTP/3 config object.
  13.830-void quiche_h3_config_free(quiche_h3_config *config);
  13.831-
  13.832-// An HTTP/3 connection.
  13.833-typedef struct quiche_h3_conn quiche_h3_conn;
  13.834-
  13.835-// Creates a new server-side connection.
  13.836-quiche_h3_conn *quiche_h3_accept(quiche_conn *quiche_conn,
  13.837-                                 quiche_h3_config *config);
  13.838-
  13.839-// Creates a new HTTP/3 connection using the provided QUIC connection.
  13.840-quiche_h3_conn *quiche_h3_conn_new_with_transport(quiche_conn *quiche_conn,
  13.841-                                                  quiche_h3_config *config);
  13.842-
  13.843-enum quiche_h3_event_type {
  13.844-    QUICHE_H3_EVENT_HEADERS,
  13.845-    QUICHE_H3_EVENT_DATA,
  13.846-    QUICHE_H3_EVENT_FINISHED,
  13.847-    QUICHE_H3_EVENT_DATAGRAM,
  13.848-    QUICHE_H3_EVENT_GOAWAY,
  13.849-    QUICHE_H3_EVENT_RESET,
  13.850-    QUICHE_H3_EVENT_PRIORITY_UPDATE,
  13.851-};
  13.852-
  13.853-typedef struct quiche_h3_event quiche_h3_event;
  13.854-
  13.855-// Processes HTTP/3 data received from the peer.
  13.856-int64_t quiche_h3_conn_poll(quiche_h3_conn *conn, quiche_conn *quic_conn,
  13.857-                            quiche_h3_event **ev);
  13.858-
  13.859-// Returns the type of the event.
  13.860-enum quiche_h3_event_type quiche_h3_event_type(quiche_h3_event *ev);
  13.861-
  13.862-// Iterates over the headers in the event.
  13.863-//
  13.864-// The `cb` callback will be called for each header in `ev`. `cb` should check
  13.865-// the validity of pseudo-headers and headers. If `cb` returns any value other
  13.866-// than `0`, processing will be interrupted and the value is returned to the
  13.867-// caller.
  13.868-int quiche_h3_event_for_each_header(quiche_h3_event *ev,
  13.869-                                    int (*cb)(uint8_t *name, size_t name_len,
  13.870-                                              uint8_t *value, size_t value_len,
  13.871-                                              void *argp),
  13.872-                                    void *argp);
  13.873-
  13.874-// Iterates over the peer's HTTP/3 settings.
  13.875-//
  13.876-// The `cb` callback will be called for each setting in `conn`.
  13.877-// If `cb` returns any value other than `0`, processing will be interrupted and
  13.878-// the value is returned to the caller.
  13.879-int quiche_h3_for_each_setting(quiche_h3_conn *conn,
  13.880-                               int (*cb)(uint64_t identifier,
  13.881-                                         uint64_t value, void *argp),
  13.882-                               void *argp);
  13.883-
  13.884-// Check whether data will follow the headers on the stream.
  13.885-bool quiche_h3_event_headers_has_body(quiche_h3_event *ev);
  13.886-
  13.887-// Check whether or not extended connection is enabled by the peer
  13.888-bool quiche_h3_extended_connect_enabled_by_peer(quiche_h3_conn *conn);
  13.889-
  13.890-// Frees the HTTP/3 event object.
  13.891-void quiche_h3_event_free(quiche_h3_event *ev);
  13.892-
  13.893-typedef struct {
  13.894-    const uint8_t *name;
  13.895-    size_t name_len;
  13.896-
  13.897-    const uint8_t *value;
  13.898-    size_t value_len;
  13.899-} quiche_h3_header;
  13.900-
  13.901-// Extensible Priorities parameters.
  13.902-typedef struct {
  13.903-    uint8_t urgency;
  13.904-    bool incremental;
  13.905-} quiche_h3_priority;
  13.906-
  13.907-// Sends an HTTP/3 request.
  13.908-int64_t quiche_h3_send_request(quiche_h3_conn *conn, quiche_conn *quic_conn,
  13.909-                               quiche_h3_header *headers, size_t headers_len,
  13.910-                               bool fin);
  13.911-
  13.912-// Sends an HTTP/3 response on the specified stream with default priority.
  13.913-int quiche_h3_send_response(quiche_h3_conn *conn, quiche_conn *quic_conn,
  13.914-                            uint64_t stream_id, quiche_h3_header *headers,
  13.915-                            size_t headers_len, bool fin);
  13.916-
  13.917-// Sends an HTTP/3 response on the specified stream with specified priority.
  13.918-int quiche_h3_send_response_with_priority(quiche_h3_conn *conn,
  13.919-                            quiche_conn *quic_conn, uint64_t stream_id,
  13.920-                            quiche_h3_header *headers, size_t headers_len,
  13.921-                            quiche_h3_priority *priority, bool fin);
  13.922-
  13.923-// Sends an HTTP/3 body chunk on the given stream.
  13.924-ssize_t quiche_h3_send_body(quiche_h3_conn *conn, quiche_conn *quic_conn,
  13.925-                            uint64_t stream_id, uint8_t *body, size_t body_len,
  13.926-                            bool fin);
  13.927-
  13.928-// Reads request or response body data into the provided buffer.
  13.929-ssize_t quiche_h3_recv_body(quiche_h3_conn *conn, quiche_conn *quic_conn,
  13.930-                            uint64_t stream_id, uint8_t *out, size_t out_len);
  13.931-
  13.932-// Try to parse an Extensible Priority field value.
  13.933-int quiche_h3_parse_extensible_priority(uint8_t *priority,
  13.934-                                        size_t priority_len,
  13.935-                                        quiche_h3_priority *parsed);
  13.936-
  13.937-/// Sends a PRIORITY_UPDATE frame on the control stream with specified
  13.938-/// request stream ID and priority.
  13.939-int quiche_h3_send_priority_update_for_request(quiche_h3_conn *conn,
  13.940-                                               quiche_conn *quic_conn,
  13.941-                                               uint64_t stream_id,
  13.942-                                               quiche_h3_priority *priority);
  13.943-
  13.944-// Take the last received PRIORITY_UPDATE frame for a stream.
  13.945-//
  13.946-// The `cb` callback will be called once. `cb` should check the validity of
  13.947-// priority field value contents. If `cb` returns any value other than `0`,
  13.948-// processing will be interrupted and the value is returned to the caller.
  13.949-int quiche_h3_take_last_priority_update(quiche_h3_conn *conn,
  13.950-                                        uint64_t prioritized_element_id,
  13.951-                                        int (*cb)(uint8_t  *priority_field_value,
  13.952-                                                  uint64_t priority_field_value_len,
  13.953-                                                  void *argp),
  13.954-                                        void *argp);
  13.955-
  13.956-// Returns whether the peer enabled HTTP/3 DATAGRAM frame support.
  13.957-bool quiche_h3_dgram_enabled_by_peer(quiche_h3_conn *conn,
  13.958-                                     quiche_conn *quic_conn);
  13.959-
  13.960-// Writes data to the DATAGRAM send queue.
  13.961-ssize_t quiche_h3_send_dgram(quiche_h3_conn *conn, quiche_conn *quic_conn,
  13.962-                            uint64_t flow_id, uint8_t *data, size_t data_len);
  13.963-
  13.964-// Reads data from the DATAGRAM receive queue.
  13.965-ssize_t quiche_h3_recv_dgram(quiche_h3_conn *conn, quiche_conn *quic_conn,
  13.966-                            uint64_t *flow_id, size_t *flow_id_len,
  13.967-                            uint8_t *out, size_t out_len);
  13.968-
  13.969-// Frees the HTTP/3 connection object.
  13.970-void quiche_h3_conn_free(quiche_h3_conn *conn);
  13.971-
  13.972-#if defined(__cplusplus)
  13.973-}  // extern C
  13.974-#endif
  13.975-
  13.976-#endif // QUICHE_H
    14.1--- a/gen.rs	Sat Jun 03 19:57:46 2023 -0400
    14.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3@@ -1,84 +0,0 @@
    14.4-//! demo
    14.5-pub use fig::*;
    14.6-pub use obj::*;
    14.7-use std::ffi::{CStr, CString}; //OsStr,Path
    14.8-                               //use std::os::unix::ffi::OsStrExt;
    14.9-use std::slice;
   14.10-use libc::{c_char,size_t};
   14.11-
   14.12-#[macro_export]
   14.13-macro_rules! cdefn {
   14.14-  (free $t:tt $n:tt) => {
   14.15-    #[no_mangle]
   14.16-    pub unsafe extern "C" fn $n(ptr: *mut $t) {
   14.17-      if ptr.is_null() {
   14.18-        return;
   14.19-      }
   14.20-      let _ = Box::from_raw(ptr);
   14.21-    }
   14.22-  };
   14.23-  (from_string $t:tt $n:tt) => {
   14.24-    #[no_mangle]
   14.25-    pub unsafe extern "C" fn $n(ptr: *const c_char) -> *mut $t {
   14.26-      assert!(!ptr.is_null());
   14.27-      let p = CStr::from_ptr(ptr).to_str().unwrap();
   14.28-      Box::into_raw(Box::new(p.into()))
   14.29-    }
   14.30-  };
   14.31-  (json_string $t:tt $r:tt $w:tt) => {
   14.32-    #[no_mangle]
   14.33-    pub unsafe extern "C" fn $r(ptr: *const c_char) -> *mut $t {
   14.34-      assert!(!ptr.is_null());
   14.35-      let s = CStr::from_ptr(ptr);
   14.36-      Box::into_raw(Box::new($t::from_json_str(&s.to_str().unwrap()).unwrap()))
   14.37-    }
   14.38-
   14.39-    #[no_mangle]
   14.40-    pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut c_char {
   14.41-      let p = &*ptr;
   14.42-      let x = p.to_json_string().unwrap();
   14.43-      CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   14.44-    }
   14.45-  };
   14.46-  (ron_string $t:tt $r:tt $w:tt) => {
   14.47-    #[no_mangle]
   14.48-    pub unsafe extern "C" fn $r(ptr: *const c_char) -> *mut $t {
   14.49-      assert!(!ptr.is_null());
   14.50-      let s = CStr::from_ptr(ptr);
   14.51-      Box::into_raw(Box::new($t::from_ron_str(&s.to_str().unwrap()).unwrap()))
   14.52-    }
   14.53-
   14.54-    #[no_mangle]
   14.55-    pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut c_char {
   14.56-      let p = &*ptr;
   14.57-      let x = p.to_ron_string().unwrap();
   14.58-      CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   14.59-    }
   14.60-  };
   14.61-  (bytes $t:tt $r:tt $w:tt) => {
   14.62-    #[no_mangle]
   14.63-    pub unsafe extern "C" fn $r(ptr: *const u8, len: size_t) -> *mut $t {
   14.64-      Box::into_raw(Box::new($t::decode(slice::from_raw_parts(ptr,len)).unwrap()))
   14.65-    }
   14.66-
   14.67-    #[no_mangle]
   14.68-    pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut u8 {
   14.69-      let p = &*ptr;
   14.70-      let mut x = p.encode().unwrap();
   14.71-      let r = x.as_mut_ptr();
   14.72-      std::mem::forget(x);
   14.73-      r
   14.74-    }
   14.75-  }
   14.76-}
   14.77-
   14.78-cdefn!(free Service free_service);
   14.79-cdefn!(from_string Service service_from_string);
   14.80-cdefn!(json_string Service service_from_json_string service_to_json_string);
   14.81-cdefn!(ron_string Service service_from_ron_string service_to_ron_string);
   14.82-cdefn!(bytes Service service_decode service_encode);
   14.83-cdefn!(free CustomService free_custom_service);
   14.84-cdefn!(from_string CustomService custom_service_from_string);
   14.85-cdefn!(json_string CustomService custom_service_from_json_string custom_service_to_json_string);
   14.86-cdefn!(ron_string CustomService custom_service_from_ron_string custom_service_to_ron_string);
   14.87-cdefn!(bytes CustomService custom_service_decode custom_service_encode);
    15.1--- a/install.lisp	Sat Jun 03 19:57:46 2023 -0400
    15.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3@@ -1,12 +0,0 @@
    15.4-#!/usr/local/bin/sbcl --script
    15.5-(in-package :cl-user)
    15.6-#-quicklisp
    15.7-(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname))))
    15.8-  (when (probe-file quicklisp-init)
    15.9-    (load quicklisp-init)))
   15.10-
   15.11-(asdf:load-asd "cl-demo.asd")
   15.12-(asdf:loadload "demo.asd")
   15.13-(ql:quickload :demo)
   15.14-;; (asdf:make :demo)
   15.15-(sb-ext:save-lisp-and-die "out/demo" :toplevel #'demo:main :executable t)
    16.1--- a/lib.rs	Sat Jun 03 19:57:46 2023 -0400
    16.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3@@ -1,117 +0,0 @@
    16.4-//! demo/lib.rs --- generated by DEMO:RS-MACROEXPAND
    16.5-extern crate libc;
    16.6-extern crate obj;
    16.7-use libc::{c_char, size_t};
    16.8-use obj::{CustomService, Objective, Service};
    16.9-use std::ffi::{CStr, CString};
   16.10-use std::slice;
   16.11-#[no_mangle]
   16.12-pub unsafe extern "C" fn free_service(ptr: *mut Service) {
   16.13-  if ptr.is_null() {
   16.14-    return;
   16.15-  }
   16.16-  let _ = Box::from_raw(ptr);
   16.17-}
   16.18-#[no_mangle]
   16.19-pub unsafe extern "C" fn service_from_string(ptr: *const c_char) -> *mut Service {
   16.20-  assert!(!ptr.is_null());
   16.21-  let p = CStr::from_ptr(ptr).to_str().unwrap();
   16.22-  Box::into_raw(Box::new(p.into()))
   16.23-}
   16.24-#[no_mangle]
   16.25-pub unsafe extern "C" fn service_from_json_string(ptr: *const c_char) -> *mut Service {
   16.26-  assert!(!ptr.is_null());
   16.27-  let s = CStr::from_ptr(ptr);
   16.28-  Box::into_raw(Box::new(
   16.29-    Service::from_json_str(&s.to_str().unwrap()).unwrap(),
   16.30-  ))
   16.31-}
   16.32-#[no_mangle]
   16.33-pub unsafe extern "C" fn service_to_json_string(ptr: *const Service) -> *mut c_char {
   16.34-  let p = &*ptr;
   16.35-  let x = p.to_json_string().unwrap();
   16.36-  CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   16.37-}
   16.38-#[no_mangle]
   16.39-pub unsafe extern "C" fn service_from_ron_string(ptr: *const c_char) -> *mut Service {
   16.40-  assert!(!ptr.is_null());
   16.41-  let s = CStr::from_ptr(ptr);
   16.42-  Box::into_raw(Box::new(
   16.43-    Service::from_ron_str(&s.to_str().unwrap()).unwrap(),
   16.44-  ))
   16.45-}
   16.46-#[no_mangle]
   16.47-pub unsafe extern "C" fn service_to_ron_string(ptr: *const Service) -> *mut c_char {
   16.48-  let p = &*ptr;
   16.49-  let x = p.to_ron_string().unwrap();
   16.50-  CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   16.51-}
   16.52-#[no_mangle]
   16.53-pub unsafe extern "C" fn service_decode(ptr: *const u8, len: size_t) -> *mut Service {
   16.54-  Box::into_raw(Box::new(
   16.55-    Service::decode(slice::from_raw_parts(ptr, len)).unwrap(),
   16.56-  ))
   16.57-}
   16.58-#[no_mangle]
   16.59-pub unsafe extern "C" fn service_encode(ptr: *const Service) -> *mut u8 {
   16.60-  let p = &*ptr;
   16.61-  let mut x = p.encode().unwrap();
   16.62-  let r = x.as_mut_ptr();
   16.63-  std::mem::forget(x);
   16.64-  r
   16.65-}
   16.66-#[no_mangle]
   16.67-pub unsafe extern "C" fn free_custom_service(ptr: *mut CustomService) {
   16.68-  if ptr.is_null() {
   16.69-    return;
   16.70-  }
   16.71-  let _ = Box::from_raw(ptr);
   16.72-}
   16.73-#[no_mangle]
   16.74-pub unsafe extern "C" fn custom_service_from_string(ptr: *const c_char) -> *mut CustomService {
   16.75-  assert!(!ptr.is_null());
   16.76-  let p = CStr::from_ptr(ptr).to_str().unwrap();
   16.77-  Box::into_raw(Box::new(p.into()))
   16.78-}
   16.79-#[no_mangle]
   16.80-pub unsafe extern "C" fn custom_service_from_json_string(ptr: *const c_char) -> *mut CustomService {
   16.81-  assert!(!ptr.is_null());
   16.82-  let s = CStr::from_ptr(ptr);
   16.83-  Box::into_raw(Box::new(
   16.84-    CustomService::from_json_str(&s.to_str().unwrap()).unwrap(),
   16.85-  ))
   16.86-}
   16.87-#[no_mangle]
   16.88-pub unsafe extern "C" fn custom_service_to_json_string(ptr: *const CustomService) -> *mut c_char {
   16.89-  let p = &*ptr;
   16.90-  let x = p.to_json_string().unwrap();
   16.91-  CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   16.92-}
   16.93-#[no_mangle]
   16.94-pub unsafe extern "C" fn custom_service_from_ron_string(ptr: *const c_char) -> *mut CustomService {
   16.95-  assert!(!ptr.is_null());
   16.96-  let s = CStr::from_ptr(ptr);
   16.97-  Box::into_raw(Box::new(
   16.98-    CustomService::from_ron_str(&s.to_str().unwrap()).unwrap(),
   16.99-  ))
  16.100-}
  16.101-#[no_mangle]
  16.102-pub unsafe extern "C" fn custom_service_to_ron_string(ptr: *const CustomService) -> *mut c_char {
  16.103-  let p = &*ptr;
  16.104-  let x = p.to_ron_string().unwrap();
  16.105-  CString::new(x.as_str().as_bytes()).unwrap().into_raw()
  16.106-}
  16.107-#[no_mangle]
  16.108-pub unsafe extern "C" fn custom_service_decode(ptr: *const u8, len: size_t) -> *mut CustomService {
  16.109-  Box::into_raw(Box::new(
  16.110-    CustomService::decode(slice::from_raw_parts(ptr, len)).unwrap(),
  16.111-  ))
  16.112-}
  16.113-#[no_mangle]
  16.114-pub unsafe extern "C" fn custom_service_encode(ptr: *const CustomService) -> *mut u8 {
  16.115-  let p = &*ptr;
  16.116-  let mut x = p.encode().unwrap();
  16.117-  let r = x.as_mut_ptr();
  16.118-  std::mem::forget(x);
  16.119-  r
  16.120-}
    17.1--- a/makefile	Sat Jun 03 19:57:46 2023 -0400
    17.2+++ b/makefile	Sat Jun 03 22:48:46 2023 -0400
    17.3@@ -1,23 +1,22 @@
    17.4 M?=release
    17.5 L?=sbcl
    17.6+C?=default.cfg
    17.7 L_C=$(L) --no-userinit
    17.8+L_D=$(L) --load demo.asd --eval '(ql:quickload "demo")'
    17.9 L_S=$(L) --script
   17.10-P?=python3
   17.11 ARCH?=
   17.12 A_C=ifeq ($(ARCH),x86_64) A_C=arch -$(ARCH) endif
   17.13-.PHONY:
   17.14-RS:Cargo.toml build.rs lib.rs obj
   17.15-CL:*.asd *.lisp
   17.16+.PHONY:build
   17.17+RS:Cargo.toml rustfmt.toml src/crates/*
   17.18+CL:*/*.asd */*.lisp
   17.19 deps:;
   17.20 clean:;rm -rf *.fasl;cargo clean
   17.21 fmt:$(RS);cargo fmt
   17.22-build:$(RS) $(CL);cargo build --$(M);$L --load demo.asd \
   17.23-	--eval '(ql:quickload :demo)' \
   17.24-	--eval '(asdf:make :demo)' \
   17.25+build:$(RS) $(CL);cargo build --$(M);$(L_D)
   17.26+	--eval '(asdf:make "demo")' \
   17.27 	--eval '(quit)'
   17.28-ffi:build;cp target/$(M)/libdemo.dylib ffi;cd ffi;$(P) ffi/build.py
   17.29 docs:$(RS);cargo doc
   17.30-test:$(RS) $(CL);cargo test;$L tests.lisp
   17.31+test:$(RS) $(CL);cargo test;$(L_D) --eval '(asdf:test "demo")' --eval '(quit)'
   17.32 #pack:;scripts/pack.ros
   17.33 #check:;scripts/check.ros
   17.34-ci:clean fmt build ffi docs test;
   17.35+ci:clean fmt build docs test;
    18.1--- a/obj/Cargo.toml	Sat Jun 03 19:57:46 2023 -0400
    18.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3@@ -1,27 +0,0 @@
    18.4-[package]
    18.5-name = "obj"
    18.6-version = "0.1.0"
    18.7-edition = "2021"
    18.8-[features]
    18.9-oauth = ["yup-oauth2"]
   18.10-
   18.11-[dependencies]
   18.12-ron = "0.7.0"
   18.13-bincode = "1.3.3"
   18.14-serde_json = "1.0.68"
   18.15-serde = { version = "1.0.130", features = ["derive"] }
   18.16-chrono = { version = "0.4.19", features = ["serde"] }
   18.17-mime = "0.3.16"
   18.18-regex = "1.5.4"
   18.19-rusty_ulid = "0.11.0"
   18.20-uuid = { version = "0.8", features = ["serde"] }
   18.21-yup-oauth2 = { version = "5.1.0", optional = true }
   18.22-blake3 = "1.0.0"
   18.23-hashbrown = "0.11.2"
   18.24-rand = "0.8.0"
   18.25-sha2 = "0.9.5"
   18.26-hex = "0.4.3"
   18.27-ulid = "1.0.0"
   18.28-
   18.29-[target.'cfg(target_arch = "wasm32")'.dependencies]
   18.30-uuid = { version = "0.8", features = ["wasm-bindgen"] }
    19.1--- a/obj/proc_macros/Cargo.toml	Sat Jun 03 19:57:46 2023 -0400
    19.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3@@ -1,10 +0,0 @@
    19.4-[package]
    19.5-name = "proc_macros"
    19.6-version = "0.1.0"
    19.7-edition = "2021"
    19.8-[lib]
    19.9-proc-macro = true
   19.10-[dependencies]
   19.11-quote = "1.0"
   19.12-proc-macro2 = "1.0"
   19.13-syn = "1.0"
   19.14\ No newline at end of file
    20.1--- a/obj/proc_macros/src/derive.rs	Sat Jun 03 19:57:46 2023 -0400
    20.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3@@ -1,5 +0,0 @@
    20.4-mod derive;
    20.5-use proc_macro::TokenStream;
    20.6-pub fn derive_static_type(input: TokenStream) -> TokenStream {
    20.7-    derive::derive_static_type(input)
    20.8-}
    21.1--- a/obj/proc_macros/src/lib.rs	Sat Jun 03 19:57:46 2023 -0400
    21.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3@@ -1,1 +0,0 @@
    21.4-
    22.1--- a/obj/src/auth.rs	Sat Jun 03 19:57:46 2023 -0400
    22.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3@@ -1,72 +0,0 @@
    22.4-//! Auth Configs
    22.5-use serde::{Deserialize, Serialize};
    22.6-
    22.7-#[cfg(feature = "oauth")]
    22.8-use yup_oauth2::ApplicationSecret;
    22.9-
   22.10-#[derive(Serialize, Deserialize, Debug, Default, Hash)]
   22.11-pub struct AuthConfig {
   22.12-  pub provider: String,
   22.13-  #[cfg(feature = "oauth")]
   22.14-  pub oauth: Option<Oauth2Config>,
   22.15-  pub ssh: Option<SshConfig>,
   22.16-  pub pw: Option<PasswordConfig>,
   22.17-}
   22.18-
   22.19-#[derive(Serialize, Deserialize, Default, Debug, Hash)]
   22.20-pub struct PasswordConfig(String, String);
   22.21-
   22.22-#[cfg(feature = "oauth")]
   22.23-#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone, Default)]
   22.24-pub struct Oauth2Config {
   22.25-  pub client_id: String,
   22.26-  pub client_secret: String,
   22.27-  pub redirect_uris: Vec<String>,
   22.28-  pub auth_uri: String,
   22.29-  pub token_uri: String,
   22.30-  pub project_id: Option<String>, //for apptoken
   22.31-  pub client_email: Option<String>,
   22.32-  /// The URL of the public x509 certificate, used to verify the signature on
   22.33-  /// JWTs, such as ID tokens, signed by the authentication provider.
   22.34-  pub auth_provider_x509_cert_url: Option<String>,
   22.35-  ///  The URL of the public x509 certificate, used to verify JWTs signed by the
   22.36-  /// client.
   22.37-  pub client_x509_cert_url: Option<String>,
   22.38-}
   22.39-
   22.40-#[cfg(feature = "oauth")]
   22.41-impl From<ApplicationSecret> for Oauth2Config {
   22.42-  fn from(shh: ApplicationSecret) -> Self {
   22.43-    Oauth2Config {
   22.44-      client_id: shh.client_id,
   22.45-      client_secret: shh.client_secret,
   22.46-      redirect_uris: shh.redirect_uris,
   22.47-      auth_uri: shh.auth_uri,
   22.48-      token_uri: shh.token_uri,
   22.49-      project_id: shh.project_id,
   22.50-      client_email: shh.client_email,
   22.51-      auth_provider_x509_cert_url: shh.auth_provider_x509_cert_url,
   22.52-      client_x509_cert_url: shh.client_x509_cert_url,
   22.53-    }
   22.54-  }
   22.55-}
   22.56-
   22.57-#[cfg(feature = "oauth")]
   22.58-impl From<Oauth2Config> for ApplicationSecret {
   22.59-  fn from(cfg: Oauth2Config) -> Self {
   22.60-    ApplicationSecret {
   22.61-      client_id: cfg.client_id,
   22.62-      client_secret: cfg.client_secret,
   22.63-      redirect_uris: cfg.redirect_uris,
   22.64-      auth_uri: cfg.auth_uri,
   22.65-      token_uri: cfg.token_uri,
   22.66-      project_id: cfg.project_id,
   22.67-      client_email: cfg.client_email,
   22.68-      auth_provider_x509_cert_url: cfg.auth_provider_x509_cert_url,
   22.69-      client_x509_cert_url: cfg.client_x509_cert_url,
   22.70-    }
   22.71-  }
   22.72-}
   22.73-
   22.74-#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone, Default)]
   22.75-pub struct SshConfig {}
    23.1--- a/obj/src/cfg.rs	Sat Jun 03 19:57:46 2023 -0400
    23.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3@@ -1,51 +0,0 @@
    23.4-/// common trait for all config modules. This trait provides functions
    23.5-/// for de/serializing to/from RON, updating fields, and formatting.
    23.6-use serde::{Serialize, Deserialize};
    23.7-use crate::Objective;
    23.8-use std::collections::HashMap as M;
    23.9-use std::path::PathBuf;
   23.10-use std::string::String as S;
   23.11-use std::error::Error as E;
   23.12-use std::boxed::Box as B;
   23.13-type R<X> = std::result::Result<X,B<dyn E>>;
   23.14-
   23.15-pub trait Configure: Objective {
   23.16-  fn update(&self) -> R<()> {
   23.17-    Ok(())
   23.18-  }
   23.19-}
   23.20-
   23.21-#[derive(Serialize, Deserialize, Debug, Default)]
   23.22-pub struct ShellConfig {
   23.23-  pub env: M<S,S>,
   23.24-  pub cmds: M<S,S>,
   23.25-  pub shell: ShellType,
   23.26-}
   23.27-
   23.28-impl Objective for ShellConfig {}
   23.29-
   23.30-#[derive(Serialize, Deserialize, Debug, Hash, Default)]
   23.31-pub enum ShellType {
   23.32-  #[default]
   23.33-  Bash,
   23.34-  Zsh,
   23.35-  Sh,
   23.36-}
   23.37-
   23.38-#[derive(Serialize, Deserialize, Debug, Default)]
   23.39-pub enum EditorType {
   23.40-  #[default]
   23.41-  Emacs,
   23.42-  Vi,
   23.43-  Nano,
   23.44-}
   23.45-
   23.46-#[derive(Serialize, Deserialize, Debug, Default)]
   23.47-pub struct EditorConfig {
   23.48-  pub editor: EditorType,
   23.49-  pub cmds: M<S,S>,
   23.50-  pub init_file: PathBuf,
   23.51-}
   23.52-
   23.53-#[cfg(test)]
   23.54-mod tests;
    24.1--- a/obj/src/database.rs	Sat Jun 03 19:57:46 2023 -0400
    24.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3@@ -1,18 +0,0 @@
    24.4-//! cfg::config::database
    24.5-//!
    24.6-//! Database configuration primitives
    24.7-use serde::{Deserialize, Serialize};
    24.8-
    24.9-#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq)]
   24.10-pub struct DatabaseConfig {
   24.11-  engine: DatabaseType,
   24.12-  path: String,
   24.13-  cfs: Vec<String>,
   24.14-}
   24.15-
   24.16-#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq)]
   24.17-pub enum DatabaseType {
   24.18-  RocksDB,
   24.19-  Postgres,
   24.20-  Alch,
   24.21-}
    25.1--- a/obj/src/err.rs	Sat Jun 03 19:57:46 2023 -0400
    25.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3@@ -1,81 +0,0 @@
    25.4-//! obj errors
    25.5-use std::{fmt, io};
    25.6-
    25.7-/// obj Result wrapper
    25.8-pub type Result<T> = std::result::Result<T, Error>;
    25.9-
   25.10-/// obj Error type
   25.11-#[derive(Debug)]
   25.12-pub enum Error {
   25.13-  Message(String),
   25.14-  Ron(ron::error::Error),
   25.15-  Json(serde_json::error::Error),
   25.16-  Io(io::Error),
   25.17-  Bincode(bincode::Error),
   25.18-  Utf8(std::string::FromUtf8Error),
   25.19-  Parse(std::string::ParseError),
   25.20-}
   25.21-
   25.22-impl serde::ser::Error for Error {
   25.23-  fn custom<T: fmt::Display>(msg: T) -> Self {
   25.24-    Error::Message(msg.to_string())
   25.25-  }
   25.26-}
   25.27-
   25.28-impl serde::de::Error for Error {
   25.29-  fn custom<T: fmt::Display>(msg: T) -> Self {
   25.30-    Error::Message(msg.to_string())
   25.31-  }
   25.32-}
   25.33-
   25.34-impl fmt::Display for Error {
   25.35-  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
   25.36-    match self {
   25.37-      Error::Message(msg) => f.write_str(msg),
   25.38-      Error::Io(ref err) => write!(f, "obj IO error: {}", err),
   25.39-      Error::Ron(ref err) => write!(f, "obj Ron error: {}", err),
   25.40-      Error::Json(ref err) => write!(f, "obj Json error: {}", err),
   25.41-      Error::Bincode(ref err) => write!(f, "obj Bincode error: {}", err),
   25.42-      Error::Utf8(ref err) => write!(f, "obj Utf8 error: {}", err),
   25.43-      Error::Parse(ref err) => write!(f, "obj Parse error: {}", err),
   25.44-    }
   25.45-  }
   25.46-}
   25.47-
   25.48-impl From<io::Error> for Error {
   25.49-  fn from(e: io::Error) -> Self {
   25.50-    Error::Io(e)
   25.51-  }
   25.52-}
   25.53-
   25.54-impl From<std::string::ParseError> for Error {
   25.55-  fn from(e: std::string::ParseError) -> Self {
   25.56-    Error::Parse(e)
   25.57-  }
   25.58-}
   25.59-
   25.60-impl From<std::string::FromUtf8Error> for Error {
   25.61-  fn from(err: std::string::FromUtf8Error) -> Self {
   25.62-    Error::Utf8(err)
   25.63-  }
   25.64-}
   25.65-
   25.66-impl From<ron::Error> for Error {
   25.67-  fn from(e: ron::Error) -> Self {
   25.68-    Error::Ron(e)
   25.69-  }
   25.70-}
   25.71-
   25.72-impl From<serde_json::Error> for Error {
   25.73-  fn from(e: serde_json::Error) -> Self {
   25.74-    Error::Json(e)
   25.75-  }
   25.76-}
   25.77-
   25.78-impl From<bincode::Error> for Error {
   25.79-  fn from(e: bincode::Error) -> Self {
   25.80-    Error::Bincode(e)
   25.81-  }
   25.82-}
   25.83-
   25.84-impl std::error::Error for Error {}
    26.1--- a/obj/src/hash.rs	Sat Jun 03 19:57:46 2023 -0400
    26.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3@@ -1,51 +0,0 @@
    26.4-//! hash - wrapper for hash algorithms and types
    26.5-
    26.6-pub use blake3::{derive_key, hash, keyed_hash, Hash as B3Hash, Hasher as B3Hasher, OutputReader};
    26.7-pub use hex;
    26.8-pub use sha2::Sha512;
    26.9-
   26.10-pub use std::hash::{Hash, Hasher};
   26.11-
   26.12-pub const KEY_LEN: usize = 32;
   26.13-pub const OUT_LEN: usize = 32;
   26.14-pub const OUT_LEN_HEX: usize = OUT_LEN * 2;
   26.15-
   26.16-#[cfg(test)]
   26.17-mod tests {
   26.18-  use crate::*;
   26.19-  use super::*;
   26.20-  #[test]
   26.21-  fn id_state_hash() {
   26.22-    let id = id::Id(vec![0; KEY_LEN]);
   26.23-    let hash = id.state_hash(&mut B3Hasher::new());
   26.24-    assert_eq!(hash, id.state_hash(&mut B3Hasher::new()));
   26.25-  }
   26.26-
   26.27-  #[test]
   26.28-  fn id_hex() {
   26.29-    let id = id::Id(vec![255; KEY_LEN]);
   26.30-
   26.31-    assert_eq!(
   26.32-      hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(),
   26.33-      id.0
   26.34-    );
   26.35-  }
   26.36-
   26.37-  #[test]
   26.38-  fn rand_id() {
   26.39-    let id = id::Id::rand();
   26.40-    let hash = id.state_hash(&mut B3Hasher::new());
   26.41-    assert_eq!(hash, id.state_hash(&mut B3Hasher::new()));
   26.42-  }
   26.43-
   26.44-  #[test]
   26.45-  fn random_demon_id_is_valid() {
   26.46-    use id::PeerId;
   26.47-    for _ in 0..5000 {
   26.48-      let did = PeerId::rand();
   26.49-      let did2 = PeerId::rand();
   26.50-      assert_eq!(did, did);
   26.51-      assert_ne!(did, did2);
   26.52-    }
   26.53-  }
   26.54-}
    27.1--- a/obj/src/id.rs	Sat Jun 03 19:57:46 2023 -0400
    27.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3@@ -1,120 +0,0 @@
    27.4-use std::{fmt, str::FromStr};
    27.5-use serde::{Serialize, Deserialize};
    27.6-pub use uuid::Uuid;
    27.7-pub use ulid::Ulid;
    27.8-use rand::Rng;
    27.9-use crate::hash::{KEY_LEN,OUT_LEN,B3Hasher};
   27.10-/// a simple Id abstraction
   27.11-#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Serialize, Deserialize, Hash)]
   27.12-pub struct Id(pub Vec<u8>);
   27.13-
   27.14-impl Id {
   27.15-  pub fn rand() -> Self {
   27.16-    let mut rng = rand::thread_rng();
   27.17-    let vals: Vec<u8> = (0..KEY_LEN).map(|_| rng.gen_range(0..u8::MAX)).collect();
   27.18-    Id(vals)
   27.19-  }
   27.20-
   27.21-  pub fn state_hash(&self, state: &mut B3Hasher) -> Self {
   27.22-    let mut output = vec![0; OUT_LEN];
   27.23-    state.update(&self.0);
   27.24-    let mut res = state.finalize_xof();
   27.25-    res.fill(&mut output);
   27.26-    Id(output)
   27.27-  }
   27.28-
   27.29-  pub fn to_hex(&self) -> String {
   27.30-    hex::encode(&self.0)
   27.31-  }
   27.32-}
   27.33-
   27.34-/// PeerId
   27.35-///
   27.36-/// identifies a unique Peer
   27.37-#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
   27.38-pub struct PeerId {
   27.39-  id: [u8; 32],
   27.40-}
   27.41-
   27.42-impl PeerId {
   27.43-  pub fn new() -> Self {
   27.44-    Self::default()
   27.45-  }
   27.46-
   27.47-  pub fn rand() -> Self {
   27.48-    let pd = rand::thread_rng().gen::<[u8; 32]>();
   27.49-    Self { id: pd }
   27.50-  }
   27.51-
   27.52-  pub fn from_bytes(data: &[u8]) -> Self {
   27.53-    let pd = blake3::hash(data);
   27.54-    let hash = pd.as_bytes();
   27.55-    Self { id: *hash }
   27.56-  }
   27.57-}
   27.58-
   27.59-impl Default for PeerId {
   27.60-  fn default() -> Self {
   27.61-    PeerId { id: [0; 32] }
   27.62-  }
   27.63-}
   27.64-
   27.65-/// Identity trait
   27.66-///
   27.67-/// Defines Identity-related behaviors
   27.68-pub trait Identity: Sized {
   27.69-  /// return the hashed bytes of an ObjectId
   27.70-  fn id(&self) -> Id;
   27.71-}
   27.72-
   27.73-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
   27.74-pub struct ObjectId(u128);
   27.75-
   27.76-pub struct NameSpace {
   27.77-  pub prefix: Option<String>,
   27.78-  pub capacity: u64,
   27.79-  pub route: Vec<Id>,
   27.80-  pub key: Option<Id>,
   27.81-}
   27.82-
   27.83-pub struct Domain {
   27.84-  pub ns: NameSpace,
   27.85-  pub id: Id,
   27.86-}
   27.87-
   27.88-impl From<Uuid> for ObjectId {
   27.89-  fn from(uuid: Uuid) -> Self {
   27.90-    ObjectId(uuid.as_u128())
   27.91-  }
   27.92-}
   27.93-
   27.94-impl From<Ulid> for ObjectId {
   27.95-  fn from(ulid: Ulid) -> Self {
   27.96-    ObjectId(u128::from(ulid))
   27.97-  }
   27.98-}
   27.99-
  27.100-impl From<u128> for ObjectId {
  27.101-  fn from(src: u128) -> Self {
  27.102-    ObjectId(src)
  27.103-  }
  27.104-}
  27.105-
  27.106-impl FromStr for ObjectId {
  27.107-  type Err = ();
  27.108-  fn from_str(input: &str) -> std::result::Result<ObjectId, Self::Err> {
  27.109-    match input {
  27.110-      i => Ok(ObjectId(u128::from(Ulid::from_str(i).unwrap()))),
  27.111-    }
  27.112-  }
  27.113-}
  27.114-
  27.115-impl fmt::Display for ObjectId {
  27.116-  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  27.117-    match *self {
  27.118-      ObjectId(i) => {
  27.119-        write!(f, "{}", Ulid::from(i))
  27.120-      }
  27.121-    }
  27.122-  }
  27.123-}
    28.1--- a/obj/src/lib.rs	Sat Jun 03 19:57:46 2023 -0400
    28.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.3@@ -1,149 +0,0 @@
    28.4-//! obj/src/lib.rs --- Objective type library
    28.5-#![feature(associated_type_bounds)]
    28.6-mod err;
    28.7-pub use err::{Error, Result};
    28.8-mod types;
    28.9-pub use types::*;
   28.10-pub mod id;
   28.11-pub mod auth;
   28.12-pub mod hash;
   28.13-pub mod network;
   28.14-pub mod database;
   28.15-pub use bincode;
   28.16-pub use ron;
   28.17-use ron::extensions::Extensions;
   28.18-use serde::{de::DeserializeOwned, Deserialize, Serialize};
   28.19-pub use serde_json;
   28.20-use std::collections::{BTreeMap, HashMap};
   28.21-use std::io;
   28.22-
   28.23-/// Objective trait
   28.24-/// Define Object behaviors, implemented by Objects
   28.25-pub trait Objective {
   28.26-  fn encode(&self) -> Result<Vec<u8>>
   28.27-  where
   28.28-    Self: Serialize,
   28.29-  {
   28.30-    Ok(bincode::serialize(self)?)
   28.31-  }
   28.32-
   28.33-  fn encode_into<W>(&self, writer: W) -> Result<()>
   28.34-  where
   28.35-    W: io::Write,
   28.36-    Self: Serialize,
   28.37-  {
   28.38-    Ok(bincode::serialize_into(writer, self)?)
   28.39-  }
   28.40-
   28.41-  fn decode<'a>(bytes: &'a [u8]) -> Result<Self>
   28.42-  where
   28.43-    Self: Deserialize<'a>,
   28.44-  {
   28.45-    Ok(bincode::deserialize(bytes)?)
   28.46-  }
   28.47-
   28.48-  fn decode_from<R>(&self, rdr: R) -> Result<Self>
   28.49-  where
   28.50-    R: io::Read,
   28.51-    Self: DeserializeOwned,
   28.52-  {
   28.53-    Ok(bincode::deserialize_from(rdr)?)
   28.54-  }
   28.55-
   28.56-  fn to_ron_writer<W>(&self, writer: W) -> Result<()>
   28.57-  where
   28.58-    W: io::Write,
   28.59-    Self: Serialize,
   28.60-  {
   28.61-    Ok(ron::ser::to_writer_pretty(
   28.62-      writer,
   28.63-      &self,
   28.64-      ron::ser::PrettyConfig::new()
   28.65-        .indentor("  ".to_owned())
   28.66-        .extensions(Extensions::all()),
   28.67-    )?)
   28.68-  }
   28.69-
   28.70-  fn to_ron_string(&self) -> Result<String>
   28.71-  where
   28.72-    Self: Serialize,
   28.73-  {
   28.74-    Ok(ron::ser::to_string_pretty(
   28.75-      &self,
   28.76-      ron::ser::PrettyConfig::new().indentor("  ".to_owned()),
   28.77-    )?)
   28.78-  }
   28.79-
   28.80-  fn from_ron_reader<R>(&self, mut rdr: R) -> Result<Self>
   28.81-  where
   28.82-    R: io::Read,
   28.83-    Self: DeserializeOwned,
   28.84-  {
   28.85-    let mut bytes = Vec::new();
   28.86-    rdr.read_to_end(&mut bytes)?;
   28.87-    Ok(ron::de::from_bytes(&bytes)?)
   28.88-  }
   28.89-
   28.90-  fn from_ron_str<'a>(s: &'a str) -> Result<Self>
   28.91-  where
   28.92-    Self: Deserialize<'a>,
   28.93-  {
   28.94-    Ok(ron::de::from_bytes(s.as_bytes())?)
   28.95-  }
   28.96-
   28.97-  fn to_json_writer<W>(&self, writer: W) -> Result<()>
   28.98-  where
   28.99-    W: io::Write,
  28.100-    Self: Serialize,
  28.101-  {
  28.102-    //    let formatter = serde_json::ser::PrettyFormatter::with_indent(b"  ");
  28.103-    Ok(serde_json::ser::to_writer_pretty(writer, &self)?)
  28.104-  }
  28.105-
  28.106-  fn to_json_string(&self) -> Result<String>
  28.107-  where
  28.108-    Self: Serialize,
  28.109-  {
  28.110-    Ok(serde_json::ser::to_string_pretty(&self)?)
  28.111-  }
  28.112-
  28.113-  fn from_json_reader<R>(&self, mut rdr: R) -> Result<Self>
  28.114-  where
  28.115-    R: io::Read,
  28.116-    Self: DeserializeOwned,
  28.117-  {
  28.118-    let mut bytes = Vec::new();
  28.119-    rdr.read_to_end(&mut bytes)?;
  28.120-    Ok(serde_json::de::from_slice(&bytes)?)
  28.121-  }
  28.122-
  28.123-  fn from_json_str<'a>(s: &'a str) -> Result<Self>
  28.124-  where
  28.125-    Self: Deserialize<'a>,
  28.126-  {
  28.127-    Ok(serde_json::de::from_slice(s.as_bytes())?)
  28.128-  }
  28.129-}
  28.130-
  28.131-impl<T> Objective for Vec<T> {}
  28.132-impl<K, V> Objective for HashMap<K, V> {}
  28.133-impl<K, V> Objective for BTreeMap<K, V> {}
  28.134-impl Objective for std::path::PathBuf {}
  28.135-impl Objective for std::path::Path {}
  28.136-impl Objective for std::string::String {}
  28.137-impl Objective for std::any::TypeId {}
  28.138-impl Objective for u8 {}
  28.139-impl Objective for u16 {}
  28.140-impl Objective for u32 {}
  28.141-impl Objective for u64 {}
  28.142-impl Objective for u128 {}
  28.143-impl Objective for i8 {}
  28.144-impl Objective for i16 {}
  28.145-impl Objective for i32 {}
  28.146-impl Objective for i64 {}
  28.147-impl Objective for i128 {}
  28.148-impl Objective for isize {}
  28.149-impl Objective for usize {}
  28.150-impl Objective for f32 {}
  28.151-impl Objective for f64 {}
  28.152-
    29.1--- a/obj/src/network.rs	Sat Jun 03 19:57:46 2023 -0400
    29.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3@@ -1,59 +0,0 @@
    29.4-//! cfg::config::network
    29.5-//!
    29.6-//! Network configuration primitives
    29.7-use serde::{Deserialize, Serialize};
    29.8-use std::{fmt, net::SocketAddr};
    29.9-
   29.10-/// Network configuration
   29.11-#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone)]
   29.12-pub struct NetworkConfig {
   29.13-  /// a socket to bind
   29.14-  pub socket: SocketAddr,
   29.15-  /// a proxy to forward packets from
   29.16-  pub proxy: Option<SocketAddr>,
   29.17-  /// tunnel to use
   29.18-  pub tunnel: Option<String>,
   29.19-  /// network engine to attach
   29.20-  pub engine: EngineType,
   29.21-  /// peers to register AOT
   29.22-  pub peers: Option<Vec<SocketAddr>>,
   29.23-}
   29.24-
   29.25-impl Default for NetworkConfig {
   29.26-  fn default() -> Self {
   29.27-    NetworkConfig {
   29.28-      socket: "127.0.0.1:0".parse().unwrap(),
   29.29-      proxy: None,
   29.30-      tunnel: None,
   29.31-      engine: EngineType::default(),
   29.32-      peers: None,
   29.33-    }
   29.34-  }
   29.35-}
   29.36-
   29.37-#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone)]
   29.38-pub enum EngineType {
   29.39-  Quic,
   29.40-  Http,
   29.41-  Dns,
   29.42-  Ssh,
   29.43-  Uds,
   29.44-}
   29.45-
   29.46-impl Default for EngineType {
   29.47-  fn default() -> Self {
   29.48-    Self::Http
   29.49-  }
   29.50-}
   29.51-
   29.52-impl std::fmt::Display for EngineType {
   29.53-  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
   29.54-    match self {
   29.55-      EngineType::Quic => write!(f, "quic"),
   29.56-      EngineType::Http => write!(f, "http"),
   29.57-      EngineType::Dns => write!(f, "dns"),
   29.58-      EngineType::Ssh => write!(f, "ssh"),
   29.59-      EngineType::Uds => write!(f, "uds"),
   29.60-    }
   29.61-  }
   29.62-}
    30.1--- a/obj/src/types.rs	Sat Jun 03 19:57:46 2023 -0400
    30.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3@@ -1,70 +0,0 @@
    30.4-//! obj/src/types.rs --- OBJ type descriptions used by our demo
    30.5-use crate::{Deserialize, Objective, Result, Serialize};
    30.6-use std::collections::HashMap;
    30.7-
    30.8-/// APPLICATION TYPES
    30.9-#[derive(Serialize,Deserialize,Default)]
   30.10-pub enum Service {
   30.11-  Weather,
   30.12-  Stocks,
   30.13-  Dynamic(Vec<Service>),
   30.14-  Custom(CustomService),
   30.15-  #[default]
   30.16-  Bench,
   30.17-}
   30.18-
   30.19-impl Objective for Service {}
   30.20-
   30.21-impl From<&str> for Service {
   30.22-  fn from(value: &str) -> Self {
   30.23-    match value {
   30.24-      "weather" => Service::Weather,
   30.25-      "stocks" => Service::Stocks,
   30.26-      "bench" => Service::Bench,
   30.27-      s => {
   30.28-        if s.contains(",") {
   30.29-          let x = s.split(",");
   30.30-          Service::Dynamic(
   30.31-            x.map(|y| Service::Custom(y.into()))
   30.32-              .collect::<Vec<Service>>(),
   30.33-          )
   30.34-        } else {
   30.35-          Service::Custom(s.into())
   30.36-        }
   30.37-      }
   30.38-    }
   30.39-  }
   30.40-}
   30.41-
   30.42-#[derive(Serialize,Deserialize,Default)]
   30.43-pub struct CustomService {
   30.44-  name: String,
   30.45-  registry: HashMap<String,Vec<u8>>,
   30.46-}
   30.47-
   30.48-impl Objective for CustomService {}
   30.49-impl From<CustomService> for Service {
   30.50-  fn from(value: CustomService) -> Self {
   30.51-    Service::Custom(value)
   30.52-  }
   30.53-}
   30.54-impl From<&str> for CustomService {
   30.55-  fn from(value: &str) -> Self {
   30.56-    let name = value.to_owned();
   30.57-    let registry = HashMap::new();
   30.58-    CustomService { name, registry }
   30.59-  }
   30.60-}
   30.61-
   30.62-#[derive(Serialize, Deserialize,Default)]
   30.63-pub struct Complex<X: Objective> {
   30.64-  data: X,
   30.65-  stack: Vec<u8>,
   30.66-  registry: HashMap<String,Vec<u8>>,
   30.67-}
   30.68-
   30.69-impl Objective for Complex<Service> {}
   30.70-
   30.71-pub fn generate_complex() -> Result<Complex<Service>> {
   30.72-  Ok(Complex::<Service>::from_json_str("hi")?)
   30.73-}
    31.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2+++ b/package.lisp	Sat Jun 03 22:48:46 2023 -0400
    31.3@@ -0,0 +1,75 @@
    31.4+;; demo package.lisp
    31.5+(defpackage :demo
    31.6+  (:use #:cl #:cffi)
    31.7+  (:local-nicknames
    31.8+   ;;   (#:rdb #:cl-rocksdb)
    31.9+   (#:v #:org.shirakumo.verbose)
   31.10+   (#:bt #:bordeaux-threads)
   31.11+   (#:cli #:clingon))
   31.12+  ;; db.lisp
   31.13+  ;; (:export
   31.14+  ;;  #:create-options
   31.15+  ;;  #:destroy-options
   31.16+  ;;  #:increase-parallelism
   31.17+  ;;  #:optimize-level-style-compaction
   31.18+  ;;  #:set-create-if-missing
   31.19+  ;;  #:create-writeoptions
   31.20+  ;;  #:destroy-writeoptions
   31.21+  ;;  #:create-readoptions
   31.22+  ;;  #:destroy-readoptions
   31.23+  ;;  #:open-db
   31.24+  ;;  #:close-db
   31.25+  ;;  #:cancel-all-background-work
   31.26+  ;;  #:put-kv
   31.27+  ;;  #:put-kv-str
   31.28+  ;;  #:get-kv
   31.29+  ;;  #:get-kv-str
   31.30+  ;;  #:create-iter
   31.31+  ;;  #:destroy-iter
   31.32+  ;;  #:move-iter-to-first
   31.33+  ;;  #:move-iter-forward
   31.34+  ;;  #:move-iter-backword
   31.35+  ;;  #:valid-iter-p
   31.36+  ;;  #:iter-key
   31.37+  ;;  #:iter-key-str
   31.38+  ;;  #:iter-value
   31.39+  ;;  #:iter-value-str
   31.40+  ;;  #:with-open-db
   31.41+  ;;  #:with-iter)
   31.42+  ;; demo.lisp
   31.43+  (:export
   31.44+   #:main
   31.45+   #:demo-path
   31.46+   #:db-path
   31.47+   #:cli-opts
   31.48+   #:cli-handler
   31.49+   #:cli-cmd)
   31.50+  ;; ui.lisp
   31.51+  (:export
   31.52+   #:on-new-window
   31.53+   #:start-ui)
   31.54+  ;; tk.lisp
   31.55+  (:export
   31.56+   #:source-dir
   31.57+   #:random-id
   31.58+   #:scan-dir
   31.59+   #:mkstr
   31.60+   #:symb
   31.61+   #:sbq-reader)
   31.62+  ;; rs.lisp
   31.63+  (:export
   31.64+   #:*cargo-target*
   31.65+   #:*rs-macros*
   31.66+   #:rs-defmacro
   31.67+   #:rs-macroexpand-1
   31.68+   #:rs-macroexpand)
   31.69+  ;; ffi.lisp
   31.70+  ;; (:export
   31.71+  ;;  #:quiche-lib-path
   31.72+  ;;  #:rocksdb-lib-path
   31.73+  ;;  #:demo-lib-path
   31.74+  ;;  #:find-rs-cdylib
   31.75+  ;;  #:install-demo-lib
   31.76+  ;;  #:install-quiche-lib
   31.77+  ;;  #:install-rocksdb-lib)
   31.78+)
    32.1--- a/pkg.lisp	Sat Jun 03 19:57:46 2023 -0400
    32.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.3@@ -1,78 +0,0 @@
    32.4-#|
    32.5-demo
    32.6-> (demo:main)
    32.7-|#
    32.8-(defpackage :demo
    32.9-  (:use #:cl #:cffi)
   32.10-  (:local-nicknames
   32.11-   ;;   (#:rdb #:cl-rocksdb)
   32.12-   (#:v #:org.shirakumo.verbose)
   32.13-   (#:bt #:bordeaux-threads)
   32.14-   (#:cli #:clingon))
   32.15-  ;; db.lisp
   32.16-  ;; (:export
   32.17-  ;;  #:create-options
   32.18-  ;;  #:destroy-options
   32.19-  ;;  #:increase-parallelism
   32.20-  ;;  #:optimize-level-style-compaction
   32.21-  ;;  #:set-create-if-missing
   32.22-  ;;  #:create-writeoptions
   32.23-  ;;  #:destroy-writeoptions
   32.24-  ;;  #:create-readoptions
   32.25-  ;;  #:destroy-readoptions
   32.26-  ;;  #:open-db
   32.27-  ;;  #:close-db
   32.28-  ;;  #:cancel-all-background-work
   32.29-  ;;  #:put-kv
   32.30-  ;;  #:put-kv-str
   32.31-  ;;  #:get-kv
   32.32-  ;;  #:get-kv-str
   32.33-  ;;  #:create-iter
   32.34-  ;;  #:destroy-iter
   32.35-  ;;  #:move-iter-to-first
   32.36-  ;;  #:move-iter-forward
   32.37-  ;;  #:move-iter-backword
   32.38-  ;;  #:valid-iter-p
   32.39-  ;;  #:iter-key
   32.40-  ;;  #:iter-key-str
   32.41-  ;;  #:iter-value
   32.42-  ;;  #:iter-value-str
   32.43-  ;;  #:with-open-db
   32.44-  ;;  #:with-iter)
   32.45-  ;; demo.lisp
   32.46-  (:export
   32.47-   #:main
   32.48-   #:demo-path
   32.49-   #:db-path
   32.50-   #:cli-opts
   32.51-   #:cli-handler
   32.52-   #:cli-cmd)
   32.53-  ;; ui.lisp
   32.54-  (:export
   32.55-   #:on-new-window
   32.56-   #:start-ui)
   32.57-  ;; tk.lisp
   32.58-  (:export
   32.59-   #:source-dir
   32.60-   #:random-id
   32.61-   #:scan-dir
   32.62-   #:mkstr
   32.63-   #:symb
   32.64-   #:sbq-reader)
   32.65-  ;; rs.lisp
   32.66-  (:export
   32.67-   #:*cargo-target*
   32.68-   #:*rs-macros*
   32.69-   #:rs-defmacro
   32.70-   #:rs-macroexpand-1
   32.71-   #:rs-macroexpand)
   32.72-  ;; ffi.lisp
   32.73-  ;; (:export
   32.74-  ;;  #:quiche-lib-path
   32.75-  ;;  #:rocksdb-lib-path
   32.76-  ;;  #:demo-lib-path
   32.77-  ;;  #:find-rs-cdylib
   32.78-  ;;  #:install-demo-lib
   32.79-  ;;  #:install-quiche-lib
   32.80-  ;;  #:install-rocksdb-lib)
   32.81-  )
    33.1--- a/readme.org	Sat Jun 03 19:57:46 2023 -0400
    33.2+++ b/readme.org	Sat Jun 03 22:48:46 2023 -0400
    33.3@@ -1,5 +1,22 @@
    33.4-#+TITTLE: cl-demo
    33.5-This is a demo software suite which showcases the power of Common Lisp and Rust.
    33.6+#+TITTLE: Demo
    33.7+Welcome to our first demo system. What you will find here is a modular
    33.8+client-server software stack which can be extended and customized by
    33.9+the user at runtime.
   33.10+
   33.11+* How it works
   33.12+The backend services are written in Rust and controlled by a simple
   33.13+messaging protocol. Services provide common runtime capabilities known
   33.14+as the /core protocol/ but are specialized on a unique /service type/
   33.15+which may in turn register their own /custom protocols/ (via core).
   33.16+
   33.17+Services are capable of dispatching data directly to clients, or
   33.18+storing data in the /database/ (TBD).
   33.19+
   33.20+The frontend clients are pre-dominantly written in Common Lisp and
   33.21+come in many shapes and sizes. There is a cli-client, web-client
   33.22+(CLOG), docker-client (archlinux, stumpwm, McCLIM), and native-client
   33.23+which also compiles to WASM (slint-rs).
   33.24+
   33.25 * Guide
   33.26 ** Build
   33.27 - *install dependencies*
   33.28@@ -11,21 +28,19 @@
   33.29     - on MacOS :: =brew install sbcl=
   33.30     - on Windows :: download from
   33.31       <https://www.sbcl.org/platform-table.html> and figure it out.
   33.32-  - Quiche
   33.33-  - RocksDB
   33.34 - *make executables* \\
   33.35   Simply run =make build=. Read the ~makefile~ and change the options
   33.36   as needed.
   33.37 - M :: Mode (debug, release)
   33.38 - L :: Lisp (sbcl, cmucl, ccl)
   33.39-- P :: Python (python3, python2)
   33.40+- C :: Config (default.cfg)
   33.41 ** Run
   33.42 #+begin_src shell
   33.43-  make build
   33.44-  ./out/demo
   33.45+  ./demo -i
   33.46 #+end_src
   33.47 ** Config
   33.48-Configs can be specified in JSON, TOML, RON, or of course SEXP.
   33.49+Configs can be specified in JSON, TOML, RON, or of course SEXP. See
   33.50+=default.cfg= for an example.
   33.51 ** Play
   33.52 The high-level user interface is presented as a multi-modal GUI
   33.53 application which adapts to the specific application /instances/
    34.1--- a/rs.lisp	Sat Jun 03 19:57:46 2023 -0400
    34.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3@@ -1,78 +0,0 @@
    34.4-;;; RUST DSL
    34.5-
    34.6-;; So basically, this was born out of personal frustration with how
    34.7-;; cbindgen and Rust macros work (they don't). Rust macros in general
    34.8-;; are something of a pain in my opinion, so I thought why not just
    34.9-;; generate Rust code from Lisp instead?
   34.10-
   34.11-(in-package :demo)
   34.12-
   34.13-(defvar *cargo-target* #p"/Users/ellis/dev/otom8/demo/target/")
   34.14-(defvar *rs-macros* nil)
   34.15-
   34.16-;; TODO gensyms
   34.17-(defmacro rs-defmacro (name args &body body)
   34.18-  "Define a macro which can be used within the body of a 'with-rs' form."
   34.19-  `(prog1
   34.20-       (defmacro ,name ,@(mapcar #`(,a1) args) ,@body)
   34.21-     (push ',name *rs-macros*)))
   34.22-
   34.23-(defun rs-mod-form (crate &optional mods pub)
   34.24-  "Generate a basic mod form (CRATE . [MODS] [PUB])"
   34.25-    `(,crate ,mods ,pub))
   34.26-
   34.27-(defmacro with-rs-env (imports &body body)
   34.28-  "Generate an environment for use within a Rust generator macro."
   34.29-  `(let ((imports ,(mapcar #'rs-mod-form imports)))
   34.30-     (format nil "~A~&~A" imports ',body)))
   34.31-
   34.32-(defun rs-use (crate &optional mods pub)
   34.33-  "Generate a single Rust use statement."
   34.34-  (concatenate
   34.35-   'string
   34.36-   (if pub "pub " "")
   34.37-   "use " crate "::{"
   34.38-   (cond
   34.39-     ((consp mods)
   34.40-      (reduce
   34.41-       (lambda (x y) (format nil "~A,~A" x y))
   34.42-       mods))
   34.43-     (t mods))
   34.44-   "};"))
   34.45-
   34.46-(defun rs-mod (mod &optional pub)
   34.47-  "Generate a single Rust mod statement."
   34.48-  (concatenate
   34.49-   'string
   34.50-   (if pub "pub " "")
   34.51-   "mod " mod ";"))
   34.52-
   34.53-(defun rs-imports (&rest imports)
   34.54-  "Generate a string of Rust 'use' statements."
   34.55-  (cond
   34.56-    ((consp imports)
   34.57-     (mapcar (lambda (x) (apply #'rs-use (apply #'rs-mod-form x))) imports))
   34.58-    (t imports)))
   34.59-
   34.60-(defmacro rs-extern-c-fn (name args &optional pub unsafe no-mangle &body body)
   34.61-  "Generate a Rust extern 'C' fn."
   34.62-  `(concatenate
   34.63-   'string
   34.64-   ,(when no-mangle (format nil "#[no_mangle]~&"))
   34.65-   ,(when pub "pub ")
   34.66-   ,(when unsafe "unsafe ")
   34.67-   "extern \"C\" fn " ,name "("
   34.68-   ,(cond
   34.69-      ((consp args) (reduce (lambda (x y) (format nil "~A,~A" x y)) args))
   34.70-      (t args))
   34.71-   ")" "{" ,@body "}"))
   34.72-
   34.73-(defun rs-obj-impl (obj)
   34.74-  "Implement Objective for give OBJ."
   34.75-  (format nil "impl Objective for ~A {};" obj))
   34.76-
   34.77-;; (defun rs-macroexpand-1 (form &optional env))
   34.78-
   34.79-;; (defun rs-macroexpand (env &rest body)
   34.80-
   34.81-;;; 
    35.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2+++ b/src/build.rs	Sat Jun 03 22:48:46 2023 -0400
    35.3@@ -0,0 +1,17 @@
    35.4+use std::env;
    35.5+use std::fs::create_dir;
    35.6+use std::path::PathBuf;
    35.7+fn main() {
    35.8+  let crate_dir: PathBuf = env::var("CARGO_MANIFEST_DIR")
    35.9+    .expect("CARGO_MANIFEST_DIR env var is not defined")
   35.10+    .into();
   35.11+  // let mpk_py = "build.py";
   35.12+  let build_dir = crate_dir.join("ffi/");
   35.13+  if !build_dir.exists() {
   35.14+    create_dir(&build_dir).unwrap();
   35.15+  }
   35.16+  cbindgen::generate(crate_dir)
   35.17+    .expect("Unable to find cbindgen.toml configuration file")
   35.18+    .write_to_file(build_dir.join("demo.h"));
   35.19+  
   35.20+}
    36.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2+++ b/src/cbindgen.toml	Sat Jun 03 22:48:46 2023 -0400
    36.3@@ -0,0 +1,14 @@
    36.4+include_guard = "demo_h"
    36.5+autogen_warning = "/* DO NOT TOUCH */"
    36.6+include_version = true
    36.7+language = "C"
    36.8+cpp_compat = true
    36.9+line_length = 88
   36.10+documentation = true	
   36.11+[parse]
   36.12+parse_deps = true
   36.13+include = ["obj","fig","libc"]
   36.14+extra_bindings = ["obj","fig","libc"]
   36.15+#expand = ["demo","obj"]
   36.16+#[parse.expand]
   36.17+#crates = ["demo"]
   36.18\ No newline at end of file
    38.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2+++ b/src/crates/obj/Cargo.toml	Sat Jun 03 22:48:46 2023 -0400
    38.3@@ -0,0 +1,27 @@
    38.4+[package]
    38.5+name = "obj"
    38.6+version = "0.1.0"
    38.7+edition = "2021"
    38.8+[features]
    38.9+oauth = ["yup-oauth2"]
   38.10+
   38.11+[dependencies]
   38.12+ron = "0.7.0"
   38.13+bincode = "1.3.3"
   38.14+serde_json = "1.0.68"
   38.15+serde = { version = "1.0.130", features = ["derive"] }
   38.16+chrono = { version = "0.4.19", features = ["serde"] }
   38.17+mime = "0.3.16"
   38.18+regex = "1.5.4"
   38.19+rusty_ulid = "0.11.0"
   38.20+uuid = { version = "0.8", features = ["serde"] }
   38.21+yup-oauth2 = { version = "5.1.0", optional = true }
   38.22+blake3 = "1.0.0"
   38.23+hashbrown = "0.11.2"
   38.24+rand = "0.8.0"
   38.25+sha2 = "0.9.5"
   38.26+hex = "0.4.3"
   38.27+ulid = "1.0.0"
   38.28+
   38.29+[target.'cfg(target_arch = "wasm32")'.dependencies]
   38.30+uuid = { version = "0.8", features = ["wasm-bindgen"] }
    39.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2+++ b/src/crates/obj/proc_macros/Cargo.toml	Sat Jun 03 22:48:46 2023 -0400
    39.3@@ -0,0 +1,10 @@
    39.4+[package]
    39.5+name = "proc_macros"
    39.6+version = "0.1.0"
    39.7+edition = "2021"
    39.8+[lib]
    39.9+proc-macro = true
   39.10+[dependencies]
   39.11+quote = "1.0"
   39.12+proc-macro2 = "1.0"
   39.13+syn = "1.0"
   39.14\ No newline at end of file
    40.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2+++ b/src/crates/obj/proc_macros/src/derive.rs	Sat Jun 03 22:48:46 2023 -0400
    40.3@@ -0,0 +1,5 @@
    40.4+mod derive;
    40.5+use proc_macro::TokenStream;
    40.6+pub fn derive_static_type(input: TokenStream) -> TokenStream {
    40.7+    derive::derive_static_type(input)
    40.8+}
    41.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2+++ b/src/crates/obj/proc_macros/src/lib.rs	Sat Jun 03 22:48:46 2023 -0400
    41.3@@ -0,0 +1,1 @@
    41.4+
    42.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2+++ b/src/crates/obj/src/auth.rs	Sat Jun 03 22:48:46 2023 -0400
    42.3@@ -0,0 +1,72 @@
    42.4+//! Auth Configs
    42.5+use serde::{Deserialize, Serialize};
    42.6+
    42.7+#[cfg(feature = "oauth")]
    42.8+use yup_oauth2::ApplicationSecret;
    42.9+
   42.10+#[derive(Serialize, Deserialize, Debug, Default, Hash)]
   42.11+pub struct AuthConfig {
   42.12+  pub provider: String,
   42.13+  #[cfg(feature = "oauth")]
   42.14+  pub oauth: Option<Oauth2Config>,
   42.15+  pub ssh: Option<SshConfig>,
   42.16+  pub pw: Option<PasswordConfig>,
   42.17+}
   42.18+
   42.19+#[derive(Serialize, Deserialize, Default, Debug, Hash)]
   42.20+pub struct PasswordConfig(String, String);
   42.21+
   42.22+#[cfg(feature = "oauth")]
   42.23+#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone, Default)]
   42.24+pub struct Oauth2Config {
   42.25+  pub client_id: String,
   42.26+  pub client_secret: String,
   42.27+  pub redirect_uris: Vec<String>,
   42.28+  pub auth_uri: String,
   42.29+  pub token_uri: String,
   42.30+  pub project_id: Option<String>, //for apptoken
   42.31+  pub client_email: Option<String>,
   42.32+  /// The URL of the public x509 certificate, used to verify the signature on
   42.33+  /// JWTs, such as ID tokens, signed by the authentication provider.
   42.34+  pub auth_provider_x509_cert_url: Option<String>,
   42.35+  ///  The URL of the public x509 certificate, used to verify JWTs signed by the
   42.36+  /// client.
   42.37+  pub client_x509_cert_url: Option<String>,
   42.38+}
   42.39+
   42.40+#[cfg(feature = "oauth")]
   42.41+impl From<ApplicationSecret> for Oauth2Config {
   42.42+  fn from(shh: ApplicationSecret) -> Self {
   42.43+    Oauth2Config {
   42.44+      client_id: shh.client_id,
   42.45+      client_secret: shh.client_secret,
   42.46+      redirect_uris: shh.redirect_uris,
   42.47+      auth_uri: shh.auth_uri,
   42.48+      token_uri: shh.token_uri,
   42.49+      project_id: shh.project_id,
   42.50+      client_email: shh.client_email,
   42.51+      auth_provider_x509_cert_url: shh.auth_provider_x509_cert_url,
   42.52+      client_x509_cert_url: shh.client_x509_cert_url,
   42.53+    }
   42.54+  }
   42.55+}
   42.56+
   42.57+#[cfg(feature = "oauth")]
   42.58+impl From<Oauth2Config> for ApplicationSecret {
   42.59+  fn from(cfg: Oauth2Config) -> Self {
   42.60+    ApplicationSecret {
   42.61+      client_id: cfg.client_id,
   42.62+      client_secret: cfg.client_secret,
   42.63+      redirect_uris: cfg.redirect_uris,
   42.64+      auth_uri: cfg.auth_uri,
   42.65+      token_uri: cfg.token_uri,
   42.66+      project_id: cfg.project_id,
   42.67+      client_email: cfg.client_email,
   42.68+      auth_provider_x509_cert_url: cfg.auth_provider_x509_cert_url,
   42.69+      client_x509_cert_url: cfg.client_x509_cert_url,
   42.70+    }
   42.71+  }
   42.72+}
   42.73+
   42.74+#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone, Default)]
   42.75+pub struct SshConfig {}
    43.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2+++ b/src/crates/obj/src/cfg.rs	Sat Jun 03 22:48:46 2023 -0400
    43.3@@ -0,0 +1,51 @@
    43.4+/// common trait for all config modules. This trait provides functions
    43.5+/// for de/serializing to/from RON, updating fields, and formatting.
    43.6+use serde::{Serialize, Deserialize};
    43.7+use crate::Objective;
    43.8+use std::collections::HashMap as M;
    43.9+use std::path::PathBuf;
   43.10+use std::string::String as S;
   43.11+use std::error::Error as E;
   43.12+use std::boxed::Box as B;
   43.13+type R<X> = std::result::Result<X,B<dyn E>>;
   43.14+
   43.15+pub trait Configure: Objective {
   43.16+  fn update(&self) -> R<()> {
   43.17+    Ok(())
   43.18+  }
   43.19+}
   43.20+
   43.21+#[derive(Serialize, Deserialize, Debug, Default)]
   43.22+pub struct ShellConfig {
   43.23+  pub env: M<S,S>,
   43.24+  pub cmds: M<S,S>,
   43.25+  pub shell: ShellType,
   43.26+}
   43.27+
   43.28+impl Objective for ShellConfig {}
   43.29+
   43.30+#[derive(Serialize, Deserialize, Debug, Hash, Default)]
   43.31+pub enum ShellType {
   43.32+  #[default]
   43.33+  Bash,
   43.34+  Zsh,
   43.35+  Sh,
   43.36+}
   43.37+
   43.38+#[derive(Serialize, Deserialize, Debug, Default)]
   43.39+pub enum EditorType {
   43.40+  #[default]
   43.41+  Emacs,
   43.42+  Vi,
   43.43+  Nano,
   43.44+}
   43.45+
   43.46+#[derive(Serialize, Deserialize, Debug, Default)]
   43.47+pub struct EditorConfig {
   43.48+  pub editor: EditorType,
   43.49+  pub cmds: M<S,S>,
   43.50+  pub init_file: PathBuf,
   43.51+}
   43.52+
   43.53+#[cfg(test)]
   43.54+mod tests;
    44.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2+++ b/src/crates/obj/src/database.rs	Sat Jun 03 22:48:46 2023 -0400
    44.3@@ -0,0 +1,18 @@
    44.4+//! cfg::config::database
    44.5+//!
    44.6+//! Database configuration primitives
    44.7+use serde::{Deserialize, Serialize};
    44.8+
    44.9+#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq)]
   44.10+pub struct DatabaseConfig {
   44.11+  engine: DatabaseType,
   44.12+  path: String,
   44.13+  cfs: Vec<String>,
   44.14+}
   44.15+
   44.16+#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq)]
   44.17+pub enum DatabaseType {
   44.18+  RocksDB,
   44.19+  Postgres,
   44.20+  Alch,
   44.21+}
    45.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2+++ b/src/crates/obj/src/err.rs	Sat Jun 03 22:48:46 2023 -0400
    45.3@@ -0,0 +1,81 @@
    45.4+//! obj errors
    45.5+use std::{fmt, io};
    45.6+
    45.7+/// obj Result wrapper
    45.8+pub type Result<T> = std::result::Result<T, Error>;
    45.9+
   45.10+/// obj Error type
   45.11+#[derive(Debug)]
   45.12+pub enum Error {
   45.13+  Message(String),
   45.14+  Ron(ron::error::Error),
   45.15+  Json(serde_json::error::Error),
   45.16+  Io(io::Error),
   45.17+  Bincode(bincode::Error),
   45.18+  Utf8(std::string::FromUtf8Error),
   45.19+  Parse(std::string::ParseError),
   45.20+}
   45.21+
   45.22+impl serde::ser::Error for Error {
   45.23+  fn custom<T: fmt::Display>(msg: T) -> Self {
   45.24+    Error::Message(msg.to_string())
   45.25+  }
   45.26+}
   45.27+
   45.28+impl serde::de::Error for Error {
   45.29+  fn custom<T: fmt::Display>(msg: T) -> Self {
   45.30+    Error::Message(msg.to_string())
   45.31+  }
   45.32+}
   45.33+
   45.34+impl fmt::Display for Error {
   45.35+  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
   45.36+    match self {
   45.37+      Error::Message(msg) => f.write_str(msg),
   45.38+      Error::Io(ref err) => write!(f, "obj IO error: {}", err),
   45.39+      Error::Ron(ref err) => write!(f, "obj Ron error: {}", err),
   45.40+      Error::Json(ref err) => write!(f, "obj Json error: {}", err),
   45.41+      Error::Bincode(ref err) => write!(f, "obj Bincode error: {}", err),
   45.42+      Error::Utf8(ref err) => write!(f, "obj Utf8 error: {}", err),
   45.43+      Error::Parse(ref err) => write!(f, "obj Parse error: {}", err),
   45.44+    }
   45.45+  }
   45.46+}
   45.47+
   45.48+impl From<io::Error> for Error {
   45.49+  fn from(e: io::Error) -> Self {
   45.50+    Error::Io(e)
   45.51+  }
   45.52+}
   45.53+
   45.54+impl From<std::string::ParseError> for Error {
   45.55+  fn from(e: std::string::ParseError) -> Self {
   45.56+    Error::Parse(e)
   45.57+  }
   45.58+}
   45.59+
   45.60+impl From<std::string::FromUtf8Error> for Error {
   45.61+  fn from(err: std::string::FromUtf8Error) -> Self {
   45.62+    Error::Utf8(err)
   45.63+  }
   45.64+}
   45.65+
   45.66+impl From<ron::Error> for Error {
   45.67+  fn from(e: ron::Error) -> Self {
   45.68+    Error::Ron(e)
   45.69+  }
   45.70+}
   45.71+
   45.72+impl From<serde_json::Error> for Error {
   45.73+  fn from(e: serde_json::Error) -> Self {
   45.74+    Error::Json(e)
   45.75+  }
   45.76+}
   45.77+
   45.78+impl From<bincode::Error> for Error {
   45.79+  fn from(e: bincode::Error) -> Self {
   45.80+    Error::Bincode(e)
   45.81+  }
   45.82+}
   45.83+
   45.84+impl std::error::Error for Error {}
    46.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2+++ b/src/crates/obj/src/hash.rs	Sat Jun 03 22:48:46 2023 -0400
    46.3@@ -0,0 +1,51 @@
    46.4+//! hash - wrapper for hash algorithms and types
    46.5+
    46.6+pub use blake3::{derive_key, hash, keyed_hash, Hash as B3Hash, Hasher as B3Hasher, OutputReader};
    46.7+pub use hex;
    46.8+pub use sha2::Sha512;
    46.9+
   46.10+pub use std::hash::{Hash, Hasher};
   46.11+
   46.12+pub const KEY_LEN: usize = 32;
   46.13+pub const OUT_LEN: usize = 32;
   46.14+pub const OUT_LEN_HEX: usize = OUT_LEN * 2;
   46.15+
   46.16+#[cfg(test)]
   46.17+mod tests {
   46.18+  use crate::*;
   46.19+  use super::*;
   46.20+  #[test]
   46.21+  fn id_state_hash() {
   46.22+    let id = id::Id(vec![0; KEY_LEN]);
   46.23+    let hash = id.state_hash(&mut B3Hasher::new());
   46.24+    assert_eq!(hash, id.state_hash(&mut B3Hasher::new()));
   46.25+  }
   46.26+
   46.27+  #[test]
   46.28+  fn id_hex() {
   46.29+    let id = id::Id(vec![255; KEY_LEN]);
   46.30+
   46.31+    assert_eq!(
   46.32+      hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(),
   46.33+      id.0
   46.34+    );
   46.35+  }
   46.36+
   46.37+  #[test]
   46.38+  fn rand_id() {
   46.39+    let id = id::Id::rand();
   46.40+    let hash = id.state_hash(&mut B3Hasher::new());
   46.41+    assert_eq!(hash, id.state_hash(&mut B3Hasher::new()));
   46.42+  }
   46.43+
   46.44+  #[test]
   46.45+  fn random_demon_id_is_valid() {
   46.46+    use id::PeerId;
   46.47+    for _ in 0..5000 {
   46.48+      let did = PeerId::rand();
   46.49+      let did2 = PeerId::rand();
   46.50+      assert_eq!(did, did);
   46.51+      assert_ne!(did, did2);
   46.52+    }
   46.53+  }
   46.54+}
    47.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2+++ b/src/crates/obj/src/id.rs	Sat Jun 03 22:48:46 2023 -0400
    47.3@@ -0,0 +1,120 @@
    47.4+use std::{fmt, str::FromStr};
    47.5+use serde::{Serialize, Deserialize};
    47.6+pub use uuid::Uuid;
    47.7+pub use ulid::Ulid;
    47.8+use rand::Rng;
    47.9+use crate::hash::{KEY_LEN,OUT_LEN,B3Hasher};
   47.10+/// a simple Id abstraction
   47.11+#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Serialize, Deserialize, Hash)]
   47.12+pub struct Id(pub Vec<u8>);
   47.13+
   47.14+impl Id {
   47.15+  pub fn rand() -> Self {
   47.16+    let mut rng = rand::thread_rng();
   47.17+    let vals: Vec<u8> = (0..KEY_LEN).map(|_| rng.gen_range(0..u8::MAX)).collect();
   47.18+    Id(vals)
   47.19+  }
   47.20+
   47.21+  pub fn state_hash(&self, state: &mut B3Hasher) -> Self {
   47.22+    let mut output = vec![0; OUT_LEN];
   47.23+    state.update(&self.0);
   47.24+    let mut res = state.finalize_xof();
   47.25+    res.fill(&mut output);
   47.26+    Id(output)
   47.27+  }
   47.28+
   47.29+  pub fn to_hex(&self) -> String {
   47.30+    hex::encode(&self.0)
   47.31+  }
   47.32+}
   47.33+
   47.34+/// PeerId
   47.35+///
   47.36+/// identifies a unique Peer
   47.37+#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
   47.38+pub struct PeerId {
   47.39+  id: [u8; 32],
   47.40+}
   47.41+
   47.42+impl PeerId {
   47.43+  pub fn new() -> Self {
   47.44+    Self::default()
   47.45+  }
   47.46+
   47.47+  pub fn rand() -> Self {
   47.48+    let pd = rand::thread_rng().gen::<[u8; 32]>();
   47.49+    Self { id: pd }
   47.50+  }
   47.51+
   47.52+  pub fn from_bytes(data: &[u8]) -> Self {
   47.53+    let pd = blake3::hash(data);
   47.54+    let hash = pd.as_bytes();
   47.55+    Self { id: *hash }
   47.56+  }
   47.57+}
   47.58+
   47.59+impl Default for PeerId {
   47.60+  fn default() -> Self {
   47.61+    PeerId { id: [0; 32] }
   47.62+  }
   47.63+}
   47.64+
   47.65+/// Identity trait
   47.66+///
   47.67+/// Defines Identity-related behaviors
   47.68+pub trait Identity: Sized {
   47.69+  /// return the hashed bytes of an ObjectId
   47.70+  fn id(&self) -> Id;
   47.71+}
   47.72+
   47.73+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
   47.74+pub struct ObjectId(u128);
   47.75+
   47.76+pub struct NameSpace {
   47.77+  pub prefix: Option<String>,
   47.78+  pub capacity: u64,
   47.79+  pub route: Vec<Id>,
   47.80+  pub key: Option<Id>,
   47.81+}
   47.82+
   47.83+pub struct Domain {
   47.84+  pub ns: NameSpace,
   47.85+  pub id: Id,
   47.86+}
   47.87+
   47.88+impl From<Uuid> for ObjectId {
   47.89+  fn from(uuid: Uuid) -> Self {
   47.90+    ObjectId(uuid.as_u128())
   47.91+  }
   47.92+}
   47.93+
   47.94+impl From<Ulid> for ObjectId {
   47.95+  fn from(ulid: Ulid) -> Self {
   47.96+    ObjectId(u128::from(ulid))
   47.97+  }
   47.98+}
   47.99+
  47.100+impl From<u128> for ObjectId {
  47.101+  fn from(src: u128) -> Self {
  47.102+    ObjectId(src)
  47.103+  }
  47.104+}
  47.105+
  47.106+impl FromStr for ObjectId {
  47.107+  type Err = ();
  47.108+  fn from_str(input: &str) -> std::result::Result<ObjectId, Self::Err> {
  47.109+    match input {
  47.110+      i => Ok(ObjectId(u128::from(Ulid::from_str(i).unwrap()))),
  47.111+    }
  47.112+  }
  47.113+}
  47.114+
  47.115+impl fmt::Display for ObjectId {
  47.116+  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  47.117+    match *self {
  47.118+      ObjectId(i) => {
  47.119+        write!(f, "{}", Ulid::from(i))
  47.120+      }
  47.121+    }
  47.122+  }
  47.123+}
    48.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2+++ b/src/crates/obj/src/lib.rs	Sat Jun 03 22:48:46 2023 -0400
    48.3@@ -0,0 +1,149 @@
    48.4+//! obj/src/lib.rs --- Objective type library
    48.5+#![feature(associated_type_bounds)]
    48.6+mod err;
    48.7+pub use err::{Error, Result};
    48.8+mod types;
    48.9+pub use types::*;
   48.10+pub mod id;
   48.11+pub mod auth;
   48.12+pub mod hash;
   48.13+pub mod network;
   48.14+pub mod database;
   48.15+pub use bincode;
   48.16+pub use ron;
   48.17+use ron::extensions::Extensions;
   48.18+use serde::{de::DeserializeOwned, Deserialize, Serialize};
   48.19+pub use serde_json;
   48.20+use std::collections::{BTreeMap, HashMap};
   48.21+use std::io;
   48.22+
   48.23+/// Objective trait
   48.24+/// Define Object behaviors, implemented by Objects
   48.25+pub trait Objective {
   48.26+  fn encode(&self) -> Result<Vec<u8>>
   48.27+  where
   48.28+    Self: Serialize,
   48.29+  {
   48.30+    Ok(bincode::serialize(self)?)
   48.31+  }
   48.32+
   48.33+  fn encode_into<W>(&self, writer: W) -> Result<()>
   48.34+  where
   48.35+    W: io::Write,
   48.36+    Self: Serialize,
   48.37+  {
   48.38+    Ok(bincode::serialize_into(writer, self)?)
   48.39+  }
   48.40+
   48.41+  fn decode<'a>(bytes: &'a [u8]) -> Result<Self>
   48.42+  where
   48.43+    Self: Deserialize<'a>,
   48.44+  {
   48.45+    Ok(bincode::deserialize(bytes)?)
   48.46+  }
   48.47+
   48.48+  fn decode_from<R>(&self, rdr: R) -> Result<Self>
   48.49+  where
   48.50+    R: io::Read,
   48.51+    Self: DeserializeOwned,
   48.52+  {
   48.53+    Ok(bincode::deserialize_from(rdr)?)
   48.54+  }
   48.55+
   48.56+  fn to_ron_writer<W>(&self, writer: W) -> Result<()>
   48.57+  where
   48.58+    W: io::Write,
   48.59+    Self: Serialize,
   48.60+  {
   48.61+    Ok(ron::ser::to_writer_pretty(
   48.62+      writer,
   48.63+      &self,
   48.64+      ron::ser::PrettyConfig::new()
   48.65+        .indentor("  ".to_owned())
   48.66+        .extensions(Extensions::all()),
   48.67+    )?)
   48.68+  }
   48.69+
   48.70+  fn to_ron_string(&self) -> Result<String>
   48.71+  where
   48.72+    Self: Serialize,
   48.73+  {
   48.74+    Ok(ron::ser::to_string_pretty(
   48.75+      &self,
   48.76+      ron::ser::PrettyConfig::new().indentor("  ".to_owned()),
   48.77+    )?)
   48.78+  }
   48.79+
   48.80+  fn from_ron_reader<R>(&self, mut rdr: R) -> Result<Self>
   48.81+  where
   48.82+    R: io::Read,
   48.83+    Self: DeserializeOwned,
   48.84+  {
   48.85+    let mut bytes = Vec::new();
   48.86+    rdr.read_to_end(&mut bytes)?;
   48.87+    Ok(ron::de::from_bytes(&bytes)?)
   48.88+  }
   48.89+
   48.90+  fn from_ron_str<'a>(s: &'a str) -> Result<Self>
   48.91+  where
   48.92+    Self: Deserialize<'a>,
   48.93+  {
   48.94+    Ok(ron::de::from_bytes(s.as_bytes())?)
   48.95+  }
   48.96+
   48.97+  fn to_json_writer<W>(&self, writer: W) -> Result<()>
   48.98+  where
   48.99+    W: io::Write,
  48.100+    Self: Serialize,
  48.101+  {
  48.102+    //    let formatter = serde_json::ser::PrettyFormatter::with_indent(b"  ");
  48.103+    Ok(serde_json::ser::to_writer_pretty(writer, &self)?)
  48.104+  }
  48.105+
  48.106+  fn to_json_string(&self) -> Result<String>
  48.107+  where
  48.108+    Self: Serialize,
  48.109+  {
  48.110+    Ok(serde_json::ser::to_string_pretty(&self)?)
  48.111+  }
  48.112+
  48.113+  fn from_json_reader<R>(&self, mut rdr: R) -> Result<Self>
  48.114+  where
  48.115+    R: io::Read,
  48.116+    Self: DeserializeOwned,
  48.117+  {
  48.118+    let mut bytes = Vec::new();
  48.119+    rdr.read_to_end(&mut bytes)?;
  48.120+    Ok(serde_json::de::from_slice(&bytes)?)
  48.121+  }
  48.122+
  48.123+  fn from_json_str<'a>(s: &'a str) -> Result<Self>
  48.124+  where
  48.125+    Self: Deserialize<'a>,
  48.126+  {
  48.127+    Ok(serde_json::de::from_slice(s.as_bytes())?)
  48.128+  }
  48.129+}
  48.130+
  48.131+impl<T> Objective for Vec<T> {}
  48.132+impl<K, V> Objective for HashMap<K, V> {}
  48.133+impl<K, V> Objective for BTreeMap<K, V> {}
  48.134+impl Objective for std::path::PathBuf {}
  48.135+impl Objective for std::path::Path {}
  48.136+impl Objective for std::string::String {}
  48.137+impl Objective for std::any::TypeId {}
  48.138+impl Objective for u8 {}
  48.139+impl Objective for u16 {}
  48.140+impl Objective for u32 {}
  48.141+impl Objective for u64 {}
  48.142+impl Objective for u128 {}
  48.143+impl Objective for i8 {}
  48.144+impl Objective for i16 {}
  48.145+impl Objective for i32 {}
  48.146+impl Objective for i64 {}
  48.147+impl Objective for i128 {}
  48.148+impl Objective for isize {}
  48.149+impl Objective for usize {}
  48.150+impl Objective for f32 {}
  48.151+impl Objective for f64 {}
  48.152+
    49.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2+++ b/src/crates/obj/src/network.rs	Sat Jun 03 22:48:46 2023 -0400
    49.3@@ -0,0 +1,59 @@
    49.4+//! cfg::config::network
    49.5+//!
    49.6+//! Network configuration primitives
    49.7+use serde::{Deserialize, Serialize};
    49.8+use std::{fmt, net::SocketAddr};
    49.9+
   49.10+/// Network configuration
   49.11+#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone)]
   49.12+pub struct NetworkConfig {
   49.13+  /// a socket to bind
   49.14+  pub socket: SocketAddr,
   49.15+  /// a proxy to forward packets from
   49.16+  pub proxy: Option<SocketAddr>,
   49.17+  /// tunnel to use
   49.18+  pub tunnel: Option<String>,
   49.19+  /// network engine to attach
   49.20+  pub engine: EngineType,
   49.21+  /// peers to register AOT
   49.22+  pub peers: Option<Vec<SocketAddr>>,
   49.23+}
   49.24+
   49.25+impl Default for NetworkConfig {
   49.26+  fn default() -> Self {
   49.27+    NetworkConfig {
   49.28+      socket: "127.0.0.1:0".parse().unwrap(),
   49.29+      proxy: None,
   49.30+      tunnel: None,
   49.31+      engine: EngineType::default(),
   49.32+      peers: None,
   49.33+    }
   49.34+  }
   49.35+}
   49.36+
   49.37+#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Clone)]
   49.38+pub enum EngineType {
   49.39+  Quic,
   49.40+  Http,
   49.41+  Dns,
   49.42+  Ssh,
   49.43+  Uds,
   49.44+}
   49.45+
   49.46+impl Default for EngineType {
   49.47+  fn default() -> Self {
   49.48+    Self::Http
   49.49+  }
   49.50+}
   49.51+
   49.52+impl std::fmt::Display for EngineType {
   49.53+  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
   49.54+    match self {
   49.55+      EngineType::Quic => write!(f, "quic"),
   49.56+      EngineType::Http => write!(f, "http"),
   49.57+      EngineType::Dns => write!(f, "dns"),
   49.58+      EngineType::Ssh => write!(f, "ssh"),
   49.59+      EngineType::Uds => write!(f, "uds"),
   49.60+    }
   49.61+  }
   49.62+}
    50.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2+++ b/src/crates/obj/src/types.rs	Sat Jun 03 22:48:46 2023 -0400
    50.3@@ -0,0 +1,70 @@
    50.4+//! obj/src/types.rs --- OBJ type descriptions used by our demo
    50.5+use crate::{Deserialize, Objective, Result, Serialize};
    50.6+use std::collections::HashMap;
    50.7+
    50.8+/// APPLICATION TYPES
    50.9+#[derive(Serialize,Deserialize,Default)]
   50.10+pub enum Service {
   50.11+  Weather,
   50.12+  Stocks,
   50.13+  Dynamic(Vec<Service>),
   50.14+  Custom(CustomService),
   50.15+  #[default]
   50.16+  Bench,
   50.17+}
   50.18+
   50.19+impl Objective for Service {}
   50.20+
   50.21+impl From<&str> for Service {
   50.22+  fn from(value: &str) -> Self {
   50.23+    match value {
   50.24+      "weather" => Service::Weather,
   50.25+      "stocks" => Service::Stocks,
   50.26+      "bench" => Service::Bench,
   50.27+      s => {
   50.28+        if s.contains(",") {
   50.29+          let x = s.split(",");
   50.30+          Service::Dynamic(
   50.31+            x.map(|y| Service::Custom(y.into()))
   50.32+              .collect::<Vec<Service>>(),
   50.33+          )
   50.34+        } else {
   50.35+          Service::Custom(s.into())
   50.36+        }
   50.37+      }
   50.38+    }
   50.39+  }
   50.40+}
   50.41+
   50.42+#[derive(Serialize,Deserialize,Default)]
   50.43+pub struct CustomService {
   50.44+  name: String,
   50.45+  registry: HashMap<String,Vec<u8>>,
   50.46+}
   50.47+
   50.48+impl Objective for CustomService {}
   50.49+impl From<CustomService> for Service {
   50.50+  fn from(value: CustomService) -> Self {
   50.51+    Service::Custom(value)
   50.52+  }
   50.53+}
   50.54+impl From<&str> for CustomService {
   50.55+  fn from(value: &str) -> Self {
   50.56+    let name = value.to_owned();
   50.57+    let registry = HashMap::new();
   50.58+    CustomService { name, registry }
   50.59+  }
   50.60+}
   50.61+
   50.62+#[derive(Serialize, Deserialize,Default)]
   50.63+pub struct Complex<X: Objective> {
   50.64+  data: X,
   50.65+  stack: Vec<u8>,
   50.66+  registry: HashMap<String,Vec<u8>>,
   50.67+}
   50.68+
   50.69+impl Objective for Complex<Service> {}
   50.70+
   50.71+pub fn generate_complex() -> Result<Complex<Service>> {
   50.72+  Ok(Complex::<Service>::from_json_str("hi")?)
   50.73+}
    51.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2+++ b/src/crates/ui/Cargo.toml	Sat Jun 03 22:48:46 2023 -0400
    51.3@@ -0,0 +1,22 @@
    51.4+[package]
    51.5+name = "ui"
    51.6+version = "0.1.0"
    51.7+edition = "2021"
    51.8+build = "build.rs"
    51.9+[lib]
   51.10+path = "lib.rs"
   51.11+crate-type = ["rlib","cdylib"]
   51.12+[[bin]]
   51.13+name = "demo-ui"
   51.14+path = "main.rs"
   51.15+[build-dependencies]
   51.16+slint-build = "1.0.2"
   51.17+[dependencies]
   51.18+obj = {version = "0.1.0",path = "../obj"}
   51.19+env_logger = "0.10.0"
   51.20+log = "0.4.17"
   51.21+slint = "1.0.2"
   51.22+[target.'cfg(target_arch = "wasm32")'.dependencies]
   51.23+wasm-bindgen = { version = "0.2" }
   51.24+web-sys = { version = "0.3", features=["console"] }
   51.25+console_error_panic_hook = "0.1.5"
    52.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2+++ b/src/crates/ui/build.rs	Sat Jun 03 22:48:46 2023 -0400
    52.3@@ -0,0 +1,3 @@
    52.4+fn main() {
    52.5+    slint_build::compile("ui.slint").unwrap();
    52.6+}
    53.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2+++ b/src/crates/ui/config.slint	Sat Jun 03 22:48:46 2023 -0400
    53.3@@ -0,0 +1,3 @@
    53.4+export global UiConfig  {
    53.5+    in property<bool> widgets-disabled: false;
    53.6+}
    53.7\ No newline at end of file
    54.1Binary file src/crates/ui/img/ayo.jpeg has changed
    55.1Binary file src/crates/ui/img/treez.png has changed
    56.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2+++ b/src/crates/ui/index.html	Sat Jun 03 22:48:46 2023 -0400
    56.3@@ -0,0 +1,9 @@
    56.4+<html>
    56.5+  <body>
    56.6+    <canvas id="canvas">>/canvas>
    56.7+    <script type="module">
    56.8+      import init from './pkg/ui.js';
    56.9+      init();
   56.10+    </script>
   56.11+  </body>
   56.12+</html>
    57.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2+++ b/src/crates/ui/lib.rs	Sat Jun 03 22:48:46 2023 -0400
    57.3@@ -0,0 +1,69 @@
    57.4+#![deny(unsafe_code)]
    57.5+
    57.6+#[cfg(target_arch = "wasm32")]
    57.7+use wasm_bindgen::prelude::*;
    57.8+
    57.9+slint::include_modules!();
   57.10+
   57.11+use std::rc::Rc;
   57.12+
   57.13+use slint::{Model, StandardListViewItem, VecModel};
   57.14+
   57.15+#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
   57.16+pub fn run() {
   57.17+    // This provides better error messages in debug mode.
   57.18+    // It's disabled in release mode so it doesn't bloat up the file size.
   57.19+    #[cfg(all(debug_assertions, target_arch = "wasm32"))]
   57.20+    console_error_panic_hook::set_once();
   57.21+
   57.22+    let app = App::new().unwrap();
   57.23+
   57.24+    let row_data: Rc<VecModel<slint::ModelRc<StandardListViewItem>>> = Rc::new(VecModel::default());
   57.25+
   57.26+    for r in 1..101 {
   57.27+        let items = Rc::new(VecModel::default());
   57.28+
   57.29+        for c in 1..5 {
   57.30+            items.push(slint::format!("Item {r}.{c}").into());
   57.31+        }
   57.32+
   57.33+        row_data.push(items.into());
   57.34+    }
   57.35+
   57.36+    app.global::<TableViewPageAdapter>().set_row_data(row_data.clone().into());
   57.37+
   57.38+    app.global::<TableViewPageAdapter>().on_sort_ascending({
   57.39+        let app_weak = app.as_weak();
   57.40+        let row_data = row_data.clone();
   57.41+        move |index| {
   57.42+            let row_data = row_data.clone();
   57.43+
   57.44+            let sort_model = Rc::new(row_data.sort_by(move |r_a, r_b| {
   57.45+                let c_a = r_a.row_data(index as usize).unwrap();
   57.46+                let c_b = r_b.row_data(index as usize).unwrap();
   57.47+
   57.48+                c_a.text.cmp(&c_b.text)
   57.49+            }));
   57.50+
   57.51+            app_weak.unwrap().global::<TableViewPageAdapter>().set_row_data(sort_model.into());
   57.52+        }
   57.53+    });
   57.54+
   57.55+    app.global::<TableViewPageAdapter>().on_sort_descending({
   57.56+        let app_weak = app.as_weak();
   57.57+        move |index| {
   57.58+            let row_data = row_data.clone();
   57.59+
   57.60+            let sort_model = Rc::new(row_data.sort_by(move |r_a, r_b| {
   57.61+                let c_a = r_a.row_data(index as usize).unwrap();
   57.62+                let c_b = r_b.row_data(index as usize).unwrap();
   57.63+
   57.64+                c_b.text.cmp(&c_a.text)
   57.65+            }));
   57.66+
   57.67+            app_weak.unwrap().global::<TableViewPageAdapter>().set_row_data(sort_model.into());
   57.68+        }
   57.69+    });
   57.70+
   57.71+    app.run().unwrap();
   57.72+}
    58.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2+++ b/src/crates/ui/main.rs	Sat Jun 03 22:48:46 2023 -0400
    58.3@@ -0,0 +1,4 @@
    58.4+use ui::run;
    58.5+fn main() {
    58.6+  run();
    58.7+}
    59.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2+++ b/src/crates/ui/pages.slint	Sat Jun 03 22:48:46 2023 -0400
    59.3@@ -0,0 +1,7 @@
    59.4+import { AboutPage } from "pages/about.slint";
    59.5+import { ControlsPage } from "pages/controls.slint";
    59.6+import { ListViewPage } from "pages/list_view.slint";
    59.7+import { TableViewPage, TableViewPageAdapter } from "pages/table_view.slint";
    59.8+import { TextEditPage } from "pages/text_edit.slint";
    59.9+
   59.10+export { AboutPage, ControlsPage, ListViewPage, TextEditPage, TableViewPage, TableViewPageAdapter }
   59.11\ No newline at end of file
    60.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2+++ b/src/crates/ui/pages/about.slint	Sat Jun 03 22:48:46 2023 -0400
    60.3@@ -0,0 +1,10 @@
    60.4+import { AboutSlint } from "std-widgets.slint";
    60.5+import { UiConfig } from "../config.slint";
    60.6+import { Page } from "page.slint";
    60.7+
    60.8+export component AboutPage inherits Page {
    60.9+    title: "About";
   60.10+    description: "Are you curious now? Check out the docs and gettings start from the Github repository and the website https://slint-ui.com and try it yourself.";
   60.11+
   60.12+    AboutSlint {}
   60.13+}
   60.14\ No newline at end of file
    61.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2+++ b/src/crates/ui/pages/controls.slint	Sat Jun 03 22:48:46 2023 -0400
    61.3@@ -0,0 +1,145 @@
    61.4+import { Button, GroupBox, SpinBox, ComboBox, CheckBox, LineEdit, TabWidget, VerticalBox, HorizontalBox,
    61.5+    Slider, SpinBox } from "std-widgets.slint";
    61.6+import { UiConfig } from "../config.slint";
    61.7+import { Page } from "page.slint";
    61.8+
    61.9+export component ControlsPage inherits Page {
   61.10+    title: "Controls";
   61.11+    description: "This page gives an overview of the default widget set provided by Slint. The widgets are available in different styles native, fluent-(dark/light) and material-(dark/light). The widgets can be imported from \"std-widgets.slint\".";
   61.12+
   61.13+    GroupBox {
   61.14+        vertical-stretch: 0;
   61.15+        title: "Buttons";
   61.16+
   61.17+        HorizontalLayout {
   61.18+            spacing: 8px;
   61.19+            alignment: start;
   61.20+
   61.21+            Button {
   61.22+                text: "Regular Button";
   61.23+                enabled: !UiConfig.widgets-disabled;
   61.24+            }
   61.25+
   61.26+            Button {
   61.27+                text: "Button with Icon";
   61.28+                icon: @image-url("../img/treez.png");
   61.29+                enabled: !UiConfig.widgets-disabled;
   61.30+            }
   61.31+
   61.32+            Button {
   61.33+                checkable: true;
   61.34+                text: self.checked ? "ON" : "OFF";
   61.35+                enabled: !UiConfig.widgets-disabled;
   61.36+            }
   61.37+        }
   61.38+    }
   61.39+
   61.40+    GroupBox {
   61.41+        title: "CheckBox - SpinBox - ComboBox";
   61.42+        vertical-stretch: 0;
   61.43+
   61.44+        HorizontalBox {
   61.45+            alignment: start;
   61.46+            checkbox := CheckBox {
   61.47+                text: checkbox.checked ? "(checked)" : "(unchecked)";
   61.48+                checked: true;
   61.49+                enabled: !UiConfig.widgets-disabled;
   61.50+            }
   61.51+
   61.52+
   61.53+        SpinBox {
   61.54+            vertical-stretch: 0;
   61.55+            value: 42;
   61.56+            enabled: !UiConfig.widgets-disabled;
   61.57+        }
   61.58+
   61.59+            ComboBox {
   61.60+                model: ["Select Something", "From this", "Combobox"];
   61.61+                enabled: !UiConfig.widgets-disabled;
   61.62+            }
   61.63+        }
   61.64+
   61.65+
   61.66+    }
   61.67+
   61.68+    GroupBox {
   61.69+        title: "LineEdit";
   61.70+        vertical-stretch: 0;
   61.71+
   61.72+        LineEdit {
   61.73+            placeholder-text: "Enter some text";
   61.74+            enabled: !UiConfig.widgets-disabled;
   61.75+        }
   61.76+    }
   61.77+
   61.78+    GroupBox {
   61.79+        title: "Slider";
   61.80+        vertical-stretch: 0;
   61.81+
   61.82+        Slider {
   61.83+            min-width: 160px;
   61.84+            minimum: -100;
   61.85+            maximum: 100;
   61.86+            value: 42;
   61.87+            enabled: !UiConfig.widgets-disabled;
   61.88+        }
   61.89+    }
   61.90+
   61.91+    GroupBox {
   61.92+        title: "TabWidget";
   61.93+
   61.94+        TabWidget {
   61.95+            Tab {
   61.96+                title: "Tab 1";
   61.97+
   61.98+                VerticalBox {
   61.99+                    alignment: start;
  61.100+
  61.101+                    GroupBox {
  61.102+                        title: "Content of tab 1";
  61.103+
  61.104+                        HorizontalBox {
  61.105+                            alignment: start;
  61.106+
  61.107+                            Button {
  61.108+                                text: "Click me";
  61.109+                                enabled: !UiConfig.widgets-disabled;
  61.110+                            }
  61.111+                        }
  61.112+                    }
  61.113+                }
  61.114+            }
  61.115+
  61.116+            Tab {
  61.117+                title: "Tab 2";
  61.118+
  61.119+                VerticalBox {
  61.120+                    alignment: start;
  61.121+
  61.122+                    GroupBox {
  61.123+                        title: "Content of tab 2";
  61.124+
  61.125+                        VerticalBox {
  61.126+                            alignment: start;
  61.127+
  61.128+                            CheckBox {
  61.129+                                text: "Check me";
  61.130+                                enabled: !UiConfig.widgets-disabled;
  61.131+                            }
  61.132+                        }
  61.133+                    }
  61.134+                }
  61.135+            }
  61.136+
  61.137+            Tab {
  61.138+                title: "Tab 3";
  61.139+
  61.140+                VerticalBox {
  61.141+                    Text {
  61.142+                        text: "Content of tab 3";
  61.143+                    }
  61.144+                }
  61.145+            }
  61.146+        }
  61.147+    }
  61.148+}
  61.149\ No newline at end of file
    62.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2+++ b/src/crates/ui/pages/list_view.slint	Sat Jun 03 22:48:46 2023 -0400
    62.3@@ -0,0 +1,45 @@
    62.4+import { HorizontalBox, VerticalBox, ListView, StandardListView, GroupBox } from "std-widgets.slint";
    62.5+import { UiConfig } from "../config.slint";
    62.6+import { Page } from "page.slint";
    62.7+
    62.8+export component ListViewPage inherits Page {
    62.9+    title: "ListView";
   62.10+    description: "ListViews can be used to display a list of elements. The StandardListBox is like the default ListView just with a default text based definition of the visual items. Both can be imported from \"std-widgets.slint\"";
   62.11+
   62.12+    HorizontalBox {
   62.13+        vertical-stretch: 1;
   62.14+        GroupBox {
   62.15+            title: "ListView";
   62.16+
   62.17+            ListView {
   62.18+                vertical-stretch: 0;
   62.19+                for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] : HorizontalBox {
   62.20+                   Image {
   62.21+                        width: 24px;
   62.22+                        source: @image-url("../img/ayo.jpeg");
   62.23+                   }
   62.24+                   Text {
   62.25+                        text: "Item " + i;
   62.26+                   }
   62.27+                }
   62.28+            }
   62.29+        }
   62.30+
   62.31+        GroupBox {
   62.32+            title: "StandardListView";
   62.33+            vertical-stretch: 0;
   62.34+
   62.35+            StandardListView {
   62.36+                model: [
   62.37+                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   62.38+                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   62.39+                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   62.40+                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   62.41+                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   62.42+                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   62.43+                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
   62.44+                ];
   62.45+            }
   62.46+        }
   62.47+    }
   62.48+}
   62.49\ No newline at end of file
    63.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2+++ b/src/crates/ui/pages/page.slint	Sat Jun 03 22:48:46 2023 -0400
    63.3@@ -0,0 +1,27 @@
    63.4+import { CheckBox, GridBox, ListView, ScrollView, VerticalBox } from "std-widgets.slint";
    63.5+
    63.6+import { UiConfig } from "../config.slint";
    63.7+
    63.8+export component Page inherits VerticalBox {
    63.9+    in property<string> title: "title";
   63.10+    in property<string> description: "description";
   63.11+
   63.12+    HorizontalLayout {
   63.13+        height: 24px;
   63.14+        Text {
   63.15+            font-size: 20px;
   63.16+            text <=> root.title;
   63.17+        }
   63.18+
   63.19+        // Spacer
   63.20+        Rectangle {}
   63.21+
   63.22+        CheckBox {
   63.23+            horizontal-stretch: 0;
   63.24+            text: "Disable widgets";
   63.25+            checked <=> UiConfig.widgets-disabled;
   63.26+        }
   63.27+    }
   63.28+
   63.29+    @children
   63.30+}
   63.31\ No newline at end of file
    64.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2+++ b/src/crates/ui/pages/table_view.slint	Sat Jun 03 22:48:46 2023 -0400
    64.3@@ -0,0 +1,48 @@
    64.4+import { HorizontalBox, VerticalBox, StandardTableView, GroupBox} from "std-widgets.slint";
    64.5+import { UiConfig } from "../config.slint";
    64.6+import { Page } from "page.slint";
    64.7+
    64.8+export global TableViewPageAdapter  {
    64.9+    callback sort_ascending(int);
   64.10+    callback sort_descending(int);
   64.11+    in property <[[StandardListViewItem]]> row_data: [
   64.12+        [ { text: "Item 1.1" }, { text: "Item 1.2" }, { text: "Item 1.3" }, { text: "Item 1.4" }, ],
   64.13+        [ { text: "Item 2.1" }, { text: "Item 2.2" }, { text: "Item 2.3" }, { text: "Item 2.4" }, ],
   64.14+        [ { text: "Item 3.1" }, { text: "Item 3.2" }, { text: "Item 3.3" }, { text: "Item 3.4" }, ],
   64.15+        [ { text: "Item 4.1" }, { text: "Item 4.2" }, { text: "Item 4.3" }, { text: "Item 4.4" }, ],
   64.16+        [ { text: "Item 5.1" }, { text: "Item 5.2" }, { text: "Item 5.3" }, { text: "Item 5.4" }, ],
   64.17+        [ { text: "Item 6.1" }, { text: "Item 6.2" }, { text: "Item 6.3" }, { text: "Item 6.4" }, ],
   64.18+    ];
   64.19+}
   64.20+
   64.21+export component TableViewPage inherits Page {
   64.22+    title: "TableView";
   64.23+    description: "StandardTableView can be used to display a list of text elements in columns and rows. It can be imported from \"std-widgets.slint\"";
   64.24+
   64.25+    HorizontalBox {
   64.26+        vertical-stretch: 1;
   64.27+
   64.28+        GroupBox {
   64.29+            title: "StandardTableView";
   64.30+            vertical-stretch: 0;
   64.31+
   64.32+            StandardTableView {
   64.33+                sort-ascending(index) => {
   64.34+                    TableViewPageAdapter.sort_ascending(index);
   64.35+                }
   64.36+
   64.37+                sort-descending(index) => {
   64.38+                    TableViewPageAdapter.sort-descending(index);
   64.39+                }
   64.40+
   64.41+                columns: [
   64.42+                    { title: "Header 1" },
   64.43+                    { title: "Header 2" },
   64.44+                    { title: "Header 3" },
   64.45+                    { title: "Header 4" },
   64.46+                ];
   64.47+                rows: TableViewPageAdapter.row_data;
   64.48+            }
   64.49+        }
   64.50+    }
   64.51+}
   64.52\ No newline at end of file
    65.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2+++ b/src/crates/ui/pages/text_edit.slint	Sat Jun 03 22:48:46 2023 -0400
    65.3@@ -0,0 +1,32 @@
    65.4+import { HorizontalBox, GroupBox, TextEdit } from "std-widgets.slint";
    65.5+import { UiConfig } from "../config.slint";
    65.6+import { Page } from "page.slint";
    65.7+
    65.8+export component TextEditPage inherits Page {
    65.9+    title: "TextEdit";
   65.10+    description: "Similar to LineEdit, but can be used to enter several lines of text. The widget can be imported from \"std-widgets.slint\".";
   65.11+
   65.12+    HorizontalBox {
   65.13+        GroupBox {
   65.14+            vertical-stretch: 0;
   65.15+            title: "Word-Wrap";
   65.16+            te1 := TextEdit {
   65.17+                min-width: 200px;
   65.18+                text: "This is our TextEdit widget, which allows for editing text that spans over multiple paragraphs.\nFor example this line starts in a new paragraph.\n\nWhen the amount of lines - due to wrapping and number of paragraphs - exceeds the available vertical height, a vertical scrollbar is shown that allows scrolling.\nYou may want to enter a bit of text here then in order to make them visible.";
   65.19+                wrap: word-wrap;
   65.20+                enabled: !UiConfig.widgets-disabled;
   65.21+            }
   65.22+        }
   65.23+
   65.24+        GroupBox {
   65.25+            title: "No-Wrap";
   65.26+            vertical-stretch: 0;
   65.27+            te2 := TextEdit {
   65.28+                min-width: 200px;
   65.29+                text <=> te1.text;
   65.30+                wrap: no-wrap;
   65.31+                enabled: !UiConfig.widgets-disabled;
   65.32+            }
   65.33+        }
   65.34+    }
   65.35+}
   65.36\ No newline at end of file
    66.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2+++ b/src/crates/ui/sidebar.slint	Sat Jun 03 22:48:46 2023 -0400
    66.3@@ -0,0 +1,127 @@
    66.4+import { StyleMetrics } from "std-widgets.slint";
    66.5+
    66.6+component SideBarItem inherits Rectangle {
    66.7+    callback clicked <=> touch.clicked;
    66.8+    in-out property<string> text <=> label.text;
    66.9+    in property<bool> selected;
   66.10+    in property<bool> has-focus;
   66.11+
   66.12+    min-height: l.preferred-height;
   66.13+
   66.14+    state := Rectangle {
   66.15+        opacity: 0;
   66.16+        background: StyleMetrics.window-background;
   66.17+
   66.18+        animate opacity { duration: 150ms; }
   66.19+    }
   66.20+
   66.21+    l := HorizontalLayout {
   66.22+        y: (parent.height - self.height) / 2;
   66.23+        padding: StyleMetrics.layout-padding;
   66.24+        spacing: 0px;
   66.25+
   66.26+        label := Text {
   66.27+            color: StyleMetrics.default-text-color;
   66.28+            vertical-alignment: center;
   66.29+         }
   66.30+    }
   66.31+
   66.32+    touch := TouchArea {
   66.33+        width: 100%;
   66.34+        height: 100%;
   66.35+    }
   66.36+
   66.37+    states [
   66.38+        pressed when touch.pressed : {
   66.39+            state.opacity: 0.8;
   66.40+        }
   66.41+        hover when touch.has-hover : {
   66.42+            state.opacity: 0.6;
   66.43+        }
   66.44+        selected when root.selected : {
   66.45+            state.opacity: 1;
   66.46+        }
   66.47+        focused when root.has-focus : {
   66.48+            state.opacity: 0.8;
   66.49+        }
   66.50+    ]
   66.51+}
   66.52+
   66.53+export component SideBar inherits Rectangle {
   66.54+    in property<[string]> model: [];
   66.55+    out property<int> current-item: 0;
   66.56+    in property<string> title <=> label.text;
   66.57+    out property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
   66.58+    width: 180px;
   66.59+
   66.60+    forward-focus: fs;
   66.61+
   66.62+    accessible-role: tab;
   66.63+    accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-item;
   66.64+
   66.65+    Rectangle {
   66.66+        background: StyleMetrics.window-background.darker(0.2);
   66.67+
   66.68+        fs := FocusScope {
   66.69+            x:0;
   66.70+            width: 0px; // Do not react on clicks
   66.71+            property<int> focused-tab: 0;
   66.72+
   66.73+            key-pressed(event) => {
   66.74+                if (event.text == "\n") {
   66.75+                     root.current-item = root.current-focused;
   66.76+                     return accept;
   66.77+                }
   66.78+                if (event.text == Key.UpArrow) {
   66.79+                     self.focused-tab = Math.max(self.focused-tab - 1,  0);
   66.80+                     return accept;
   66.81+                }
   66.82+                if (event.text == Key.DownArrow) {
   66.83+                     self.focused-tab = Math.min(self.focused-tab + 1, root.model.length - 1);
   66.84+                     return accept;
   66.85+                }
   66.86+                return reject;
   66.87+            }
   66.88+
   66.89+            key-released(event) => {
   66.90+                if (event.text == " ") {
   66.91+                     root.current-item = root.current-focused;
   66.92+                     return accept;
   66.93+                }
   66.94+                return reject;
   66.95+            }
   66.96+        }
   66.97+    }
   66.98+
   66.99+    VerticalLayout {
  66.100+        padding-top: StyleMetrics.layout-padding;
  66.101+        padding-bottom: StyleMetrics.layout-padding;
  66.102+        spacing: StyleMetrics.layout-spacing;
  66.103+        alignment: start;
  66.104+
  66.105+        label := Text {
  66.106+            font-size: 16px;
  66.107+            horizontal-alignment: center;
  66.108+        }
  66.109+
  66.110+        navigation := VerticalLayout {
  66.111+            alignment: start;
  66.112+            vertical-stretch: 0;
  66.113+            for item[index] in root.model : SideBarItem {
  66.114+                has-focus: index == root.current-focused;
  66.115+                text: item;
  66.116+                selected: index == root.current-item;
  66.117+                clicked => { root.current-item = index; }
  66.118+            }
  66.119+        }
  66.120+
  66.121+        VerticalLayout {
  66.122+            bottom := VerticalLayout {
  66.123+                padding-left: StyleMetrics.layout-padding;
  66.124+                padding-right: StyleMetrics.layout-padding;
  66.125+
  66.126+                @children
  66.127+             }
  66.128+        }
  66.129+    }
  66.130+}
  66.131\ No newline at end of file
    67.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2+++ b/src/crates/ui/ui.slint	Sat Jun 03 22:48:46 2023 -0400
    67.3@@ -0,0 +1,20 @@
    67.4+import {CheckBox, StandardListView, StyleMetrics} from "std-widgets.slint";
    67.5+import {AboutPage, ControlsPage, ListViewPage, TableViewPage, TableViewPageAdapter, TextEditPage} from "pages.slint";
    67.6+import {UiConfig} from "config.slint";
    67.7+import {SideBar} from "sidebar.slint";
    67.8+export {TableViewPageAdapter}
    67.9+export component App inherits Window {
   67.10+  title: "Demo";
   67.11+  icon: @image-url("img/treez.png");
   67.12+  HorizontalLayout {
   67.13+    side-bar := SideBar {
   67.14+      title: "Demo";
   67.15+      model: ["Controls", "ListView", "TableView", "TextEdit", "About"];
   67.16+    }
   67.17+    if(side-bar.current-item == 0) : ControlsPage {}
   67.18+    if(side-bar.current-item == 1) : ListViewPage {}
   67.19+    if(side-bar.current-item == 2) : TableViewPage {}
   67.20+    if(side-bar.current-item == 3) : TextEditPage {}
   67.21+    if(side-bar.current-item == 4) : AboutPage {}
   67.22+  }
   67.23+}
   67.24\ No newline at end of file
    68.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2+++ b/src/db.lisp	Sat Jun 03 22:48:46 2023 -0400
    68.3@@ -0,0 +1,197 @@
    68.4+(in-package :demo)
    68.5+
    68.6+(define-foreign-library rocksdb
    68.7+  (:win32 "rocksdb")
    68.8+  (t (:default "librocksdb")))
    68.9+
   68.10+(use-foreign-library rocksdb)
   68.11+
   68.12+(defcfun ("rocksdb_options_create" create-options) :pointer)
   68.13+(defcfun ("rocksdb_options_destroy" destroy-options) :void (options :pointer))
   68.14+(defcfun ("rocksdb_options_increase_parallelism" increase-parallelism) :void (opt :pointer) (total-threads :int))
   68.15+(defcfun ("rocksdb_options_optimize_level_style_compaction" optimize-level-style-compaction) :void (opt :pointer) (memtable_memory_budget :uint64))
   68.16+(defcfun ("rocksdb_options_set_create_if_missing" set-create-if-missing) :void (opt :pointer) (val :boolean))
   68.17+
   68.18+(defcfun ("rocksdb_writeoptions_create" create-writeoptions) :pointer)
   68.19+(defcfun ("rocksdb_writeoptions_destroy" destroy-writeoptions) :void (opt :pointer))
   68.20+(defcfun ("rocksdb_readoptions_create" create-readoptions) :pointer)
   68.21+(defcfun ("rocksdb_readoptions_destroy" destroy-readoptions) :void (opt :pointer))
   68.22+
   68.23+(defcfun ("rocksdb_open" open-db*) :pointer (opt :pointer) (name :string) (errptr :pointer))
   68.24+(defcfun ("rocksdb_close" close-db) :void (opt :pointer))
   68.25+(defcfun ("rocksdb_cancel_all_background_work" cancel-all-background-work) :void (db :pointer) (wait :boolean))
   68.26+
   68.27+(defcfun ("rocksdb_put" put*) :void (db :pointer) (options :pointer) (key :pointer) (keylen :unsigned-int) (val :pointer) (vallen :unsigned-int) (errptr :pointer))
   68.28+(defcfun ("rocksdb_get" get*) :pointer (db :pointer) (options :pointer) (key :pointer) (keylen :unsigned-int) (vallen :pointer) (errptr :pointer))
   68.29+
   68.30+(defcfun ("rocksdb_create_iterator" create-iter*) :pointer (db :pointer) (opt :pointer))
   68.31+(defcfun ("rocksdb_iter_destroy" destroy-iter) :void (iter :pointer))
   68.32+(defcfun ("rocksdb_iter_seek_to_first" move-iter-to-first) :void (iter :pointer))
   68.33+(defcfun ("rocksdb_iter_valid" valid-iter-p) :boolean (iter :pointer))
   68.34+(defcfun ("rocksdb_iter_next" move-iter-forward) :void (iter :pointer))
   68.35+(defcfun ("rocksdb_iter_prev" move-iter-backward) :void (iter :pointer))
   68.36+(defcfun ("rocksdb_iter_key" iter-key*) :pointer (iter :pointer) (klen-ptr :pointer))
   68.37+(defcfun ("rocksdb_iter_value" iter-value*) :pointer (iter :pointer) (vlen-ptr :pointer))
   68.38+
   68.39+(define-condition unable-to-open-db (error)
   68.40+  ((db-path :initarg :db-path
   68.41+            :reader db-path)
   68.42+   (error-message :initarg :error-message
   68.43+                  :reader error-message)))
   68.44+
   68.45+(defmethod print-object ((obj unable-to-open-db) stream)
   68.46+  (print-unreadable-object (obj stream :type t :identity t)
   68.47+    (format stream "error-message=~A" (error-message obj))))
   68.48+
   68.49+(define-condition unable-to-put-key-value-to-db (error)
   68.50+  ((db :initarg :db
   68.51+       :reader db)
   68.52+   (key :initarg :key
   68.53+        :reader key)
   68.54+   (val :initarg :val
   68.55+        :reader val)
   68.56+   (error-message :initarg :error-message
   68.57+                  :reader error-message)))
   68.58+
   68.59+(define-condition unable-to-get-value-to-db (error)
   68.60+  ((db :initarg :db
   68.61+       :reader db)
   68.62+   (key :initarg :key
   68.63+        :reader key)
   68.64+   (error-message :initarg :error-message
   68.65+                  :reader error-message)))
   68.66+
   68.67+(defun open-db (db-path &optional opt)
   68.68+  (unless opt
   68.69+    (setq opt (create-options)))
   68.70+  (let ((errptr (foreign-alloc :pointer)))
   68.71+    (setf (mem-ref errptr :pointer) (null-pointer))
   68.72+    (let* ((db-path (if (pathnamep db-path)
   68.73+                        (namestring db-path)
   68.74+                        db-path))
   68.75+           (db (open-db* opt db-path errptr))
   68.76+           (err (mem-ref errptr :pointer)))
   68.77+      (unless (null-pointer-p err)
   68.78+        (error 'unable-to-open-db
   68.79+               :db-path db-path
   68.80+               :error-message (foreign-string-to-lisp err)))
   68.81+      db)))
   68.82+
   68.83+(defmacro clone-octets-to-foreign (lisp-array foreign-array)
   68.84+  (let ((i (gensym)))
   68.85+    `(loop for ,i from 0 below (length ,lisp-array)
   68.86+           do (setf (mem-aref ,foreign-array :unsigned-char ,i)
   68.87+                    (aref ,lisp-array ,i)))))
   68.88+
   68.89+(defmacro clone-octets-from-foreign (foreign-array lisp-array len)
   68.90+  (let ((i (gensym)))
   68.91+    `(loop for ,i from 0 below ,len
   68.92+           do (setf (aref ,lisp-array ,i)
   68.93+                    (mem-aref ,foreign-array :unsigned-char ,i)))))
   68.94+
   68.95+(defun put-kv (db key val &optional opt)
   68.96+  (unless opt
   68.97+    (setq opt (create-writeoptions)))
   68.98+  (with-foreign-objects ((errptr :pointer)
   68.99+                         (key* :unsigned-char (length key))
  68.100+                         (val* :unsigned-char (length val)))
  68.101+    (clone-octets-to-foreign key key*)
  68.102+    (clone-octets-to-foreign val val*)
  68.103+    (setf (mem-ref errptr :pointer) (null-pointer))
  68.104+    (put* db
  68.105+          opt
  68.106+          key*
  68.107+          (length key)
  68.108+          val*
  68.109+          (length val)
  68.110+          errptr)
  68.111+    (let ((err (mem-ref errptr :pointer)))
  68.112+      (unless (null-pointer-p err)
  68.113+        (error 'unable-to-put-key-value-to-db
  68.114+               :db db
  68.115+               :key key
  68.116+               :val val
  68.117+               :error-message (foreign-string-to-lisp err))))))
  68.118+
  68.119+(defun put-kv-str (db key val &optional opt)
  68.120+  (let ((key-octets (babel:string-to-octets key))
  68.121+        (val-octets (babel:string-to-octets val)))
  68.122+    (put-kv db key-octets val-octets opt)))
  68.123+
  68.124+(defun get-kv (db key &optional opt)
  68.125+  (unless opt
  68.126+    (setq opt (create-readoptions)))
  68.127+
  68.128+  (with-foreign-objects ((val-len-ptr :unsigned-int)
  68.129+                         (errptr :pointer)
  68.130+                         (key* :unsigned-char (length key)))
  68.131+    (clone-octets-to-foreign key key*)
  68.132+    (setf (mem-ref errptr :pointer) (null-pointer))
  68.133+    (let ((val (get* db
  68.134+                     opt
  68.135+                     key*
  68.136+                     (length key)
  68.137+                     val-len-ptr
  68.138+                     errptr)))
  68.139+      (let ((err (mem-ref errptr :pointer)))
  68.140+        (unless (null-pointer-p err)
  68.141+          (error 'unable-to-get-value-to-db
  68.142+                 :db db
  68.143+                 :key key
  68.144+                 :error-message (foreign-string-to-lisp err)))
  68.145+        
  68.146+        (unless (null-pointer-p val)
  68.147+          (let* ((val-len (mem-ref val-len-ptr :unsigned-int))
  68.148+                 (val* (make-array val-len
  68.149+                                      :element-type '(unsigned-byte 8))))
  68.150+            (clone-octets-from-foreign val val* val-len)
  68.151+            val*))))))
  68.152+
  68.153+(defun get-kv-str (db key &optional opt)
  68.154+  (let ((key-octets (babel:string-to-octets key)))
  68.155+    (let ((#1=val-octets (get-kv db key-octets opt)))
  68.156+      (when #1#
  68.157+        (babel:octets-to-string #1#)))))
  68.158+
  68.159+(defun create-iter (db &optional opt)
  68.160+  (unless opt
  68.161+    (setq opt (create-readoptions)))
  68.162+  (create-iter* db opt))
  68.163+
  68.164+(defun iter-key (iter)
  68.165+  (with-foreign-objects ((klen-ptr :unsigned-int))
  68.166+    (setf (mem-ref klen-ptr :unsigned-int) 0)
  68.167+    (let* ((key-ptr (iter-key* iter klen-ptr))
  68.168+           (klen (mem-ref klen-ptr :unsigned-int))
  68.169+           (key (make-array klen :element-type '(unsigned-byte 8))))
  68.170+      (clone-octets-from-foreign key-ptr key klen)
  68.171+      key)))
  68.172+
  68.173+(defun iter-key-str (iter)
  68.174+  (let ((#1=key-octets (iter-key iter)))
  68.175+    (when #1#
  68.176+      (babel:octets-to-string #1#))))
  68.177+
  68.178+(defun iter-value (iter)
  68.179+  (with-foreign-objects ((len-ptr :unsigned-int))
  68.180+    (setf (mem-ref len-ptr :unsigned-int) 0)
  68.181+    (let* ((value-ptr (iter-value* iter len-ptr))
  68.182+           (vlen (mem-ref len-ptr :unsigned-int))
  68.183+           (value* (make-array vlen :element-type '(unsigned-byte 8))))
  68.184+      (clone-octets-from-foreign value-ptr value* vlen)
  68.185+      value*)))
  68.186+
  68.187+(defun iter-value-str (iter)
  68.188+  (let ((#1=val-octets (iter-value iter)))
  68.189+    (when #1#
  68.190+      (babel:octets-to-string #1#))))
  68.191+
  68.192+(defmacro with-open-db ((db-var db-path &optional opt) &body body)
  68.193+  `(let ((,db-var (open-db ,db-path ,opt)))
  68.194+     (unwind-protect (progn ,@body)
  68.195+       (close-db ,db-var))))
  68.196+
  68.197+(defmacro with-iter ((iter-var db &optional opt) &body body)
  68.198+  `(let ((,iter-var (create-iter ,db ,opt)))
  68.199+     (unwind-protect (progn ,@body)
  68.200+       (destroy-iter ,iter-var))))
    69.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2+++ b/src/demo.lisp	Sat Jun 03 22:48:46 2023 -0400
    69.3@@ -0,0 +1,45 @@
    69.4+;; demo.lisp
    69.5+(in-package :demo)
    69.6+
    69.7+(defparameter demo-path (merge-pathnames "cl-demo" (uiop:temporary-directory)))
    69.8+
    69.9+(defvar db-path (merge-pathnames "db" demo-path))
   69.10+
   69.11+(defun cli-opts ()
   69.12+  "Returns the top-level CLI options."
   69.13+  (list
   69.14+   (cli:make-option
   69.15+    :string
   69.16+    :description "demo app to run"
   69.17+    :short-name #\x
   69.18+    :long-name "app"
   69.19+    :initial-value "client"
   69.20+    :env-vars '("DEMO_APP")
   69.21+    :key :app)
   69.22+   (cli:make-option
   69.23+    :string
   69.24+    :description "path to config"
   69.25+    :short-name #\c
   69.26+    :long-name "config"
   69.27+    :initial-value "$DEMO_PATH/.fig"
   69.28+    :env-vars '("DEMO_CONFIG"))))
   69.29+
   69.30+(defun cli-handler (cmd)
   69.31+  "Handler for the `demo' command."
   69.32+  (let ((app (cli:getopt cmd :app)))
   69.33+    (format t "running: ~A!~%" app)))
   69.34+
   69.35+(defun cli-cmd ()
   69.36+  "Our demo command."
   69.37+  (cli:make-command
   69.38+   :name "demo"
   69.39+   :description "A collection of demos"
   69.40+   :version "1.0.0"
   69.41+   :authors '("ellis <ellis@rwest.io>")
   69.42+   :license "WTFPL"
   69.43+   :options (cli-opts)
   69.44+   :handler #'cli-handler))
   69.45+
   69.46+(defun main ()
   69.47+  "A demo of some common-lisp functionality."
   69.48+  (cli:run (cli-cmd)))
    70.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2+++ b/src/ffi.lisp	Sat Jun 03 22:48:46 2023 -0400
    70.3@@ -0,0 +1,28 @@
    70.4+(in-package :demo)
    70.5+(defparameter quiche-lib-path #p"./ffi/libquiche.dylib")
    70.6+;;(defparameter rocksdb-lib-path #p"./ffi/librocksdb.dylib")
    70.7+(defparameter demo-lib-path (find-rs-cdylib "libdemo.dylib"))
    70.8+(defmacro find-rs-cdylib (name &optional debug)
    70.9+  "Find the rust dll specified by NAME."
   70.10+  (cond
   70.11+    ((uiop:directory-exists-p (merge-pathnames *cargo-target* "release"))
   70.12+     `,(mkstr "./target/release/" name))
   70.13+    ((uiop:directory-exists-p  (merge-pathnames *cargo-target* "debug"))
   70.14+     `,(mkstr "./target/debug/" name))
   70.15+    (t `(progn
   70.16+	 ,(uiop:run-program '("cargo" "build" (unless debug "--release")) :output t)
   70.17+	 (find-rs-cdylib ,name ,debug)))))
   70.18+
   70.19+(define-foreign-library demo
   70.20+  (:win32 (:default "demo"))
   70.21+  (t (:default "libdemo")))
   70.22+(define-foreign-library quiche
   70.23+  (:win32 (:default "quiche"))
   70.24+  (t (:default "libquiche")))
   70.25+;; (define-foreign-library rocksdb
   70.26+;;   (:win32 (:default "rocksdb"))
   70.27+;;   (t (:default "librocksdb")))
   70.28+
   70.29+(defun load-libdemo () (load-foreign-library (find-rs-cdylib "libdemo.dylib")))
   70.30+(defun install-quiche-lib (&optional path) (load-foreign-library (or path quiche-lib-path)))
   70.31+;; (defun install-rocksdb-lib (&optional path) (load-foreign-library (or path rocksdb-lib-path)))
    71.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2+++ b/src/gen.rs	Sat Jun 03 22:48:46 2023 -0400
    71.3@@ -0,0 +1,84 @@
    71.4+//! demo
    71.5+pub use fig::*;
    71.6+pub use obj::*;
    71.7+use std::ffi::{CStr, CString}; //OsStr,Path
    71.8+                               //use std::os::unix::ffi::OsStrExt;
    71.9+use std::slice;
   71.10+use libc::{c_char,size_t};
   71.11+
   71.12+#[macro_export]
   71.13+macro_rules! cdefn {
   71.14+  (free $t:tt $n:tt) => {
   71.15+    #[no_mangle]
   71.16+    pub unsafe extern "C" fn $n(ptr: *mut $t) {
   71.17+      if ptr.is_null() {
   71.18+        return;
   71.19+      }
   71.20+      let _ = Box::from_raw(ptr);
   71.21+    }
   71.22+  };
   71.23+  (from_string $t:tt $n:tt) => {
   71.24+    #[no_mangle]
   71.25+    pub unsafe extern "C" fn $n(ptr: *const c_char) -> *mut $t {
   71.26+      assert!(!ptr.is_null());
   71.27+      let p = CStr::from_ptr(ptr).to_str().unwrap();
   71.28+      Box::into_raw(Box::new(p.into()))
   71.29+    }
   71.30+  };
   71.31+  (json_string $t:tt $r:tt $w:tt) => {
   71.32+    #[no_mangle]
   71.33+    pub unsafe extern "C" fn $r(ptr: *const c_char) -> *mut $t {
   71.34+      assert!(!ptr.is_null());
   71.35+      let s = CStr::from_ptr(ptr);
   71.36+      Box::into_raw(Box::new($t::from_json_str(&s.to_str().unwrap()).unwrap()))
   71.37+    }
   71.38+
   71.39+    #[no_mangle]
   71.40+    pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut c_char {
   71.41+      let p = &*ptr;
   71.42+      let x = p.to_json_string().unwrap();
   71.43+      CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   71.44+    }
   71.45+  };
   71.46+  (ron_string $t:tt $r:tt $w:tt) => {
   71.47+    #[no_mangle]
   71.48+    pub unsafe extern "C" fn $r(ptr: *const c_char) -> *mut $t {
   71.49+      assert!(!ptr.is_null());
   71.50+      let s = CStr::from_ptr(ptr);
   71.51+      Box::into_raw(Box::new($t::from_ron_str(&s.to_str().unwrap()).unwrap()))
   71.52+    }
   71.53+
   71.54+    #[no_mangle]
   71.55+    pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut c_char {
   71.56+      let p = &*ptr;
   71.57+      let x = p.to_ron_string().unwrap();
   71.58+      CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   71.59+    }
   71.60+  };
   71.61+  (bytes $t:tt $r:tt $w:tt) => {
   71.62+    #[no_mangle]
   71.63+    pub unsafe extern "C" fn $r(ptr: *const u8, len: size_t) -> *mut $t {
   71.64+      Box::into_raw(Box::new($t::decode(slice::from_raw_parts(ptr,len)).unwrap()))
   71.65+    }
   71.66+
   71.67+    #[no_mangle]
   71.68+    pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut u8 {
   71.69+      let p = &*ptr;
   71.70+      let mut x = p.encode().unwrap();
   71.71+      let r = x.as_mut_ptr();
   71.72+      std::mem::forget(x);
   71.73+      r
   71.74+    }
   71.75+  }
   71.76+}
   71.77+
   71.78+cdefn!(free Service free_service);
   71.79+cdefn!(from_string Service service_from_string);
   71.80+cdefn!(json_string Service service_from_json_string service_to_json_string);
   71.81+cdefn!(ron_string Service service_from_ron_string service_to_ron_string);
   71.82+cdefn!(bytes Service service_decode service_encode);
   71.83+cdefn!(free CustomService free_custom_service);
   71.84+cdefn!(from_string CustomService custom_service_from_string);
   71.85+cdefn!(json_string CustomService custom_service_from_json_string custom_service_to_json_string);
   71.86+cdefn!(ron_string CustomService custom_service_from_ron_string custom_service_to_ron_string);
   71.87+cdefn!(bytes CustomService custom_service_decode custom_service_encode);
    72.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2+++ b/src/lib.rs	Sat Jun 03 22:48:46 2023 -0400
    72.3@@ -0,0 +1,117 @@
    72.4+//! demo/lib.rs --- generated by DEMO:RS-MACROEXPAND
    72.5+extern crate libc;
    72.6+extern crate obj;
    72.7+use libc::{c_char, size_t};
    72.8+use obj::{CustomService, Objective, Service};
    72.9+use std::ffi::{CStr, CString};
   72.10+use std::slice;
   72.11+#[no_mangle]
   72.12+pub unsafe extern "C" fn free_service(ptr: *mut Service) {
   72.13+  if ptr.is_null() {
   72.14+    return;
   72.15+  }
   72.16+  let _ = Box::from_raw(ptr);
   72.17+}
   72.18+#[no_mangle]
   72.19+pub unsafe extern "C" fn service_from_string(ptr: *const c_char) -> *mut Service {
   72.20+  assert!(!ptr.is_null());
   72.21+  let p = CStr::from_ptr(ptr).to_str().unwrap();
   72.22+  Box::into_raw(Box::new(p.into()))
   72.23+}
   72.24+#[no_mangle]
   72.25+pub unsafe extern "C" fn service_from_json_string(ptr: *const c_char) -> *mut Service {
   72.26+  assert!(!ptr.is_null());
   72.27+  let s = CStr::from_ptr(ptr);
   72.28+  Box::into_raw(Box::new(
   72.29+    Service::from_json_str(&s.to_str().unwrap()).unwrap(),
   72.30+  ))
   72.31+}
   72.32+#[no_mangle]
   72.33+pub unsafe extern "C" fn service_to_json_string(ptr: *const Service) -> *mut c_char {
   72.34+  let p = &*ptr;
   72.35+  let x = p.to_json_string().unwrap();
   72.36+  CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   72.37+}
   72.38+#[no_mangle]
   72.39+pub unsafe extern "C" fn service_from_ron_string(ptr: *const c_char) -> *mut Service {
   72.40+  assert!(!ptr.is_null());
   72.41+  let s = CStr::from_ptr(ptr);
   72.42+  Box::into_raw(Box::new(
   72.43+    Service::from_ron_str(&s.to_str().unwrap()).unwrap(),
   72.44+  ))
   72.45+}
   72.46+#[no_mangle]
   72.47+pub unsafe extern "C" fn service_to_ron_string(ptr: *const Service) -> *mut c_char {
   72.48+  let p = &*ptr;
   72.49+  let x = p.to_ron_string().unwrap();
   72.50+  CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   72.51+}
   72.52+#[no_mangle]
   72.53+pub unsafe extern "C" fn service_decode(ptr: *const u8, len: size_t) -> *mut Service {
   72.54+  Box::into_raw(Box::new(
   72.55+    Service::decode(slice::from_raw_parts(ptr, len)).unwrap(),
   72.56+  ))
   72.57+}
   72.58+#[no_mangle]
   72.59+pub unsafe extern "C" fn service_encode(ptr: *const Service) -> *mut u8 {
   72.60+  let p = &*ptr;
   72.61+  let mut x = p.encode().unwrap();
   72.62+  let r = x.as_mut_ptr();
   72.63+  std::mem::forget(x);
   72.64+  r
   72.65+}
   72.66+#[no_mangle]
   72.67+pub unsafe extern "C" fn free_custom_service(ptr: *mut CustomService) {
   72.68+  if ptr.is_null() {
   72.69+    return;
   72.70+  }
   72.71+  let _ = Box::from_raw(ptr);
   72.72+}
   72.73+#[no_mangle]
   72.74+pub unsafe extern "C" fn custom_service_from_string(ptr: *const c_char) -> *mut CustomService {
   72.75+  assert!(!ptr.is_null());
   72.76+  let p = CStr::from_ptr(ptr).to_str().unwrap();
   72.77+  Box::into_raw(Box::new(p.into()))
   72.78+}
   72.79+#[no_mangle]
   72.80+pub unsafe extern "C" fn custom_service_from_json_string(ptr: *const c_char) -> *mut CustomService {
   72.81+  assert!(!ptr.is_null());
   72.82+  let s = CStr::from_ptr(ptr);
   72.83+  Box::into_raw(Box::new(
   72.84+    CustomService::from_json_str(&s.to_str().unwrap()).unwrap(),
   72.85+  ))
   72.86+}
   72.87+#[no_mangle]
   72.88+pub unsafe extern "C" fn custom_service_to_json_string(ptr: *const CustomService) -> *mut c_char {
   72.89+  let p = &*ptr;
   72.90+  let x = p.to_json_string().unwrap();
   72.91+  CString::new(x.as_str().as_bytes()).unwrap().into_raw()
   72.92+}
   72.93+#[no_mangle]
   72.94+pub unsafe extern "C" fn custom_service_from_ron_string(ptr: *const c_char) -> *mut CustomService {
   72.95+  assert!(!ptr.is_null());
   72.96+  let s = CStr::from_ptr(ptr);
   72.97+  Box::into_raw(Box::new(
   72.98+    CustomService::from_ron_str(&s.to_str().unwrap()).unwrap(),
   72.99+  ))
  72.100+}
  72.101+#[no_mangle]
  72.102+pub unsafe extern "C" fn custom_service_to_ron_string(ptr: *const CustomService) -> *mut c_char {
  72.103+  let p = &*ptr;
  72.104+  let x = p.to_ron_string().unwrap();
  72.105+  CString::new(x.as_str().as_bytes()).unwrap().into_raw()
  72.106+}
  72.107+#[no_mangle]
  72.108+pub unsafe extern "C" fn custom_service_decode(ptr: *const u8, len: size_t) -> *mut CustomService {
  72.109+  Box::into_raw(Box::new(
  72.110+    CustomService::decode(slice::from_raw_parts(ptr, len)).unwrap(),
  72.111+  ))
  72.112+}
  72.113+#[no_mangle]
  72.114+pub unsafe extern "C" fn custom_service_encode(ptr: *const CustomService) -> *mut u8 {
  72.115+  let p = &*ptr;
  72.116+  let mut x = p.encode().unwrap();
  72.117+  let r = x.as_mut_ptr();
  72.118+  std::mem::forget(x);
  72.119+  r
  72.120+}
    73.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2+++ b/src/rs.lisp	Sat Jun 03 22:48:46 2023 -0400
    73.3@@ -0,0 +1,78 @@
    73.4+;;; RUST DSL
    73.5+
    73.6+;; So basically, this was born out of personal frustration with how
    73.7+;; cbindgen and Rust macros work (they don't). Rust macros in general
    73.8+;; are something of a pain in my opinion, so I thought why not just
    73.9+;; generate Rust code from Lisp instead?
   73.10+
   73.11+(in-package :demo)
   73.12+
   73.13+(defvar *cargo-target* #p"/Users/ellis/dev/otom8/demo/target/")
   73.14+(defvar *rs-macros* nil)
   73.15+
   73.16+;; TODO gensyms
   73.17+(defmacro rs-defmacro (name args &body body)
   73.18+  "Define a macro which can be used within the body of a 'with-rs' form."
   73.19+  `(prog1
   73.20+       (defmacro ,name ,@(mapcar #`(,a1) args) ,@body)
   73.21+     (push ',name *rs-macros*)))
   73.22+
   73.23+(defun rs-mod-form (crate &optional mods pub)
   73.24+  "Generate a basic mod form (CRATE . [MODS] [PUB])"
   73.25+    `(,crate ,mods ,pub))
   73.26+
   73.27+(defmacro with-rs-env (imports &body body)
   73.28+  "Generate an environment for use within a Rust generator macro."
   73.29+  `(let ((imports ,(mapcar #'rs-mod-form imports)))
   73.30+     (format nil "~A~&~A" imports ',body)))
   73.31+
   73.32+(defun rs-use (crate &optional mods pub)
   73.33+  "Generate a single Rust use statement."
   73.34+  (concatenate
   73.35+   'string
   73.36+   (if pub "pub " "")
   73.37+   "use " crate "::{"
   73.38+   (cond
   73.39+     ((consp mods)
   73.40+      (reduce
   73.41+       (lambda (x y) (format nil "~A,~A" x y))
   73.42+       mods))
   73.43+     (t mods))
   73.44+   "};"))
   73.45+
   73.46+(defun rs-mod (mod &optional pub)
   73.47+  "Generate a single Rust mod statement."
   73.48+  (concatenate
   73.49+   'string
   73.50+   (if pub "pub " "")
   73.51+   "mod " mod ";"))
   73.52+
   73.53+(defun rs-imports (&rest imports)
   73.54+  "Generate a string of Rust 'use' statements."
   73.55+  (cond
   73.56+    ((consp imports)
   73.57+     (mapcar (lambda (x) (apply #'rs-use (apply #'rs-mod-form x))) imports))
   73.58+    (t imports)))
   73.59+
   73.60+(defmacro rs-extern-c-fn (name args &optional pub unsafe no-mangle &body body)
   73.61+  "Generate a Rust extern 'C' fn."
   73.62+  `(concatenate
   73.63+   'string
   73.64+   ,(when no-mangle (format nil "#[no_mangle]~&"))
   73.65+   ,(when pub "pub ")
   73.66+   ,(when unsafe "unsafe ")
   73.67+   "extern \"C\" fn " ,name "("
   73.68+   ,(cond
   73.69+      ((consp args) (reduce (lambda (x y) (format nil "~A,~A" x y)) args))
   73.70+      (t args))
   73.71+   ")" "{" ,@body "}"))
   73.72+
   73.73+(defun rs-obj-impl (obj)
   73.74+  "Implement Objective for give OBJ."
   73.75+  (format nil "impl Objective for ~A {};" obj))
   73.76+
   73.77+;; (defun rs-macroexpand-1 (form &optional env))
   73.78+
   73.79+;; (defun rs-macroexpand (env &rest body)
   73.80+
   73.81+;;; 
    74.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2+++ b/src/tests.lisp	Sat Jun 03 22:48:46 2023 -0400
    74.3@@ -0,0 +1,1 @@
    74.4+(in-package :demo)
    75.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2+++ b/src/tests/demo_test.c	Sat Jun 03 22:48:46 2023 -0400
    75.3@@ -0,0 +1,8 @@
    75.4+#include <stdio.h>
    75.5+#include "demo.h"
    75.6+
    75.7+int main() {
    75.8+  Service *srv = service_from_string("weather");
    75.9+  printf!("%s\n",service_to_json_str(srv));
   75.10+  free_service(srv);
   75.11+}
    76.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2+++ b/src/tests/demo_test.py	Sat Jun 03 22:48:46 2023 -0400
    76.3@@ -0,0 +1,1 @@
    76.4+from _demo import lib
    77.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2+++ b/src/tests/prime-test.lisp	Sat Jun 03 22:48:46 2023 -0400
    77.3@@ -0,0 +1,67 @@
    77.4+;; (defun is-prime(n)
    77.5+;;   (do ((num 2 (+ num 1)))
    77.6+;;       ((> num (/ n 2)) t)
    77.7+;;     (if (= 0 (mod n num))
    77.8+;; 	(return-from is-prime nil))))
    77.9+
   77.10+;; (defun kth-prime(k)
   77.11+;;   (do ((candidate 2 (+ candidate 1)))
   77.12+;;       ((< k 1) (- candidate 1))
   77.13+;;     (when (is-prime candidate)
   77.14+;;       (decf k))))
   77.15+
   77.16+;; (time (kth-prime 10000))
   77.17+
   77.18+;; (declaim (inline is-prime))
   77.19+;; (defun is-prime (n)
   77.20+;;   (loop for num of-type fixnum from 3 to (isqrt n) by 2
   77.21+;;         when (zerop (mod n num))
   77.22+;;         return nil
   77.23+;;         finally (return t)))
   77.24+
   77.25+;; (defun kth-prime (k)
   77.26+;;   (declare (optimize (speed 3) (safety 0))
   77.27+;;            (fixnum k))
   77.28+;;   (if (zerop k)
   77.29+;;       2
   77.30+;;       (loop for candidate of-type fixnum from 3 by 2
   77.31+;;             when (<= k 0) return (- candidate 2)
   77.32+;;             when (is-prime candidate) do (decf k))))
   77.33+
   77.34+;; (declaim
   77.35+;;   (optimize (speed 3) (safety 0))
   77.36+;;   (inline is-prime))
   77.37+
   77.38+;; (defun is-prime(n)
   77.39+;;   (declare (fixnum n))
   77.40+;;   (do ((num 2 (+ num 1)))
   77.41+;;       ((> num (floor n 2)) t)
   77.42+;;     (declare (fixnum num))
   77.43+;;     (if (= 0 (mod n num))
   77.44+;;       (return-from is-prime nil))))
   77.45+
   77.46+;; (defun kth-prime(k)
   77.47+;;   (declare (fixnum k))
   77.48+;;   (do ((candidate 2 (+ candidate 1)))
   77.49+;;       ((< k 1) (- candidate 1))
   77.50+;;     (declare (fixnum candidate))
   77.51+;;     (when (is-prime candidate)
   77.52+;;       (decf k))))
   77.53+
   77.54+;; (time (kth-prime 10000))
   77.55+
   77.56+(declaim (inline is-prime))
   77.57+(defun is-prime (n)
   77.58+  (loop for num of-type fixnum from 2 to (ash n -1)
   77.59+        when (zerop (mod n num))
   77.60+          return nil
   77.61+        finally (return t)))
   77.62+
   77.63+(defun kth-prime (k)
   77.64+  (declare (optimize (speed 3) (safety 0))
   77.65+           (fixnum k))
   77.66+  (loop for candidate of-type fixnum from 2
   77.67+        when (<= k 0) return (1- candidate)
   77.68+          when (is-prime candidate) do (decf k)))
   77.69+
   77.70+(time (kth-prime 10000))
    78.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2+++ b/src/tk.lisp	Sat Jun 03 22:48:46 2023 -0400
    78.3@@ -0,0 +1,28 @@
    78.4+(in-package :demo)
    78.5+
    78.6+(defun mkstr (&rest args)
    78.7+  (with-output-to-string (s)
    78.8+    (dolist (a args) (princ a s))))
    78.9+
   78.10+(defun symb (&rest args)
   78.11+  (values (intern (apply #'mkstr args))))
   78.12+
   78.13+(defun random-id ()
   78.14+  (format NIL "~8,'0x-~8,'0x" (random #xFFFFFFFF) (get-universal-time)))
   78.15+
   78.16+(defun scan-dir (dir filename callback)
   78.17+  (dolist (path (directory (merge-pathnames (merge-pathnames filename "**/") dir)))
   78.18+    (funcall callback path)))
   78.19+
   78.20+(defun sbq-reader (stream sub-char numarg)
   78.21+  "The anaphoric sharp-backquote reader: #`((,a1))"
   78.22+  (declare (ignore sub-char))
   78.23+  (unless numarg (setq numarg 1))
   78.24+  `(lambda ,(loop for i from 1 to numarg
   78.25+		  collect (symb 'a i))
   78.26+     ,(funcall
   78.27+       (get-macro-character #\`) stream nil)))
   78.28+
   78.29+(eval-when (:load-toplevel)
   78.30+  (set-dispatch-macro-character
   78.31+   #\# #\` #'demo:sbq-reader))
    79.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2+++ b/src/ui.lisp	Sat Jun 03 22:48:46 2023 -0400
    79.3@@ -0,0 +1,43 @@
    79.4+(in-package :demo)
    79.5+
    79.6+(defparameter ui-server-port 8080)
    79.7+(defparameter ui-server-host "0.0.0.0")
    79.8+
    79.9+(defclass ui-element (clog-element) ()
   79.10+  (:documentation "UI Element Object."))
   79.11+
   79.12+(defgeneric create-ui-element (obj &key hidden class id mode)
   79.13+  (:documentation "Create a new ui-element as a child of OBJ."))
   79.14+(defmethod create-ui-element ((obj clog:clog-obj)
   79.15+			      &key (class nil)
   79.16+				(hidden nil)
   79.17+				(id nil)
   79.18+				(mode 'auto))
   79.19+  (let ((new (clog:create-div obj
   79.20+			      :class class
   79.21+			      :hidden hidden
   79.22+			      :id id
   79.23+			      :mode mode)))
   79.24+    (clog:set-geometry new :width 200 :height 100)
   79.25+    (change-class new 'ui-element)))
   79.26+			      
   79.27+(defun on-new-window (body)
   79.28+  "Handle new window event."
   79.29+  (clog:debug-mode body)
   79.30+  (let ((elt (clog:create-child body "<h1>foobar</h1>")))
   79.31+    (clog:set-on-click
   79.32+     elt
   79.33+     (lambda (o)
   79.34+       (setf (clog:color elt) "green")))))
   79.35+
   79.36+(defun start-ui ()
   79.37+  "Start the UI."
   79.38+  (clog:initialize #'on-new-window
   79.39+		   :extended-routing t
   79.40+		   :host ui-server-host
   79.41+		   :port ui-server-port)
   79.42+  (clog:open-browser))
   79.43+
   79.44+(defun stop-ui ()
   79.45+  "Stop the UI."
   79.46+  (clog:shutdown))
    80.1--- a/tests.lisp	Sat Jun 03 19:57:46 2023 -0400
    80.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.3@@ -1,1 +0,0 @@
    80.4-(in-package :demo)
    81.1--- a/tests/demo_test.c	Sat Jun 03 19:57:46 2023 -0400
    81.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.3@@ -1,8 +0,0 @@
    81.4-#include <stdio.h>
    81.5-#include "demo.h"
    81.6-
    81.7-int main() {
    81.8-  Service *srv = service_from_string("weather");
    81.9-  printf!("%s\n",service_to_json_str(srv));
   81.10-  free_service(srv);
   81.11-}
    82.1--- a/tests/demo_test.py	Sat Jun 03 19:57:46 2023 -0400
    82.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.3@@ -1,1 +0,0 @@
    82.4-from _demo import lib
    83.1--- a/tests/prime-test.lisp	Sat Jun 03 19:57:46 2023 -0400
    83.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.3@@ -1,67 +0,0 @@
    83.4-;; (defun is-prime(n)
    83.5-;;   (do ((num 2 (+ num 1)))
    83.6-;;       ((> num (/ n 2)) t)
    83.7-;;     (if (= 0 (mod n num))
    83.8-;; 	(return-from is-prime nil))))
    83.9-
   83.10-;; (defun kth-prime(k)
   83.11-;;   (do ((candidate 2 (+ candidate 1)))
   83.12-;;       ((< k 1) (- candidate 1))
   83.13-;;     (when (is-prime candidate)
   83.14-;;       (decf k))))
   83.15-
   83.16-;; (time (kth-prime 10000))
   83.17-
   83.18-;; (declaim (inline is-prime))
   83.19-;; (defun is-prime (n)
   83.20-;;   (loop for num of-type fixnum from 3 to (isqrt n) by 2
   83.21-;;         when (zerop (mod n num))
   83.22-;;         return nil
   83.23-;;         finally (return t)))
   83.24-
   83.25-;; (defun kth-prime (k)
   83.26-;;   (declare (optimize (speed 3) (safety 0))
   83.27-;;            (fixnum k))
   83.28-;;   (if (zerop k)
   83.29-;;       2
   83.30-;;       (loop for candidate of-type fixnum from 3 by 2
   83.31-;;             when (<= k 0) return (- candidate 2)
   83.32-;;             when (is-prime candidate) do (decf k))))
   83.33-
   83.34-;; (declaim
   83.35-;;   (optimize (speed 3) (safety 0))
   83.36-;;   (inline is-prime))
   83.37-
   83.38-;; (defun is-prime(n)
   83.39-;;   (declare (fixnum n))
   83.40-;;   (do ((num 2 (+ num 1)))
   83.41-;;       ((> num (floor n 2)) t)
   83.42-;;     (declare (fixnum num))
   83.43-;;     (if (= 0 (mod n num))
   83.44-;;       (return-from is-prime nil))))
   83.45-
   83.46-;; (defun kth-prime(k)
   83.47-;;   (declare (fixnum k))
   83.48-;;   (do ((candidate 2 (+ candidate 1)))
   83.49-;;       ((< k 1) (- candidate 1))
   83.50-;;     (declare (fixnum candidate))
   83.51-;;     (when (is-prime candidate)
   83.52-;;       (decf k))))
   83.53-
   83.54-;; (time (kth-prime 10000))
   83.55-
   83.56-(declaim (inline is-prime))
   83.57-(defun is-prime (n)
   83.58-  (loop for num of-type fixnum from 2 to (ash n -1)
   83.59-        when (zerop (mod n num))
   83.60-          return nil
   83.61-        finally (return t)))
   83.62-
   83.63-(defun kth-prime (k)
   83.64-  (declare (optimize (speed 3) (safety 0))
   83.65-           (fixnum k))
   83.66-  (loop for candidate of-type fixnum from 2
   83.67-        when (<= k 0) return (1- candidate)
   83.68-          when (is-prime candidate) do (decf k)))
   83.69-
   83.70-(time (kth-prime 10000))
    84.1--- a/tk.lisp	Sat Jun 03 19:57:46 2023 -0400
    84.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.3@@ -1,28 +0,0 @@
    84.4-(in-package :demo)
    84.5-
    84.6-(defun mkstr (&rest args)
    84.7-  (with-output-to-string (s)
    84.8-    (dolist (a args) (princ a s))))
    84.9-
   84.10-(defun symb (&rest args)
   84.11-  (values (intern (apply #'mkstr args))))
   84.12-
   84.13-(defun random-id ()
   84.14-  (format NIL "~8,'0x-~8,'0x" (random #xFFFFFFFF) (get-universal-time)))
   84.15-
   84.16-(defun scan-dir (dir filename callback)
   84.17-  (dolist (path (directory (merge-pathnames (merge-pathnames filename "**/") dir)))
   84.18-    (funcall callback path)))
   84.19-
   84.20-(defun sbq-reader (stream sub-char numarg)
   84.21-  "The anaphoric sharp-backquote reader: #`((,a1))"
   84.22-  (declare (ignore sub-char))
   84.23-  (unless numarg (setq numarg 1))
   84.24-  `(lambda ,(loop for i from 1 to numarg
   84.25-		  collect (symb 'a i))
   84.26-     ,(funcall
   84.27-       (get-macro-character #\`) stream nil)))
   84.28-
   84.29-(eval-when (:load-toplevel)
   84.30-  (set-dispatch-macro-character
   84.31-   #\# #\` #'demo:sbq-reader))
    86.1--- a/tools/deps.nu	Sat Jun 03 19:57:46 2023 -0400
    86.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.3@@ -1,13 +0,0 @@
    86.4-
    86.5-pacman -Sy sbcl
    86.6-curl -o /tmp/ql.lisp http://beta.quicklisp.org/quicklisp.lisp
    86.7-sbcl --no-sysinit --no-userinit --load /tmp/ql.lisp \
    86.8-       --eval '(quicklisp-quickstart:install :path "~/.quicklisp")' \
    86.9-       --eval '(ql:add-to-init-file)' \
   86.10-       --quit
   86.11-sbcl --eval '(ql:quickload :quicklisp-slime-helper)' --quit
   86.12-# (load (expand-file-name "~/.quicklisp/slime-helper.el"))
   86.13-# (setq inferior-lisp-program "sbcl")
   86.14-curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
   86.15-cargo install cbindgen --force
   86.16-cargo install slint-lsp --git https://github.com/slint-ui/slint --force
   86.17\ No newline at end of file
    87.1--- a/tools/scripts/check.ros	Sat Jun 03 19:57:46 2023 -0400
    87.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.3@@ -1,17 +0,0 @@
    87.4-#!/bin/sh
    87.5-#|-*- mode:lisp -*-|#
    87.6-#|
    87.7-exec ros -Q -- $0 "$@"
    87.8-|#
    87.9-(progn ;;init forms
   87.10-  (ros:ensure-asdf)
   87.11-  #+quicklisp(ql:quickload '() :silent t)
   87.12-  )
   87.13-
   87.14-(defpackage :ros.script.scriptscheck.3892329806
   87.15-  (:use :cl))
   87.16-(in-package :ros.script.scriptscheck.3892329806)
   87.17-
   87.18-(defun main (&rest argv)
   87.19-  (declare (ignorable argv)))
   87.20-;;; vim: set ft=lisp lisp:
    88.1--- a/tools/scripts/db.ros	Sat Jun 03 19:57:46 2023 -0400
    88.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.3@@ -1,12 +0,0 @@
    88.4-#!/bin/sh
    88.5-#|-*- mode:lisp -*-|#
    88.6-#|
    88.7-exec ros -Q -- $0 "$@"
    88.8-|#
    88.9-(progn ;;init forms
   88.10-  (ros:ensure-asdf)
   88.11-  #+quicklisp(ql:quickload '() :silent t))
   88.12-
   88.13-(defun main (&rest argv)
   88.14-  (declare (ignorable argv))
   88.15-  (format t "hello world"))
    89.1--- a/tools/scripts/demo.ros	Sat Jun 03 19:57:46 2023 -0400
    89.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.3@@ -1,12 +0,0 @@
    89.4-#!/bin/sh
    89.5-#|-*- mode:lisp -*-|#
    89.6-#|
    89.7-exec ros -Q -- $0 "$@"
    89.8-|#
    89.9-(progn ;;init forms
   89.10-  (ros:ensure-asdf)
   89.11-  #+quicklisp(ql:quickload '(demo) :silent t))
   89.12-
   89.13-(defun main (&rest argv)
   89.14-  (declare (ignorable argv))
   89.15-  (demo:main))
    90.1--- a/tools/scripts/pack.ros	Sat Jun 03 19:57:46 2023 -0400
    90.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.3@@ -1,17 +0,0 @@
    90.4-#!/bin/sh
    90.5-#|-*- mode:lisp -*-|#
    90.6-#|
    90.7-exec ros -Q -- $0 "$@"
    90.8-|#
    90.9-(progn ;;init forms
   90.10-  (ros:ensure-asdf)
   90.11-  #+quicklisp(ql:quickload '() :silent t)
   90.12-  )
   90.13-
   90.14-(defpackage :ros.script.pack.3891893796
   90.15-  (:use :cl))
   90.16-(in-package :ros.script.pack.3891893796)
   90.17-
   90.18-(defun main (&rest argv)
   90.19-  (declare (ignorable argv)))
   90.20-;;; vim: set ft=lisp lisp:
    91.1--- a/tools/scripts/test.ros	Sat Jun 03 19:57:46 2023 -0400
    91.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.3@@ -1,14 +0,0 @@
    91.4-#!/bin/sh
    91.5-#|-*- mode:lisp -*-|#
    91.6-#|
    91.7-exec ros -Q -- $0 "$@"
    91.8-|#
    91.9-(progn ;;init forms
   91.10-  (ros:ensure-asdf)
   91.11-  #+quicklisp(ql:quickload '() :silent t))
   91.12-
   91.13-(defun main (&rest argv)
   91.14-  (declare (ignorable argv))
   91.15-  (write-line "> cargo test")
   91.16-  (uiop:run-program "cargo test")
   91.17-  (write-line "  tested rust crates"))
    93.1--- a/ui.lisp	Sat Jun 03 19:57:46 2023 -0400
    93.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.3@@ -1,43 +0,0 @@
    93.4-(in-package :demo)
    93.5-
    93.6-(defparameter ui-server-port 8080)
    93.7-(defparameter ui-server-host "0.0.0.0")
    93.8-
    93.9-(defclass ui-element (clog-element) ()
   93.10-  (:documentation "UI Element Object."))
   93.11-
   93.12-(defgeneric create-ui-element (obj &key hidden class id mode)
   93.13-  (:documentation "Create a new ui-element as a child of OBJ."))
   93.14-(defmethod create-ui-element ((obj clog:clog-obj)
   93.15-			      &key (class nil)
   93.16-				(hidden nil)
   93.17-				(id nil)
   93.18-				(mode 'auto))
   93.19-  (let ((new (clog:create-div obj
   93.20-			      :class class
   93.21-			      :hidden hidden
   93.22-			      :id id
   93.23-			      :mode mode)))
   93.24-    (clog:set-geometry new :width 200 :height 100)
   93.25-    (change-class new 'ui-element)))
   93.26-			      
   93.27-(defun on-new-window (body)
   93.28-  "Handle new window event."
   93.29-  (clog:debug-mode body)
   93.30-  (let ((elt (clog:create-child body "<h1>foobar</h1>")))
   93.31-    (clog:set-on-click
   93.32-     elt
   93.33-     (lambda (o)
   93.34-       (setf (clog:color elt) "green")))))
   93.35-
   93.36-(defun start-ui ()
   93.37-  "Start the UI."
   93.38-  (clog:initialize #'on-new-window
   93.39-		   :extended-routing t
   93.40-		   :host ui-server-host
   93.41-		   :port ui-server-port)
   93.42-  (clog:open-browser))
   93.43-
   93.44-(defun stop-ui ()
   93.45-  "Stop the UI."
   93.46-  (clog:shutdown))
    94.1--- a/ui/Cargo.toml	Sat Jun 03 19:57:46 2023 -0400
    94.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.3@@ -1,22 +0,0 @@
    94.4-[package]
    94.5-name = "ui"
    94.6-version = "0.1.0"
    94.7-edition = "2021"
    94.8-build = "build.rs"
    94.9-[lib]
   94.10-path = "lib.rs"
   94.11-crate-type = ["rlib","cdylib"]
   94.12-[[bin]]
   94.13-name = "demo-ui"
   94.14-path = "main.rs"
   94.15-[build-dependencies]
   94.16-slint-build = "1.0.2"
   94.17-[dependencies]
   94.18-obj = {version = "0.1.0",path = "../obj"}
   94.19-env_logger = "0.10.0"
   94.20-log = "0.4.17"
   94.21-slint = "1.0.2"
   94.22-[target.'cfg(target_arch = "wasm32")'.dependencies]
   94.23-wasm-bindgen = { version = "0.2" }
   94.24-web-sys = { version = "0.3", features=["console"] }
   94.25-console_error_panic_hook = "0.1.5"
    95.1--- a/ui/build.rs	Sat Jun 03 19:57:46 2023 -0400
    95.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.3@@ -1,3 +0,0 @@
    95.4-fn main() {
    95.5-    slint_build::compile("ui.slint").unwrap();
    95.6-}
    96.1--- a/ui/config.slint	Sat Jun 03 19:57:46 2023 -0400
    96.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.3@@ -1,3 +0,0 @@
    96.4-export global UiConfig  {
    96.5-    in property<bool> widgets-disabled: false;
    96.6-}
    96.7\ No newline at end of file
    97.1Binary file ui/img/ayo.jpeg has changed
    98.1Binary file ui/img/treez.png has changed
    99.1--- a/ui/index.html	Sat Jun 03 19:57:46 2023 -0400
    99.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.3@@ -1,9 +0,0 @@
    99.4-<html>
    99.5-  <body>
    99.6-    <canvas id="canvas">>/canvas>
    99.7-    <script type="module">
    99.8-      import init from './pkg/ui.js';
    99.9-      init();
   99.10-    </script>
   99.11-  </body>
   99.12-</html>
   100.1--- a/ui/lib.rs	Sat Jun 03 19:57:46 2023 -0400
   100.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.3@@ -1,69 +0,0 @@
   100.4-#![deny(unsafe_code)]
   100.5-
   100.6-#[cfg(target_arch = "wasm32")]
   100.7-use wasm_bindgen::prelude::*;
   100.8-
   100.9-slint::include_modules!();
  100.10-
  100.11-use std::rc::Rc;
  100.12-
  100.13-use slint::{Model, StandardListViewItem, VecModel};
  100.14-
  100.15-#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
  100.16-pub fn run() {
  100.17-    // This provides better error messages in debug mode.
  100.18-    // It's disabled in release mode so it doesn't bloat up the file size.
  100.19-    #[cfg(all(debug_assertions, target_arch = "wasm32"))]
  100.20-    console_error_panic_hook::set_once();
  100.21-
  100.22-    let app = App::new().unwrap();
  100.23-
  100.24-    let row_data: Rc<VecModel<slint::ModelRc<StandardListViewItem>>> = Rc::new(VecModel::default());
  100.25-
  100.26-    for r in 1..101 {
  100.27-        let items = Rc::new(VecModel::default());
  100.28-
  100.29-        for c in 1..5 {
  100.30-            items.push(slint::format!("Item {r}.{c}").into());
  100.31-        }
  100.32-
  100.33-        row_data.push(items.into());
  100.34-    }
  100.35-
  100.36-    app.global::<TableViewPageAdapter>().set_row_data(row_data.clone().into());
  100.37-
  100.38-    app.global::<TableViewPageAdapter>().on_sort_ascending({
  100.39-        let app_weak = app.as_weak();
  100.40-        let row_data = row_data.clone();
  100.41-        move |index| {
  100.42-            let row_data = row_data.clone();
  100.43-
  100.44-            let sort_model = Rc::new(row_data.sort_by(move |r_a, r_b| {
  100.45-                let c_a = r_a.row_data(index as usize).unwrap();
  100.46-                let c_b = r_b.row_data(index as usize).unwrap();
  100.47-
  100.48-                c_a.text.cmp(&c_b.text)
  100.49-            }));
  100.50-
  100.51-            app_weak.unwrap().global::<TableViewPageAdapter>().set_row_data(sort_model.into());
  100.52-        }
  100.53-    });
  100.54-
  100.55-    app.global::<TableViewPageAdapter>().on_sort_descending({
  100.56-        let app_weak = app.as_weak();
  100.57-        move |index| {
  100.58-            let row_data = row_data.clone();
  100.59-
  100.60-            let sort_model = Rc::new(row_data.sort_by(move |r_a, r_b| {
  100.61-                let c_a = r_a.row_data(index as usize).unwrap();
  100.62-                let c_b = r_b.row_data(index as usize).unwrap();
  100.63-
  100.64-                c_b.text.cmp(&c_a.text)
  100.65-            }));
  100.66-
  100.67-            app_weak.unwrap().global::<TableViewPageAdapter>().set_row_data(sort_model.into());
  100.68-        }
  100.69-    });
  100.70-
  100.71-    app.run().unwrap();
  100.72-}
   101.1--- a/ui/main.rs	Sat Jun 03 19:57:46 2023 -0400
   101.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.3@@ -1,4 +0,0 @@
   101.4-use ui::run;
   101.5-fn main() {
   101.6-  run();
   101.7-}
   102.1--- a/ui/pages.slint	Sat Jun 03 19:57:46 2023 -0400
   102.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.3@@ -1,7 +0,0 @@
   102.4-import { AboutPage } from "pages/about.slint";
   102.5-import { ControlsPage } from "pages/controls.slint";
   102.6-import { ListViewPage } from "pages/list_view.slint";
   102.7-import { TableViewPage, TableViewPageAdapter } from "pages/table_view.slint";
   102.8-import { TextEditPage } from "pages/text_edit.slint";
   102.9-
  102.10-export { AboutPage, ControlsPage, ListViewPage, TextEditPage, TableViewPage, TableViewPageAdapter }
  102.11\ No newline at end of file
   103.1--- a/ui/pages/about.slint	Sat Jun 03 19:57:46 2023 -0400
   103.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.3@@ -1,10 +0,0 @@
   103.4-import { AboutSlint } from "std-widgets.slint";
   103.5-import { UiConfig } from "../config.slint";
   103.6-import { Page } from "page.slint";
   103.7-
   103.8-export component AboutPage inherits Page {
   103.9-    title: "About";
  103.10-    description: "Are you curious now? Check out the docs and gettings start from the Github repository and the website https://slint-ui.com and try it yourself.";
  103.11-
  103.12-    AboutSlint {}
  103.13-}
  103.14\ No newline at end of file
   104.1--- a/ui/pages/controls.slint	Sat Jun 03 19:57:46 2023 -0400
   104.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.3@@ -1,145 +0,0 @@
   104.4-import { Button, GroupBox, SpinBox, ComboBox, CheckBox, LineEdit, TabWidget, VerticalBox, HorizontalBox,
   104.5-    Slider, SpinBox } from "std-widgets.slint";
   104.6-import { UiConfig } from "../config.slint";
   104.7-import { Page } from "page.slint";
   104.8-
   104.9-export component ControlsPage inherits Page {
  104.10-    title: "Controls";
  104.11-    description: "This page gives an overview of the default widget set provided by Slint. The widgets are available in different styles native, fluent-(dark/light) and material-(dark/light). The widgets can be imported from \"std-widgets.slint\".";
  104.12-
  104.13-    GroupBox {
  104.14-        vertical-stretch: 0;
  104.15-        title: "Buttons";
  104.16-
  104.17-        HorizontalLayout {
  104.18-            spacing: 8px;
  104.19-            alignment: start;
  104.20-
  104.21-            Button {
  104.22-                text: "Regular Button";
  104.23-                enabled: !UiConfig.widgets-disabled;
  104.24-            }
  104.25-
  104.26-            Button {
  104.27-                text: "Button with Icon";
  104.28-                icon: @image-url("../img/treez.png");
  104.29-                enabled: !UiConfig.widgets-disabled;
  104.30-            }
  104.31-
  104.32-            Button {
  104.33-                checkable: true;
  104.34-                text: self.checked ? "ON" : "OFF";
  104.35-                enabled: !UiConfig.widgets-disabled;
  104.36-            }
  104.37-        }
  104.38-    }
  104.39-
  104.40-    GroupBox {
  104.41-        title: "CheckBox - SpinBox - ComboBox";
  104.42-        vertical-stretch: 0;
  104.43-
  104.44-        HorizontalBox {
  104.45-            alignment: start;
  104.46-            checkbox := CheckBox {
  104.47-                text: checkbox.checked ? "(checked)" : "(unchecked)";
  104.48-                checked: true;
  104.49-                enabled: !UiConfig.widgets-disabled;
  104.50-            }
  104.51-
  104.52-
  104.53-        SpinBox {
  104.54-            vertical-stretch: 0;
  104.55-            value: 42;
  104.56-            enabled: !UiConfig.widgets-disabled;
  104.57-        }
  104.58-
  104.59-            ComboBox {
  104.60-                model: ["Select Something", "From this", "Combobox"];
  104.61-                enabled: !UiConfig.widgets-disabled;
  104.62-            }
  104.63-        }
  104.64-
  104.65-
  104.66-    }
  104.67-
  104.68-    GroupBox {
  104.69-        title: "LineEdit";
  104.70-        vertical-stretch: 0;
  104.71-
  104.72-        LineEdit {
  104.73-            placeholder-text: "Enter some text";
  104.74-            enabled: !UiConfig.widgets-disabled;
  104.75-        }
  104.76-    }
  104.77-
  104.78-    GroupBox {
  104.79-        title: "Slider";
  104.80-        vertical-stretch: 0;
  104.81-
  104.82-        Slider {
  104.83-            min-width: 160px;
  104.84-            minimum: -100;
  104.85-            maximum: 100;
  104.86-            value: 42;
  104.87-            enabled: !UiConfig.widgets-disabled;
  104.88-        }
  104.89-    }
  104.90-
  104.91-    GroupBox {
  104.92-        title: "TabWidget";
  104.93-
  104.94-        TabWidget {
  104.95-            Tab {
  104.96-                title: "Tab 1";
  104.97-
  104.98-                VerticalBox {
  104.99-                    alignment: start;
 104.100-
 104.101-                    GroupBox {
 104.102-                        title: "Content of tab 1";
 104.103-
 104.104-                        HorizontalBox {
 104.105-                            alignment: start;
 104.106-
 104.107-                            Button {
 104.108-                                text: "Click me";
 104.109-                                enabled: !UiConfig.widgets-disabled;
 104.110-                            }
 104.111-                        }
 104.112-                    }
 104.113-                }
 104.114-            }
 104.115-
 104.116-            Tab {
 104.117-                title: "Tab 2";
 104.118-
 104.119-                VerticalBox {
 104.120-                    alignment: start;
 104.121-
 104.122-                    GroupBox {
 104.123-                        title: "Content of tab 2";
 104.124-
 104.125-                        VerticalBox {
 104.126-                            alignment: start;
 104.127-
 104.128-                            CheckBox {
 104.129-                                text: "Check me";
 104.130-                                enabled: !UiConfig.widgets-disabled;
 104.131-                            }
 104.132-                        }
 104.133-                    }
 104.134-                }
 104.135-            }
 104.136-
 104.137-            Tab {
 104.138-                title: "Tab 3";
 104.139-
 104.140-                VerticalBox {
 104.141-                    Text {
 104.142-                        text: "Content of tab 3";
 104.143-                    }
 104.144-                }
 104.145-            }
 104.146-        }
 104.147-    }
 104.148-}
 104.149\ No newline at end of file
   105.1--- a/ui/pages/list_view.slint	Sat Jun 03 19:57:46 2023 -0400
   105.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.3@@ -1,45 +0,0 @@
   105.4-import { HorizontalBox, VerticalBox, ListView, StandardListView, GroupBox } from "std-widgets.slint";
   105.5-import { UiConfig } from "../config.slint";
   105.6-import { Page } from "page.slint";
   105.7-
   105.8-export component ListViewPage inherits Page {
   105.9-    title: "ListView";
  105.10-    description: "ListViews can be used to display a list of elements. The StandardListBox is like the default ListView just with a default text based definition of the visual items. Both can be imported from \"std-widgets.slint\"";
  105.11-
  105.12-    HorizontalBox {
  105.13-        vertical-stretch: 1;
  105.14-        GroupBox {
  105.15-            title: "ListView";
  105.16-
  105.17-            ListView {
  105.18-                vertical-stretch: 0;
  105.19-                for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] : HorizontalBox {
  105.20-                   Image {
  105.21-                        width: 24px;
  105.22-                        source: @image-url("../img/ayo.jpeg");
  105.23-                   }
  105.24-                   Text {
  105.25-                        text: "Item " + i;
  105.26-                   }
  105.27-                }
  105.28-            }
  105.29-        }
  105.30-
  105.31-        GroupBox {
  105.32-            title: "StandardListView";
  105.33-            vertical-stretch: 0;
  105.34-
  105.35-            StandardListView {
  105.36-                model: [
  105.37-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
  105.38-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
  105.39-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
  105.40-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
  105.41-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
  105.42-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
  105.43-                    {text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
  105.44-                ];
  105.45-            }
  105.46-        }
  105.47-    }
  105.48-}
  105.49\ No newline at end of file
   106.1--- a/ui/pages/page.slint	Sat Jun 03 19:57:46 2023 -0400
   106.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.3@@ -1,27 +0,0 @@
   106.4-import { CheckBox, GridBox, ListView, ScrollView, VerticalBox } from "std-widgets.slint";
   106.5-
   106.6-import { UiConfig } from "../config.slint";
   106.7-
   106.8-export component Page inherits VerticalBox {
   106.9-    in property<string> title: "title";
  106.10-    in property<string> description: "description";
  106.11-
  106.12-    HorizontalLayout {
  106.13-        height: 24px;
  106.14-        Text {
  106.15-            font-size: 20px;
  106.16-            text <=> root.title;
  106.17-        }
  106.18-
  106.19-        // Spacer
  106.20-        Rectangle {}
  106.21-
  106.22-        CheckBox {
  106.23-            horizontal-stretch: 0;
  106.24-            text: "Disable widgets";
  106.25-            checked <=> UiConfig.widgets-disabled;
  106.26-        }
  106.27-    }
  106.28-
  106.29-    @children
  106.30-}
  106.31\ No newline at end of file
   107.1--- a/ui/pages/table_view.slint	Sat Jun 03 19:57:46 2023 -0400
   107.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.3@@ -1,48 +0,0 @@
   107.4-import { HorizontalBox, VerticalBox, StandardTableView, GroupBox} from "std-widgets.slint";
   107.5-import { UiConfig } from "../config.slint";
   107.6-import { Page } from "page.slint";
   107.7-
   107.8-export global TableViewPageAdapter  {
   107.9-    callback sort_ascending(int);
  107.10-    callback sort_descending(int);
  107.11-    in property <[[StandardListViewItem]]> row_data: [
  107.12-        [ { text: "Item 1.1" }, { text: "Item 1.2" }, { text: "Item 1.3" }, { text: "Item 1.4" }, ],
  107.13-        [ { text: "Item 2.1" }, { text: "Item 2.2" }, { text: "Item 2.3" }, { text: "Item 2.4" }, ],
  107.14-        [ { text: "Item 3.1" }, { text: "Item 3.2" }, { text: "Item 3.3" }, { text: "Item 3.4" }, ],
  107.15-        [ { text: "Item 4.1" }, { text: "Item 4.2" }, { text: "Item 4.3" }, { text: "Item 4.4" }, ],
  107.16-        [ { text: "Item 5.1" }, { text: "Item 5.2" }, { text: "Item 5.3" }, { text: "Item 5.4" }, ],
  107.17-        [ { text: "Item 6.1" }, { text: "Item 6.2" }, { text: "Item 6.3" }, { text: "Item 6.4" }, ],
  107.18-    ];
  107.19-}
  107.20-
  107.21-export component TableViewPage inherits Page {
  107.22-    title: "TableView";
  107.23-    description: "StandardTableView can be used to display a list of text elements in columns and rows. It can be imported from \"std-widgets.slint\"";
  107.24-
  107.25-    HorizontalBox {
  107.26-        vertical-stretch: 1;
  107.27-
  107.28-        GroupBox {
  107.29-            title: "StandardTableView";
  107.30-            vertical-stretch: 0;
  107.31-
  107.32-            StandardTableView {
  107.33-                sort-ascending(index) => {
  107.34-                    TableViewPageAdapter.sort_ascending(index);
  107.35-                }
  107.36-
  107.37-                sort-descending(index) => {
  107.38-                    TableViewPageAdapter.sort-descending(index);
  107.39-                }
  107.40-
  107.41-                columns: [
  107.42-                    { title: "Header 1" },
  107.43-                    { title: "Header 2" },
  107.44-                    { title: "Header 3" },
  107.45-                    { title: "Header 4" },
  107.46-                ];
  107.47-                rows: TableViewPageAdapter.row_data;
  107.48-            }
  107.49-        }
  107.50-    }
  107.51-}
  107.52\ No newline at end of file
   108.1--- a/ui/pages/text_edit.slint	Sat Jun 03 19:57:46 2023 -0400
   108.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.3@@ -1,32 +0,0 @@
   108.4-import { HorizontalBox, GroupBox, TextEdit } from "std-widgets.slint";
   108.5-import { UiConfig } from "../config.slint";
   108.6-import { Page } from "page.slint";
   108.7-
   108.8-export component TextEditPage inherits Page {
   108.9-    title: "TextEdit";
  108.10-    description: "Similar to LineEdit, but can be used to enter several lines of text. The widget can be imported from \"std-widgets.slint\".";
  108.11-
  108.12-    HorizontalBox {
  108.13-        GroupBox {
  108.14-            vertical-stretch: 0;
  108.15-            title: "Word-Wrap";
  108.16-            te1 := TextEdit {
  108.17-                min-width: 200px;
  108.18-                text: "This is our TextEdit widget, which allows for editing text that spans over multiple paragraphs.\nFor example this line starts in a new paragraph.\n\nWhen the amount of lines - due to wrapping and number of paragraphs - exceeds the available vertical height, a vertical scrollbar is shown that allows scrolling.\nYou may want to enter a bit of text here then in order to make them visible.";
  108.19-                wrap: word-wrap;
  108.20-                enabled: !UiConfig.widgets-disabled;
  108.21-            }
  108.22-        }
  108.23-
  108.24-        GroupBox {
  108.25-            title: "No-Wrap";
  108.26-            vertical-stretch: 0;
  108.27-            te2 := TextEdit {
  108.28-                min-width: 200px;
  108.29-                text <=> te1.text;
  108.30-                wrap: no-wrap;
  108.31-                enabled: !UiConfig.widgets-disabled;
  108.32-            }
  108.33-        }
  108.34-    }
  108.35-}
  108.36\ No newline at end of file
   109.1--- a/ui/sidebar.slint	Sat Jun 03 19:57:46 2023 -0400
   109.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.3@@ -1,127 +0,0 @@
   109.4-import { StyleMetrics } from "std-widgets.slint";
   109.5-
   109.6-component SideBarItem inherits Rectangle {
   109.7-    callback clicked <=> touch.clicked;
   109.8-    in-out property<string> text <=> label.text;
   109.9-    in property<bool> selected;
  109.10-    in property<bool> has-focus;
  109.11-
  109.12-    min-height: l.preferred-height;
  109.13-
  109.14-    state := Rectangle {
  109.15-        opacity: 0;
  109.16-        background: StyleMetrics.window-background;
  109.17-
  109.18-        animate opacity { duration: 150ms; }
  109.19-    }
  109.20-
  109.21-    l := HorizontalLayout {
  109.22-        y: (parent.height - self.height) / 2;
  109.23-        padding: StyleMetrics.layout-padding;
  109.24-        spacing: 0px;
  109.25-
  109.26-        label := Text {
  109.27-            color: StyleMetrics.default-text-color;
  109.28-            vertical-alignment: center;
  109.29-         }
  109.30-    }
  109.31-
  109.32-    touch := TouchArea {
  109.33-        width: 100%;
  109.34-        height: 100%;
  109.35-    }
  109.36-
  109.37-    states [
  109.38-        pressed when touch.pressed : {
  109.39-            state.opacity: 0.8;
  109.40-        }
  109.41-        hover when touch.has-hover : {
  109.42-            state.opacity: 0.6;
  109.43-        }
  109.44-        selected when root.selected : {
  109.45-            state.opacity: 1;
  109.46-        }
  109.47-        focused when root.has-focus : {
  109.48-            state.opacity: 0.8;
  109.49-        }
  109.50-    ]
  109.51-}
  109.52-
  109.53-export component SideBar inherits Rectangle {
  109.54-    in property<[string]> model: [];
  109.55-    out property<int> current-item: 0;
  109.56-    in property<string> title <=> label.text;
  109.57-    out property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
  109.58-    width: 180px;
  109.59-
  109.60-    forward-focus: fs;
  109.61-
  109.62-    accessible-role: tab;
  109.63-    accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-item;
  109.64-
  109.65-    Rectangle {
  109.66-        background: StyleMetrics.window-background.darker(0.2);
  109.67-
  109.68-        fs := FocusScope {
  109.69-            x:0;
  109.70-            width: 0px; // Do not react on clicks
  109.71-            property<int> focused-tab: 0;
  109.72-
  109.73-            key-pressed(event) => {
  109.74-                if (event.text == "\n") {
  109.75-                     root.current-item = root.current-focused;
  109.76-                     return accept;
  109.77-                }
  109.78-                if (event.text == Key.UpArrow) {
  109.79-                     self.focused-tab = Math.max(self.focused-tab - 1,  0);
  109.80-                     return accept;
  109.81-                }
  109.82-                if (event.text == Key.DownArrow) {
  109.83-                     self.focused-tab = Math.min(self.focused-tab + 1, root.model.length - 1);
  109.84-                     return accept;
  109.85-                }
  109.86-                return reject;
  109.87-            }
  109.88-
  109.89-            key-released(event) => {
  109.90-                if (event.text == " ") {
  109.91-                     root.current-item = root.current-focused;
  109.92-                     return accept;
  109.93-                }
  109.94-                return reject;
  109.95-            }
  109.96-        }
  109.97-    }
  109.98-
  109.99-    VerticalLayout {
 109.100-        padding-top: StyleMetrics.layout-padding;
 109.101-        padding-bottom: StyleMetrics.layout-padding;
 109.102-        spacing: StyleMetrics.layout-spacing;
 109.103-        alignment: start;
 109.104-
 109.105-        label := Text {
 109.106-            font-size: 16px;
 109.107-            horizontal-alignment: center;
 109.108-        }
 109.109-
 109.110-        navigation := VerticalLayout {
 109.111-            alignment: start;
 109.112-            vertical-stretch: 0;
 109.113-            for item[index] in root.model : SideBarItem {
 109.114-                has-focus: index == root.current-focused;
 109.115-                text: item;
 109.116-                selected: index == root.current-item;
 109.117-                clicked => { root.current-item = index; }
 109.118-            }
 109.119-        }
 109.120-
 109.121-        VerticalLayout {
 109.122-            bottom := VerticalLayout {
 109.123-                padding-left: StyleMetrics.layout-padding;
 109.124-                padding-right: StyleMetrics.layout-padding;
 109.125-
 109.126-                @children
 109.127-             }
 109.128-        }
 109.129-    }
 109.130-}
 109.131\ No newline at end of file
   110.1--- a/ui/ui.slint	Sat Jun 03 19:57:46 2023 -0400
   110.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.3@@ -1,20 +0,0 @@
   110.4-import {CheckBox, StandardListView, StyleMetrics} from "std-widgets.slint";
   110.5-import {AboutPage, ControlsPage, ListViewPage, TableViewPage, TableViewPageAdapter, TextEditPage} from "pages.slint";
   110.6-import {UiConfig} from "config.slint";
   110.7-import {SideBar} from "sidebar.slint";
   110.8-export {TableViewPageAdapter}
   110.9-export component App inherits Window {
  110.10-  title: "Demo";
  110.11-  icon: @image-url("img/treez.png");
  110.12-  HorizontalLayout {
  110.13-    side-bar := SideBar {
  110.14-      title: "Demo";
  110.15-      model: ["Controls", "ListView", "TableView", "TextEdit", "About"];
  110.16-    }
  110.17-    if(side-bar.current-item == 0) : ControlsPage {}
  110.18-    if(side-bar.current-item == 1) : ListViewPage {}
  110.19-    if(side-bar.current-item == 2) : TableViewPage {}
  110.20-    if(side-bar.current-item == 3) : TextEditPage {}
  110.21-    if(side-bar.current-item == 4) : AboutPage {}
  110.22-  }
  110.23-}
  110.24\ No newline at end of file