]> asedeno.scripts.mit.edu Git - cl-protobufs.git/blobdiff - examples.lisp
utilities: Introduce ILOGBITP, a LOGBITP for FIXNUMS
[cl-protobufs.git] / examples.lisp
index 9a1021d628d023f3e033311f0eee1974490054b6..1ff8d53d117f5b303680a1a546f989b698ebb4e1 100644 (file)
@@ -1,8 +1,8 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;                                                                  ;;;
-;;; Confidential and proprietary information of ITA Software, Inc.   ;;;
+;;; Free Software published under an MIT-like license. See LICENSE   ;;;
 ;;;                                                                  ;;;
-;;; Copyright (c) 2012 ITA Software, Inc.  All rights reserved.      ;;;
+;;; Copyright (c) 2012 Google, Inc.  All rights reserved.            ;;;
 ;;;                                                                  ;;;
 ;;; Original author: Scott McKay                                     ;;;
 ;;;                                                                  ;;;
 (in-package "PROTO-IMPL")
 
 
-;;; Examples, for manual testing
-
-;;--- Turn these into a test suite
+;;; Some examples; also for some for manual testing
 
 #||
-(setq cschema (proto:write-protobuf-schema-for-classes
-               '(qres-core::legacy-pnr
-                 qres-core::legacy-pnr-pax
-                 qres-core::legacy-pnr-segment
-                 qres-core::legacy-pnr-pax-segment)
-               :slot-filter #'quake::quake-slot-filter
-               :type-filter #'quake::quake-type-filter
-               :enum-filter #'quake::quake-enum-filter
-               :value-filter #'quake::quake-value-filter))
-
-(proto:serialize-object-to-stream pnr cschema :stream nil)
+;; A pretty useful subset of air schedule objects
+(setq sched-schema (proto:generate-schema-for-classes
+                    '(quux::zoned-time
+                      sched::scheduled-flight
+                      sched::flight-designator
+                      sched::flight-key
+                      sched::scheduled-segment
+                      sched::segment-key
+                      sched::subsegment-key
+                      sched::scheduled-leg
+                      sched::leg-key
+                      sched::revision-entry)
+                    :package :qres-sched
+                    :slot-filter #'quake::quake-slot-filter
+                    :type-filter #'quake::quake-type-filter
+                    :enum-filter #'quake::quake-enum-filter
+                    :value-filter #'quake::quake-value-filter))
+
+(proto:write-schema sched-schema)
+(proto:write-schema sched-schema :type :lisp)
 ||#
 
-#||
-(setq pschema (proto:write-protobuf-schema-for-classes
-               '(proto:protobuf proto:protobuf-option
-                 proto:protobuf-enum proto:protobuf-enum-value
-                 proto:protobuf-message proto:protobuf-field proto:protobuf-extension
-                 proto:protobuf-service proto:protobuf-rpc)))
-
-(proto:write-protobuf pschema)
-(proto:write-protobuf pschema :type :lisp)
-
-(setq pser (proto:serialize-object-to-stream pschema pschema :stream nil))
-(describe (proto:deserialize-object 'proto:protobuf pschema pser 0))
-
-(proto:print-text-format pschema pschema)
-(proto:print-text-format (proto:deserialize-object 'proto:protobuf pschema pser 0) pschema)
-||#
 
 #||
-(defclass proto-test1 ()
-  ((intval :type (integer -2147483648 +2147483647)
-           :initarg :intval)))
-
-(defclass proto-test2 ()
-  ((intval :type (or null (integer -2147483648 +2147483647))
-           :initarg :intval)
-   (strval :type string
-           :initarg :strval)))
-
-(defclass proto-test3 ()
-  ((intval :type (or null (integer -2147483648 +2147483647))
-           :initarg :intval)
-   (strval :type (or null string)
-           :initarg :strval)
-   (recval :type proto-test1
-           :initarg :recval)))
-
-(defclass proto-test4 ()
-  ((intval :type (or null (integer -2147483648 +2147483647))
-           :initarg :intval)
-   (strval :type (or null string)
-           :initarg :strval)
-   (recval :type proto-test2
-           :initarg :recval)))
-
-(defclass proto-test5 ()
-  ((color   :type (member :red :green :blue)
-            :initarg :color)
-   (intvals :type (list-of integer)
+;; A pretty useful subset of geographic business data
+(defclass geodata ()
+  ;; This one stores the data in lists
+  ((countries :type (proto:list-of qres-core::country)
+              :initform ()
+              :initarg :countries)
+   (regions :type (proto:list-of qres-core::region)
             :initform ()
-            :initarg :intvals)
-   (strvals :type (list-of string)
-            :initform ()
-            :initarg :strvals)))
-
-(setq tschema (proto:write-protobuf-schema-for-classes
-               '(proto-test1 proto-test2 proto-test3 proto-test4 proto-test5)))
-
-(setq test1 (make-instance 'proto-test1 :intval 150))
-(setq test2 (make-instance 'proto-test2 :strval "testing"))
-(setq test3 (make-instance 'proto-test3 :recval test1))
-(setq test4 (make-instance 'proto-test4 :recval test2))
-(setq test5 (make-instance 'proto-test5 :color :red :intvals '(2 3 5 7) :strvals '("two" "three" "five" "seven")))
-
-(setq tser1 (proto:serialize-object-to-stream test1 tschema :stream nil))
-(equalp tser1 #(#x08 #x96 #x01))
-(describe (proto:deserialize-object 'proto-test1 tschema tser1 0))
-
-(setq tser2 (proto:serialize-object-to-stream test2 tschema :stream nil))
-(equalp tser2 #(#x12 #x07 #x74 #x65 #x73 #x74 #x69 #x6E #x67))
-(describe (proto:deserialize-object 'proto-test2 tschema tser2 0))
-
-(setq tser3 (proto:serialize-object-to-stream test3 tschema :stream nil))
-(equalp tser3 #(#x1A #x03 #x08 #x96 #x01))
-(describe (proto:deserialize-object 'proto-test3 tschema tser3 0))
-(describe (slot-value (proto:deserialize-object 'proto-test3 tschema tser3 0) 'recval))
-
-(setq tser4 (proto:serialize-object-to-stream test4 tschema :stream nil))
-(equalp tser4 #(#x1A #x09 #x12 #x07 #x74 #x65 #x73 #x74 #x69 #x6E #x67))
-(describe (proto:deserialize-object 'proto-test4 tschema tser4 0))
-(describe (slot-value (proto:deserialize-object 'proto-test4 tschema tser4 0) 'recval))
-
-(setq tser5 (proto:serialize-object-to-stream test5 tschema :stream nil))
-(equalp tser5 #(#x08 #x01
-                #x10 #x04 #x02 #x03 #x05 #x07
-                #x1A #x03 #x74 #x77 #x6F #x1A #x05 #x74 #x68 #x72 #x65 #x65 #x1A #x04 #x66 #x69 #x76 #x65 #x1A #x05 #x73 #x65 #x76 #x65 #x6E))
-(describe (proto:deserialize-object 'proto-test5 tschema tser5 0))
-
-(equalp (mapcar #'proto-impl:zig-zag-encode32
-                '(0 -1 1 -2 2 -2147483648 2147483647))
-        '(0 1 2 3 4 4294967295 4294967294))
-(equalp (mapcar #'proto-impl:zig-zag-encode64
-                '(0 -1 1 -2 2 -2147483648 2147483647 -1152921504606846976 1152921504606846975))
-        '(0 1 2 3 4 4294967295 4294967294 2305843009213693951 2305843009213693950))
-
-(proto:print-text-format test1 tschema)
-(proto:print-text-format (proto:deserialize-object 'proto-test1 tschema tser1 0) tschema)
-
-(proto:print-text-format test2 tschema)
-(proto:print-text-format (proto:deserialize-object 'proto-test2 tschema tser2 0) tschema)
-
-(proto:print-text-format test3 tschema)
-(proto:print-text-format (proto:deserialize-object 'proto-test3 tschema tser3 0) tschema)
-
-(proto:print-text-format test4 tschema)
-(proto:print-text-format (proto:deserialize-object 'proto-test4 tschema tser4 0) tschema)
-
-(proto:print-text-format test5 tschema)
-(proto:print-text-format (proto:deserialize-object 'proto-test5 tschema tser5 0) tschema)
+            :initarg :regions)
+   (cities :type (proto:list-of qres-core::city)
+           :initform ()
+           :initarg :cities)
+   (airports :type (proto:list-of qres-core::airport)
+             :initform ()
+             :initarg :airports)))
+
+(defclass geodata-v ()
+  ;; This one stores the data in vectors
+  ((countries :type (proto:vector-of qres-core::country)
+              :initform #()
+              :initarg :countries)
+   (regions :type (proto:vector-of qres-core::region)
+            :initform #()
+            :initarg :regions)
+   (cities :type (proto:vector-of qres-core::city)
+           :initform #()
+           :initarg :cities)
+   (airports :type (proto:vector-of qres-core::airport)
+             :initform #()
+             :initarg :airports)))
+
+(setq *geodata* (proto:generate-schema-for-classes
+                 '(qres-core::country
+                   qres-core::region
+                   qres-core::region-key
+                   qres-core::city
+                   qres-core::airport
+                   qres-core::timezone
+                   qres-core::tz-variation
+                   qres-core::currency
+                   qres-core::country-currencies
+                   qres-core::carrier
+                   geodata geodata-v)
+                 :install t))
+
+(proto:write-schema *geodata*)
+(proto:write-schema *geodata* :type :lisp)
+
+;; Load the data
+(let* ((countries (loop for v being the hash-values of (qres-core::country-business-data) collect (car v)))
+       (regions   (loop for v being the hash-values of (qres-core::region-business-data) collect v))
+       (cities    (loop for v being the hash-values of (qres-core::city-business-data) collect (car v)))
+       (airports  (loop for v being the hash-values of (car (qres-core::airport-business-data)) collect (car v))))
+  (setq geodata (make-instance 'geodata
+                  :countries countries
+                  :regions regions
+                  :cities cities
+                  :airports airports)
+        geodata-v (make-instance 'geodata-v
+                    :countries (make-array (length countries) :fill-pointer t :initial-contents countries)
+                    :regions (make-array (length regions) :fill-pointer t :initial-contents regions)
+                    :cities (make-array (length cities) :fill-pointer t :initial-contents cities)
+                    :airports (make-array (length airports) :fill-pointer t :initial-contents airports))))
+
+(dolist (class '(qres-core::country
+                 qres-core::region
+                 qres-core::region-key
+                 qres-core::city
+                 qres-core::airport
+                 qres-core::timezone
+                 qres-core::tz-variation
+                 qres-core::currency
+                 qres-core::country-currencies
+                 qres-core::carrier
+                 geodata geodata-v))
+  (let ((message (proto:find-message *geodata* class)))
+    (eval (proto-impl:generate-object-size  message))
+    (eval (proto-impl:generate-serializer   message))
+    (eval (proto-impl:generate-deserializer message))))
+
+(time (progn (setq gser (proto:serialize-object-to-bytes geodata 'geodata)) nil))
+(time (proto:deserialize-object 'geodata gser))
+
+(equalp gser (proto:serialize-object-to-bytes
+              (proto:deserialize-object 'geodata gser) 'geodata))
+
+(time (progn (setq gser-v (proto:serialize-object-to-bytes geodata-v 'geodata-v)) nil))
+(time (proto:deserialize-object 'geodata-v gser-v))
+
+(equalp gser-v (proto:serialize-object-to-bytes
+                (proto:deserialize-object 'geodata-v gser-v) 'geodata-v))
+
+(equalp gser gser-v)
 ||#
 
+
 #||
-(let* ((enums (list (make-instance 'proto:protobuf-enum
-                      :name "ColorName"
-                      :values (list (make-instance 'proto:protobuf-enum-value
-                                      :name "RED"
-                                      :index 1
-                                      :value :red)
-                                    (make-instance 'proto:protobuf-enum-value
-                                      :name "GREEN"
-                                      :index 2
-                                      :value :green)
-                                    (make-instance 'proto:protobuf-enum-value
-                                      :name "BLUE"
-                                      :index 3
-                                      :value :blue)))))
-       (msgs  (list (make-instance 'proto:protobuf-message
-                      :name "Color"
-                      :enums (list (make-instance 'proto:protobuf-enum
-                                      :name "ContrastName"
-                                      :values (list (make-instance 'proto:protobuf-enum-value
-                                                      :name "LOW"
-                                                      :index 1
-                                                      :value :high)
-                                                    (make-instance 'proto:protobuf-enum-value
-                                                      :name "HIGH"
-                                                      :index 100
-                                                      :value :low))))
-                      :fields (list (make-instance 'proto:protobuf-field
-                                      :name "color"
-                                      :type "ColorName"
-                                      :required :required
-                                      :index 1)
-                                    (make-instance 'proto:protobuf-field
-                                      :name "contrast"
-                                      :type "ContrastName"
-                                      :required :optional
-                                      :index 2
-                                      :default "LOW")))))
-       (rpcs  (list (make-instance 'proto:protobuf-rpc
-                      :name "GetColor"
-                      :input-type nil
-                      :output-type "Color")
-                    (make-instance 'proto:protobuf-rpc
-                      :name "SetColor"
-                      :input-type "Color"
-                      :output-type "Color"
-                      :options (list (make-instance 'protobuf-option
-                                       :name "deadline" :value "1.0")))))
-       (svcs  (list (make-instance 'proto:protobuf-service
-                      :name "ColorWheel"
-                      :rpcs rpcs)))
-       (proto (make-instance 'proto:protobuf
-                :package "ita.color"
-                :imports '("descriptor.proto")
-                :enums enums
-                :messages msgs
-                :services svcs)))
-  ;; The output should be example the same as the output of 'write-protobuf' below
-  (proto:write-protobuf proto))
+;; Lisp lists :-)
+(proto:define-schema typed-list ()
+  (proto:define-message typed-list ()
+    (string-car  :type (or null string)  :reader string-car)
+    (symbol-car  :type (or null string)  :reader symbol-car)
+    (integer-car :type (or null integer) :reader integer-car)
+    (float-car   :type (or null single-float) :reader float-car)
+    (list-car  :type (or null typed-list) :reader list-car)
+    (list-cdr  :type (or null typed-list) :reader list-cdr)))
+
+(defun string-car (x)
+  (and (stringp (car x)) (car x)))
+
+(defun symbol-car (x)
+  (and (symbolp (car x)) (symbol-name (car x))))
+
+(defun integer-car (x)
+  (and (integerp (car x)) (car x)))
+
+(defun float-car (x)
+  (and (floatp (car x)) (car x)))
+
+(defun list-car (x)
+  (etypecase (car x)
+    ((or string symbol integer float) nil)
+    (list (car x))))
+
+(defun list-cdr (x) 
+  (assert (listp (cdr x)) ())
+  (cdr x))
+
+(let ((list '("this" "is" "a" ("nested" "test"))))
+  (proto:serialize-object-to-bytes list 'typed-list)
+  (proto:print-text-format list 'typed-list)
+  (proto:print-text-format list 'typed-list :suppress-line-breaks t)
+  (let ((text (with-output-to-string (s)
+                (proto:print-text-format list 'typed-list :stream s))))
+    (with-input-from-string (s text)
+      (proto:parse-text-format 'typed-list :stream s))))
+
+(let ((list '((1 one) (2 two) (3 three))))
+  (proto:serialize-object-to-bytes list 'typed-list)
+  (proto:print-text-format list 'typed-list)
+  (proto:print-text-format list 'typed-list :suppress-line-breaks t)
+  (let ((text (with-output-to-string (s)
+                (proto:print-text-format list 'typed-list :stream s))))
+    (with-input-from-string (s text)
+      (proto:parse-text-format 'typed-list :stream s))))
 ||#
 
+
 #||
-(proto:define-proto color-wheel
-    (:package ita.color
-     :import "descriptor.proto"
+;; Extension example
+(proto:define-schema color-wheel
+    (:package color-wheel
+     :optimize :speed
      :documentation "Color wheel example")
-  (proto:define-enum color-name
-      (:documentation "A color name")
-    red
-    green
-    blue)
+  (proto:define-message color-wheel
+      (:conc-name color-wheel-)
+    (name   :type string)
+    (colors :type (proto:list-of color) :default ()))
   (proto:define-message color
       (:conc-name color-
-       :documentation "Color and contrast")
-    (proto:define-enum contrast-name
-        (:documentation "A contrast name")
-      (low    1)
-      (high 100))
-    (color    :type color-name)
-    (contrast :type (or null contrast-name) :default :low))
-  (proto:define-service color-wheel
-      (:documentation "Get and set colors")
-    (get-color (nil color))
-    (set-color (color color)
-               :options ("deadline" "1.0"))))
-
-=> (PROGN
-     (DEFTYPE COLOR-NAME () '(MEMBER :RED :GREEN :BLUE))
-     (DEFTYPE CONTRAST-NAME () '(MEMBER :LOW :HIGH))
-     (DEFCLASS COLOR ()
-       ((COLOR :TYPE COLOR-NAME :ACCESSOR COLOR-COLOR :INITARG :COLOR)
-        (CONTRAST :TYPE (OR NULL CONTRAST-NAME) :ACCESSOR COLOR-CONTRAST :INITARG :CONTRAST :INITFORM :LOW)))
-     (DEFVAR *COLOR-WHEEL*
-       (MAKE-INSTANCE 'PROTOBUF
-         :NAME "ColorWheel"
-         :CLASS 'COLOR-WHEEL
-         :PACKAGE "ita.color"
-         :IMPORTS '("descriptor.proto")
-         :SYNTAX NIL
-         :OPTIONS ()
-         :ENUMS (LIST (MAKE-INSTANCE 'PROTOBUF-ENUM
-                        :NAME "ColorName"
-                        :CLASS 'COLOR-NAME
-                        :VALUES (LIST (MAKE-INSTANCE 'PROTOBUF-ENUM-VALUE
-                                        :NAME "RED" :INDEX 1 :VALUE :RED)
-                                      (MAKE-INSTANCE 'PROTOBUF-ENUM-VALUE
-                                        :NAME "GREEN" :INDEX 2 :VALUE :GREEN)
-                                      (MAKE-INSTANCE 'PROTOBUF-ENUM-VALUE
-                                        :NAME "BLUE" :INDEX 3 :VALUE :BLUE))))
-         :MESSAGES (LIST (MAKE-INSTANCE 'PROTOBUF-MESSAGE
-                           :NAME "Color"
-                           :CLASS 'COLOR
-                           :CONC-NAME "COLOR-"
-                           :ENUMS (LIST (MAKE-INSTANCE 'PROTOBUF-ENUM
-                                          :NAME "ContrastName"
-                                          :CLASS 'CONTRAST-NAME
-                                          :VALUES (LIST (MAKE-INSTANCE 'PROTOBUF-ENUM-VALUE
-                                                          :NAME "LOW" :INDEX 1 :VALUE :LOW)
-                                                        (MAKE-INSTANCE 'PROTOBUF-ENUM-VALUE
-                                                          :NAME "HIGH" :INDEX 100 :VALUE :HIGH))))
-                           :MESSAGES (LIST)
-                           :FIELDS (LIST (MAKE-INSTANCE 'PROTOBUF-FIELD
-                                           :NAME "color"
-                                           :TYPE "ColorName"
-                                           :CLASS 'COLOR-NAME
-                                           :REQUIRED :REQUIRED
-                                           :INDEX 1
-                                           :VALUE 'COLOR
-                                           :DEFAULT NIL
-                                           :PACKED NIL)
-                                         (MAKE-INSTANCE 'PROTOBUF-FIELD
-                                           :NAME "contrast"
-                                           :TYPE "ContrastName"
-                                           :CLASS 'CONTRAST-NAME
-                                           :REQUIRED :OPTIONAL
-                                           :INDEX 2
-                                           :VALUE 'CONTRAST
-                                           :DEFAULT "LOW"
-                                           :PACKED NIL))))
-         :SERVICES (LIST (MAKE-INSTANCE 'PROTOBUF-SERVICE
-                           :NAME "ColorWheel"
-                           :CLASS 'COLOR-WHEEL
-                           :RPCS (LIST (MAKE-INSTANCE 'PROTOBUF-RPC
-                                         :NAME "GetColor"
-                                         :CLASS 'GET-COLOR
-                                         :INPUT-TYPE NIL
-                                         :OUTPUT-TYPE "Color"
-                                         :OPTIONS (LIST))
-                                       (MAKE-INSTANCE 'PROTOBUF-RPC
-                                         :NAME "SetColor"
-                                         :CLASS 'SET-COLOR
-                                         :INPUT-TYPE "Color"
-                                         :OUTPUT-TYPE "Color"
-                                         :OPTIONS (LIST (MAKE-INSTANCE 'PROTOBUF-OPTION
-                                                          :NAME "deadline" :VALUE "1.0")))))))))
-
-;; The output should be example the same as the output of 'write-protobuf' above
-(proto:write-protobuf *color-wheel*)
-
-;; How does the Lisp version look?
-(proto:write-protobuf *color-wheel* :type :lisp)
-
-(setq clr (make-instance 'color :color :red))
-(setq cser (proto:serialize-object-to-stream clr *color-wheel* :stream nil))
-(proto:print-text-format clr *color-wheel*)
-(proto:print-text-format (proto:deserialize-object 'color *color-wheel* cser 0) *color-wheel*)
+       :documentation "A (named) color")
+    (name    :type (or string null))
+    (r-value :type integer)
+    (g-value :type integer)
+    (b-value :type integer)
+    (proto:define-extension 1000 max))
+  (proto:define-extend color ()
+    ((opacity 1000) :type (or null integer)))
+  (proto:define-message get-color-request ()
+    (wheel :type color-wheel)
+    (name  :type string))
+  (proto:define-message add-color-request ()
+    (wheel :type color-wheel)
+    (color :type color))
+  (proto:define-service color-wheel ()
+    (get-color (get-color-request => color)
+      :options (:deadline 1.0)
+      :documentation "Look up a color by name")
+    (add-color (add-color-request => color)
+      :options (:deadline 1.0)
+      :documentation "Add a new color to the wheel")))
+
+(proto:write-schema *color-wheel*)
+(proto:write-schema *color-wheel* :type :lisp)
+
+(let* ((wheel  (make-instance 'color-wheel :name "Colors"))
+       (color1 (make-instance 'color :r-value 100 :g-value 0 :b-value 100))
+       (rqst1  (make-instance 'add-color-request :wheel wheel :color color1))
+       (color2 (make-instance 'color :r-value 100 :g-value 0 :b-value 100))
+       (rqst2  (make-instance 'add-color-request :wheel wheel :color color2)))
+  (setf (color-opacity color2) 50)
+  (progn
+    (format t "~2&Unextended (has-extension ~S)~%" (has-extension color1 'opacity))
+    (let ((ser1 (proto:serialize-object-to-bytes rqst1 'add-color-request)))
+      (print ser1)
+      (proto:print-text-format rqst1)
+      (proto:print-text-format (proto:deserialize-object 'add-color-request ser1))))
+  (progn 
+    (format t "~2&Extended (has-extension ~S)~%" (has-extension color2 'opacity))
+    (let ((ser2 (proto:serialize-object-to-bytes rqst2 'add-color-request)))
+      (print ser2)
+      (proto:print-text-format rqst2)
+      (proto:print-text-format (proto:deserialize-object 'add-color-request ser2)))))
 ||#
 
-#||
-(let ((ps "package ita.color;
-
-import \"descriptor.proto\";
-
-enum ColorName {
-  RED = 1;
-  GREEN = 2;
-  BLUE = 3;
-}
-
-message Color {
-  enum ContrastName {
-    LOW = 1;
-    HIGH = 100;
-  }
-  required ColorName color = 1;
-  optional ContrastName contrast = 2 [default = LOW];
-}
-
-service ColorWheel {
-  rpc GetColor () returns (Color);
-  rpc SetColor (Color) returns (Color) {
-    option deadline = \"1.0\";
-  }
-}"))
-  (with-input-from-string (s ps)
-    (setq ppp (parse-protobuf-from-stream s))))
-
-(proto:write-protobuf ppp)
-(proto:write-protobuf ppp :type :lisp)
-||#
 
 #||
-(proto:define-proto read-air-reservation (:package qres-core)
-  (proto:define-message read-request ()
-    ;; This is based on 'define-xto-parser (:qres-dev x-read-air-reservations-fn)'
-    (proto:define-message reservation-spec ()
-      (locator :type (list-of pnr-locator))
-      (customer :type (or null string))
-      (contract-group-id :type (or null integer))
-      (last-name :type (or null string))
-      (first-name :type (or null string))
-      (phone-number :type (or null string))
-      (email-address :type (or null string))
-      (cc-number :type (or null string))
-      (ticket-number :type (or null string))
-      (ff-account :type (or null ff-account))
-      (flights :type (list-of flight-spec)))
-    ;; This is based on 'define-xto-parser (:qres-dev q-generic-pnr-locator)'
-    (proto:define-message pnr-locator ()
-      (system :type string)
-      (locator :type string))
-    ;; This is based on 'define-xto-parser (:qres-dev ff-account)'
-    (proto:define-message ff-account ()
-      (carrier :type string)
-      (number :type string))
-    ;; This is based on 'define-xto-parser (:qres-dev x-flight)'
-    (proto:define-message flight-spec ()
-      (carrier :type string)
-      (flight-number :type integer)
-      (suffix :type (or null string))
-      (date :type string)
-      (origin :type (or null string))
-      (destination :type (or null string)))
-    (spec :type reservation-spec))
-  ;; This is based on 'define-xmlgen-component (:qres-dev :res "AirReservation")'
-  (proto:define-message read-response ()
-    )
-  (proto:define-service read-air-reservation ()
-    (read-air-reservation (read-request read-response))))
-
-(proto:write-protobuf *read-air-reservation*)
-(proto:write-protobuf *read-air-reservation* :type :lisp)
+;; Group example
+(proto:define-schema color-wheel1
+    (:package color-wheel
+     ;; :optimize :speed
+     :documentation "Color wheel example, with nested message")
+  (proto:define-type-alias date ()
+    :lisp-type integer
+    :proto-type string
+    :serializer integer-to-date
+    :deserializer date-to-integer)
+  (proto:define-message color-wheel1 ()
+    (proto:define-message metadata1 ()
+      (author :type (or null string))
+      (revision :type (or null string))
+      (date :type (or null date)))
+    (name :type string)
+    (colors :type (proto:list-of color1))
+    (metadata1 :type (or null metadata1)))
+  (proto:define-message color1 ()
+    (name :type (or null string))
+    (r-value :type integer)
+    (g-value :type integer)
+    (b-value :type integer))
+  (proto:define-message add-color1 ()
+    (wheel :type color-wheel1)
+    (color :type color1)))
+
+(proto:define-schema color-wheel2
+    (:package color-wheel
+     ;; :optimize :speed
+     :documentation "Color wheel example, with group")
+  (proto:define-type-alias date ()
+    :lisp-type integer
+    :proto-type string
+    :serializer integer-to-date
+    :deserializer date-to-integer)
+  (proto:define-message color-wheel2 ()
+    (name :type string)
+    (colors :type (proto:list-of color2))
+    (proto:define-group metadata2
+        (:index 3
+         :arity :optional)
+      (author :type (or null string))
+      (revision :type (or null string))
+      (date :type (or null date))))
+  (proto:define-message color2 ()
+    (name :type (or null string))
+    (r-value :type integer)
+    (g-value :type integer)
+    (b-value :type integer))
+  (proto:define-message add-color2 ()
+    (wheel :type color-wheel2)
+    (color :type color2)))
+
+(defun integer-to-date (date)
+  (with-output-to-string (s)
+    (quux:write-local-date (quux:get-local-time date) s :format :dd-mth-yyyy)))
+
+(defun date-to-integer (string)
+  (quux:parse-local-date string))
+
+(proto:write-schema *color-wheel1*)
+(proto:write-schema *color-wheel2*)
+
+(let* ((meta1  (make-instance 'metadata1 :revision "1.0" :date (date-to-integer "12-FEB-1958")))
+       (wheel1 (make-instance 'color-wheel1 :name "Colors" :metadata1 meta1))
+       (color1 (make-instance 'color1 :r-value 100 :g-value 0 :b-value 100))
+       (rqst1  (make-instance 'add-color1 :wheel wheel1 :color color1))
+       (meta2  (make-instance 'metadata2 :revision "1.0" :date (date-to-integer "12-FEB-1958")))
+       (wheel2 (make-instance 'color-wheel2 :name "Colors" :metadata2 meta2))
+       (color2 (make-instance 'color2 :r-value 100 :g-value 0 :b-value 100))
+       (rqst2  (make-instance 'add-color2 :wheel wheel2 :color color2)))
+  (progn
+    (format t "~2&Nested")
+    (let ((ser1 (proto:serialize-object-to-bytes rqst1 'add-color1)))
+      (print ser1)
+      (proto:print-text-format rqst1)
+      (proto:print-text-format (proto:deserialize-object 'add-color1 ser1))))
+  (progn
+    (format t "~2&Group")
+    (let ((ser2 (proto:serialize-object-to-bytes rqst2 'add-color2)))
+      (print ser2)
+      (proto:print-text-format rqst2)
+      (proto:print-text-format (proto:deserialize-object 'add-color2 ser2)))))
 ||#
-