]> asedeno.scripts.mit.edu Git - cl-protobufs.git/blob - cl-protobufs.rst
Don't kluge *asdf-verbose* on asdf3.
[cl-protobufs.git] / cl-protobufs.rst
1 .. raw:: LaTeX
2
3    \setlength{\parindent}{0pt}
4    \setlength{\parskip}{6pt plus 2pt minus 1pt}
5
6
7 =========================
8 Protobufs for Common Lisp
9 =========================
10
11
12 :Description: Protobufs for Common Lisp
13 :Author: Scott McKay <swmckay@gmail.com>
14 :Date: $Date: 2012-08-31 11:13 -0500 (Fri, 31 Aug 2012) $
15
16 .. contents::
17 ..
18     1  Introduction
19       1.1  Implementation notes
20       1.2  Model classes
21     2  Defining a Protobufs schema
22       2.1  .proto file to Lisp conversion
23       2.2  CLOS classes to .proto conversion
24       2.3  Using .proto files directly
25         2.3.1  A note on Lisp packages
26       2.4  Using the Protobufs macros
27         2.4.1  Protobufs types
28         2.4.2  Protobufs service stubs
29     3  Serializing and deserializing
30       3.1  Wire format
31       3.2  Text format
32     4  Other API functions
33       4.1 Extensions functions
34       4.2 Initialization functions
35       4.3 Python compatibility functions
36     5  Lisp-only extensions
37       5.1 Type aliases
38
39
40 Introduction
41 ============
42
43 The Common Lisp Protobufs library provides a fully in-Lisp way for
44 Common Lisp programs to use existing, or define new Protobufs
45 "schemas", and serialize and deserialize objects to and from the
46 Protobufs wire and text formats.
47
48 To use it, first load the ASDF declaration file ``protobufs/cl-protobufs.asd``
49 and then use ASDF to load the library named ``:cl-protobufs``.
50
51
52 Implementation notes
53 --------------------
54
55 The Protobufs library defines a set of model classes that describes a
56 protobufs "schema" (i.e., one .proto file). These classes describe a
57 schema, its options, enums and enum values, messages and fields, and
58 services and methods.
59
60 Unlike the 'protobuf' library described at ``http://common-lisp.net/project/protobuf``,
61 this implementation is entirely written in Common Lisp. It provides
62 some things that the 'protobuf' library does not, in particular,
63 the ability to define Protobufs schemas entirely within Lisp and
64 the ability to "export" a set of CLOS classes as a Protobufs schema.
65
66 The library provides the means to convert several kinds of inputs into
67 the Protobufs models, including:
68
69  - Parse an existing .proto file into a set of model objects.
70  - Convert a set of related CLOS classes into a set of model objects.
71  - Compile a ``proto:define-schema`` macro call into a set of model objects.
72
73 It also provides two ways to convert the model objects into outputs:
74
75  - Print a set of model objects using the standard Protobufs v2 syntax.
76  - Print a set of model objects using the Common Lisp syntax, defined below.
77
78 There are two formats for serialization and deserialization:
79
80  - The wire format, which is compact and fast.
81  - The text format, which is human readable.
82
83 Finally, there is a validator that takes an old version of a Protobufs
84 schema and a new version of the same schema and generates a set of
85 warnings that describes any incompatibilities between the old schema and
86 the new one.
87
88
89 Model classes
90 -------------
91
92 ::
93
94   proto:protobuf-schema                                         [Class]
95
96 The class the represents a Protobufs schema, i.e., one .proto file.
97 It has slots for the name, options, enums, messages and services. The
98 name is equal to the name of the .proto file, without the file type.
99
100 ::
101
102   proto:protobuf-option                                         [Class]
103
104 The class that represents a Protobufs option.
105 It has slots for a key and a value.
106
107 ::
108
109   proto:protobuf-enum                                           [Class]
110
111 The class that represents a Protobufs enum type.
112 It has slots for the enum name and its values.
113
114 ::
115
116   proto:protobuf-enum-value                                     [Class]
117
118 The class that represents one value in a Protobufs enum type.
119 It has slots for the value name and the value index.
120
121 ::
122
123   proto:protobuf-message                                        [Class]
124
125 The class that represents a Protobufs message.
126 It has slots for the name, options, nested enums and messages, and fields.
127
128 ::
129
130   proto:protobuf-field                                          [Class]
131
132 The class that represents one field in a Protobufs message.
133 It has slots for the name, type, index and options.
134
135 ::
136
137   proto:protobuf-service                                        [Class]
138
139 The class that represents a Protobufs service.
140 It has slots for the name, options and methods.
141
142 ::
143
144   proto:protobuf-method                                         [Class]
145
146 The class that represents one method description in a Protobufs service.
147 It has slots for the name, input type, output type and options.
148
149
150 Defining a Protobufs schema
151 ===========================
152
153 There are several ways to define a Protobufs schema: convert a .proto
154 file to a .lisp source file and then use the Lisp file; convert a set
155 of Lisp classes to a Protobufs model, and then use either the .lisp or
156 the .proto representation of the model; use a .proto file directly in
157 an ASDF system; or use the Protobufs macros in a Lisp source file.
158
159
160 .proto file to Lisp conversion
161 ------------------------------
162
163 If you have an existing .proto source file that you would like to
164 convert to Lisp classes (more precisely, to the macros defined by the
165 Protobufs library), you can use ``proto:parse-schema-from-file`` to
166 read the .proto file and then use ``proto:write-schema`` to write a
167 new .lisp file. (This is what that ASDF module type ``:protobuf-file``
168 does.)
169
170 ::
171
172   proto:parse-schema-from-file (pathname                        [Function]
173                                 &key name class conc-name)
174
175 Parses the contents of the file given by *pathname*, and returns the
176 Protobufs model (a set object objects rooted at ``proto:protobuf-schema``)
177 corresponding to the parsed file. The name of the Protobufs schema is
178 generated automatically from the file name.
179
180 *name*, *class* and *conc-name* are as for ``proto:parse-schema-from-stream``.
181 The defaults for *name* and *class* are produced by taking the name of the
182 file and generating a name string and a class name symbol.
183
184 ::
185
186   proto:parse-schema-from-stream (stream                        [Function]
187                                   &key name class conc-name)
188
189 Parses the contents of the stream *stream*, and returns the Protobufs
190 schema corresponding to the parsed file.
191
192 If *name* is supplied, it gives the Protobufs name (a string) for the
193 schema. If *class* is supplied, it gives the Lisp name (a symbol). These
194 are only used for display purposes.
195
196 *conc-name* is the default "conc name" to use for all of the messages
197 in the file. The default is "", which has the effect of giving eponymous
198 slot accessors to all of the classes generating during the import process.
199
200 ::
201
202   proto:write-schema (schema &key stream type)                  [Function]
203
204 Pretty-prints the Protobufs schema *schema* onto the stream *stream*,
205 which defaults to ``*standard-output*``.
206
207 *type* can be either ``:proto`` or ``:lisp``.
208
209
210 CLOS classes to .proto conversion
211 ---------------------------------
212
213 If you have an existing set of CLOS classes that you would like to
214 convert to a Protobufs schema, you can use ``proto:generate-schema-from-classes``.
215
216 Note that the Protobufs schema is an *approximation* of a good schema.
217 You should review it and, if necessary, change it (and probably the Lisp
218 classes as well) until you have a good Protobufs schema definition.
219
220 ::
221
222   proto:generate-schema-for-classes (classes                    [Function]
223                                      &key name package lisp-package
224                                           slot-filter type-filter enum-filter value-filter
225                                           alias-existing-classes)
226
227 Given a list of class names *classes*, this generates a Protobufs schema
228 for the classes, generating any necessary enum types that correspond to
229 Lisp ``member`` types. The return value is the model, rooted at an instance
230 of ``proto:protobuf-schema``.
231
232 *name* and *package* can be supplied to give the Protobufs name and
233 package. *lisp-package* can be supplied to give the name of the Lisp
234 package, if it is different from *package*. (Note that you should
235 still use ``in-package`` at the top of .lisp files, and it should
236 match the value of *lisp-package*.)
237
238 *slot-filter*, *type-filter*, *enum-filter* and *value-filter* are
239 filtering functions that can be used to weed out things from the Lisp
240 classes that should not be included in the Protobufs schema.
241
242 *slot-filter* is a function of two arguments, a list of all the slots
243 in the class and the slot currently being processed, and should return
244 true if the slot is to be kept or ``nil`` if it to be discarded. For
245 example, if there are internal implementation slots in a class that
246 need not appear in the Protobufs description, it can be used to filter
247 them out.
248
249 *type-filter* is a function of one argument, the type (of a slot); it
250 should return a "transformed" type if any is required. For example,
251 complex ``and`` and ``or`` types can't be directly represented in
252 Protobufs; this can be used to substitute something workable.
253
254 *enum-filter* is a function of one argument, a list of all the values
255 of a ``member`` type; it should return the transformed values. For
256 example, there maybe be some enumeration values that don't make sense;
257 they can be discarded by the filter.
258
259 *value-filter* is a function of one argument, the value of a slot
260 initform. It should transform the value into a scalar value suitable
261 for Protobufs.
262
263 If *alias-existing-classes* is true (the default), the generated
264 Lisp code will include ``:alias-for`` so that there will be no clash
265 with the existing Lisp class.
266
267 ::
268
269   proto:write-schema-for-classes (classes                       [Function]
270                                   &key stream type name package lisp-package
271                                        slot-filter type-filter enum-filter value-filter
272                                        alias-existing-classes)
273
274 Given a list of class names *classes*, this generates a Protobufs schema
275 for the classes, generating enum types as necessary, and then
276 pretty-prints the result onto *stream*. *type* can be either ``:proto``
277 (the default) or ``:lisp``; it controls which format the generated
278 code will be printed in. The return value is the model, rooted at an
279 instance of ``proto:protobuf-schema``.
280
281 *name* and *package* can be supplied to give the Protobufs name and
282 package. *lisp-package* can be supplied to give the name of the Lisp
283 package, if it is different from *package*.
284
285 *slot-filter*, *type-filter*, *enum-filter* and *value-filter* are
286 as for ``proto:generate-schema-for-classes``.
287
288 *alias-existing-classes* is as for ``proto:generate-schema-for-classes``.
289
290
291 Using .proto files directly
292 ---------------------------
293
294 In addition to using the tools described above to convert between
295 .proto files and .lisp files, you can also use .proto files directly
296 in ASDF systems. Just use the ASDF module type ``:protobuf-file`` in
297 your system, and compile and load the system in the usual way. This
298 will create both the Protobufs model and the Lisp classes that
299 correspond to the Protobufs messages. (Note that it will also leave a
300 .lisp file having the same name as the .proto file in the file
301 system.)
302
303
304 A note on Lisp packages
305 ~~~~~~~~~~~~~~~~~~~~~~~
306
307 When using an existing .proto file directly, it will likely contain a
308 ``package`` line, but not a ``lisp_package`` line. CL-Protobufs needs
309 to choose some package to use. Here is what it does:
310
311  - The package name from the ``package`` line is converted to a more
312    Lisp-like name, e.g., ``fortune_teller`` becomes ``fortune-teller``.
313  - If the Lisp package exists (i.e., you have previously used
314    ``defpackage`` to define the packaged), then CL-Protobufs just
315    uses it.
316  - If the Lisp package does not exist, CL-Protobufs creates a new
317    package of the given name that uses no other packages, not even
318    the ``common-lisp`` package. In addition, the symbols naming all
319    of the enum types, message types, field name and service method
320    names are exported from the new package.
321
322
323 Using the Protobufs macros
324 --------------------------
325
326 You can define a Protobufs schema entirely within Lisp by using the
327 following macros. For example::
328
329   (proto:define-schema color-wheel
330       (:package com.google.colorwheel
331        :lisp-package color-wheel)
332     (proto:define-message color-wheel
333         (:conc-name color-wheel-)
334       (name   :type string)
335       (colors :type (proto:list-of color) :default ()))
336     (proto:define-message color
337         (:conc-name color-)
338       (name    :type (or string null))
339       (r-value :type integer)
340       (g-value :type integer)
341       (b-value :type integer)
342       (proto:define-extension 1000 max))
343     (proto:define-extend color ()
344       ((opacity 1000) :type (or null integer)))
345     (proto:define-message get-color-request ()
346       (wheel :type color-wheel)
347       (name  :type string))
348     (proto:define-message add-color-request ()
349       (wheel :type color-wheel)
350       (color :type color))
351     (proto:define-service color-wheel ()
352       (get-color (get-color-request color)
353         :options (:deadline 1.0))
354       (add-color (add-color-request color)
355         :options (:deadline 1.0))))
356
357 This will create the Protobufs model objects, Lisp classes and enum
358 types that correspond to the model. The .proto file of the same schema
359 looks something like this::
360
361   syntax = "proto2";
362
363   package com.google.colorwheel;
364
365   option (lisp_package) = "color-wheel";
366
367   message ColorWheel {
368     required string name = 1;
369     repeated Color colors = 2;
370   }
371
372   message Color {
373     optional string name = 1;
374     required int64 rValue = 2;
375     required int64 gValue = 3;
376     required int64 bValue = 4;
377     extensions 1000 to max;
378   }
379
380   extend Color {
381     optional int64 opacity = 1000;
382   }
383
384   message GetColorRequest {
385     required ColorWheel wheel = 1;
386     required string name = 2;
387   }
388
389   message AddColorRequest {
390     required ColorWheel wheel = 1;
391     required Color color = 2;
392   }
393
394   service ColorWheel {
395     rpc GetColor (GetColorRequest) returns (Color) {
396       option deadline = 1.0;
397     }
398     rpc AddColor (AddColorRequest) returns (Color) {
399       option deadline = 1.0;
400     }
401   }
402
403 Note that Lisp types ``(or null <T>)`` turn into optional fields,
404 and Lisp types ``(proto:list-of <T>)`` and ``(proto:vector-of <T>)``
405 turn into repeated fields representing by lists or vectors,
406 respectively.
407
408 Note also that the macros have assigned indexes to the fields for each
409 method; similarly, they will assign values to enumerations as well.
410 *This is not stable*, that is, if you add new fields or enum values,
411 the indexes could change, which would result in an incompatible
412 Protobufs schema. 
413
414 ::
415
416   proto:define-schema (type (&key name syntax import            [Macro]
417                                   package lisp-package
418                                   optimize options documentation)
419                        &body messages)
420
421 Defines a Protobufs "schema" whose name is given by the symbol *type*,
422 corresponding to a .proto file of that name. By a "schema", we mean an
423 object that corresponds to the contents of one .proto file. If *name*
424 is not supplied, the Protobufs name of the schema is the camel-cased
425 rendition of *type* (e.g., the schema named ``color-wheel``, by
426 default, becomes ``ColorWheel``); otherwise the Protobufs name is the
427 string *name*.
428
429 *imports* is a list of pathname strings to be imported. This corresponds
430 to ``import`` in a .proto file. Note that ``proto:define-schema`` can
431 import both .proto files and .lisp files containing Protobufs macros,
432 but the generated .proto code will convert all of these to imports of
433 .proto files.
434
435 *syntax* and *package* are strings that give the Protobufs syntax and
436 package name. *lisp-package* can be supplied to give the name of the
437 Lisp package, if it is different from *package*. *package* corresponds
438 to ``package`` in a .proto file. If you want to specify a Lisp package
439 in a .proto file, you can use ``option (lisp_package)``.
440
441 *optimize* can be either ``:space`` (the default) or ``:speed``. When it
442 is ``:space`` the serialization methods generated for each message are
443 compact, but slower; when it is ``:speed``, the serialization methods
444 will be much faster, but will take more space. This corresponds to
445 ``option optimize_for = CODE_SIZE|SPEED`` in a .proto file.
446
447 *options* is a property list whose keys and values are both strings,
448 for example, ``:option ("java_package" "com.yoyodyne.overthruster")``.
449 They are passed along unchanged to the generated .proto file.
450
451 *documentation* is a documentation string that is preserved as a comment
452 in the .proto file.
453
454 *body* consists of any number of calls to ``proto:define-enum``,
455 ``proto:define-message``, ``proto:define-extend`` or ``proto:define-service``.
456
457 ::
458
459   proto:define-enum (type (&key name conc-name alias-for        [Macro]
460                                 options documentation)
461                      &body values)
462
463 Defines a Protobufs enum type and a corresponding Lisp deftype whose name
464 is given by the symbol *type*. If *name* is not supplied, the Protobufs
465 name of the enum is the camel-cased rendition of *type*; otherwise the
466 Protobufs name is the string *name*. If *conc-name* is given, it will
467 be used as the prefix for all of the enum value names. In a .proto file,
468 you can use ``option (lisp_name)`` to override the default name for the
469 enum type in Lisp.
470
471 If *alias-for* is given, no Lisp deftype is defined. Instead, the enum
472 will be used as an alias for a ``member`` type that already exists in Lisp.
473 You can use ``option (lisp_alias)`` in a .proto file to give the Lisp
474 alias for an enum type.
475
476 *options*  is a property list whose keys and values are both strings.
477
478 *documentation* is a documentation string that is preserved as a comment
479 in the .proto file.
480
481 *body* consists of the enum values, each of which is either a symbol
482 or a list either of the form ``(name index)`` or ``(name &key index)``.
483 By default, and if you have not explicitly given an index, the indexes
484 start at 0 and are incremented by 1 for each new enum value. For
485 schema forward and backward compatibility, you should always use the
486 explicit form, either ``(name index)`` or ``(name &key index)``.
487
488 ``proto:define-enum`` can be used only within ``proto:define-schema``
489 or ``proto:define-message``.
490
491 ::
492
493   proto:define-message (type (&key name conc-name alias-for     [Macro]
494                                    options documentation)
495                         &body fields)
496
497 Defines a Protobuf message and a corresponding Lisp defclass whose
498 name is given by the symbol *type*. If *name* is not supplied, the
499 Protobufs name of the class is the camel-cased rendition of *type*
500 (e.g., the class named ``color-wheel``, by default, becomes
501 ``ColorWheel``); otherwise the Protobufs name is the string *name*. If
502 *conc-name* is given, it will be used as the prefix for all of the
503 slot accessor names. In a .proto file, you can use ``option (lisp_name)``
504 to override the default name for the class in Lisp.
505
506 If *alias-for* is given, no Lisp defclass is defined. Instead, the
507 message will be used as an alias for a class that already exists in
508 Lisp. This feature is intended to be used to define messages that will
509 be serialized from existing Lisp classes; unless you get the slot names,
510 readers and writers exactly right for each field, it will be the case
511 that trying to (de)serialize into a(n aliased) Lisp object won't work.
512 You can use ``option (lisp_alias)`` in a .proto file to give the Lisp
513 alias for the class corresponding to a message.
514
515 *options*  is a property list whose keys and values are both strings.
516
517 *documentation* is a documentation string that is preserved as a comment
518 in the .proto file.
519
520 The body *fields* consists of fields, ``proto:define-enum``,
521 ``proto:define-message`` or ``proto:define-extension`` forms.
522
523 Fields take the form ``(slot &key index type name default reader writer)``.
524 *slot* can be either a symbol giving the slot name or a list of the
525 form ``(slot index)``. By default, the field indexes start at 1 and
526 are incremented by 1 for each new field value. *type* is the type of
527 the slot. For schema forward and backward compatibility, you should
528 always use either the ``(slot index)`` form or supply ``:index``.
529
530 *name* can be used to override the defaultly generated Protobufs field
531 name (for example, a Lisp field called ``color-name``, by default,
532 becomes ``color_name``). *default* is the default value for the
533 slot. *reader* is the name of a Lisp slot reader function to use to
534 get the value during serialization, as opposed to using
535 ``slot-value``; this is meant to be used when aliasing an existing
536 class. *writer* can be similarly used to name a Lisp slot writer
537 function.
538
539 Note that the Protobufs does not support full Lisp type expressions in
540 the types of fields. The following type expressions are supported:
541
542  - ``integer``, optionally with upper and lower bounds
543  - ``signed-byte``, which correspond to ``proto:int32`` or ``proto:int64``
544  - ``unsigned-byte``, which correspond to ``proto:uint32`` or ``proto:uint64``
545  - ``float`` and ``double-float``
546  - ``string``and ``character``
547  - ``(array (unsigned-byte 8))``, which corresponds to ``proto:byte-vector``
548  - ``boolean``
549  - ``(member ...)``, where all the members are symbols or keywords or ``nil``
550  - the name of a class that corresponds to another Protobufs message
551  - ``(proto:list-of <T>)``, where ``<T>`` is any of the above types
552  - ``(proto:vector-of <T>)``, where ``<T>`` is any of the above types
553  - ``(or <T> null)``, where ``<T>`` is any of the above types
554
555 ``member`` corresponds to a Protobufs ``enum``. ``(or <T> null)``
556 corresponds to an optional field. ``proto:list-of`` corresponds to a
557 repeated field, and the Lisp slot will be typed as a list. ``proto:vector-of``
558 corresponds to a repeated field, and the Lisp slot will be typed as an
559 adjustable array with a fill pointer. The other types correspond to
560 the various Protobufs scalar field types.
561
562 ``proto:define-message`` can be used only within ``proto:define-schema``
563 or ``proto:define-message``.
564
565 ::
566
567   proto:define-extension (from to)                              [Macro]
568
569 Defines a field extension for the indexes from *from* to *to*.
570 *from* and *to* are positive integers ranging from 1 to 2^29 - 1.
571 *to* can also be the token ``max``, i.e., 2^29 - 1.
572
573 Once an extension to a message has been defined, you can use
574 ``proto:define-extends`` to add new fields.
575
576 ``proto:define-extension`` can be used only within ``proto:define-message``.
577
578 In non-Lisp implementations of Protobufs, you set and get the value
579 of an extension using functions like ``SetExtension()`` and
580 ``GetExtension()``. For example, if you extended a ``Color`` message
581 to have an ``opacity`` field, you would set the field using something
582 like this::
583
584   Color color;
585   color.SetExtension(opacity, 0.5);
586
587 In Common Lisp Protobufs, you can just use an ordinary slot accessor::
588
589   (let ((color (make-instance 'color)))
590     (setf (color-opacity color) 0.5))
591
592 ::
593
594   proto:define-extend (type (&key name conc-name                [Macro]
595                                   options documentation)
596                        &body fields)
597
598 Defines a Protobuf ``extend``, that is, an extension to an existing
599 message (and corresponding Lisp class) that has additional fields that
600 were reserved by ``proto:define-extension``. *type* and *name* are as
601 for ``proto:define-message``. Note that no new Lisp class is defined;
602 the additional slots are implemented as getter and setter methods on
603 a closed-over variable. The other options, such as *conc-name* and
604 *alias-for* are take from the extended message.
605
606 *options*  is a property list whose keys and values are both strings.
607
608 *documentation* is a documentation string that is preserved as a comment
609 in the .proto file.
610
611 The body *fields* consists only of fields, which take the same form as
612 they do for ``proto:define-message``.
613
614 ``proto:define-extend`` can be used only within ``proto:define-schema``
615 or ``proto:define-message``.
616
617 ::
618
619   proto:define-service (type (&key name                         [Macro]
620                                    options documentation)
621                         &body method-specs)
622
623 Defines a Protobufs service named *type* and corresponding Lisp generic
624 functions for all its methods. If *name* is not supplied, the Protobufs
625 name of the service is the camel-cased rendition of *type*; otherwise
626 the Protobufs name is the string *name*.
627
628 *options*  is a property list whose keys and values are both strings.
629
630 *documentation* is a documentation string that is preserved as a comment
631 in the .proto file.
632
633 The body is a set of method specs of the form
634 ``(name (input-type [=>] output-type &key streams) &key options documentation)``.
635
636 For each method spec, *name* is a symbol naming the RPC method.
637 *input-type* and *output-type* give the input and output types of the method;
638 they may either be symbols or a list of the form ``(type &key name)``.
639 You can optionally include the symbol ``=>`` between the input and
640 output types; this seems to improve readability.
641
642 *streams* is also the name of a type, and provides a hook to RPC
643 implementations that implement "streaming".
644
645 ``proto:define-service`` can only be used within ``proto:define-schema``.
646
647
648 Protobufs types
649 ~~~~~~~~~~~~~~~
650
651 The following types are defined in the ``protobufs`` package:
652
653  - ``proto:int32``, which corresponds to the Protobufs ``int32`` type
654  - ``proto:int64``, which corresponds to the Protobufs ``int64`` type
655  - ``proto:uint32``, which corresponds to the Protobufs ``uint32`` type
656  - ``proto:uint64``, which corresponds to the Protobufs ``uint64`` type
657  - ``proto:sint32``, which corresponds to the Protobufs ``sint32`` type
658  - ``proto:sint64``, which corresponds to the Protobufs ``sint64`` type
659  - ``proto:fixed32``, which corresponds to the Protobufs ``fixed32`` type
660  - ``proto:fixed64``, which corresponds to the Protobufs ``fixed64`` type
661  - ``proto:sfixed32``, which corresponds to the Protobufs ``sfixed32`` type
662  - ``proto:sfixed64``, which corresponds to the Protobufs ``sfixed32`` type
663  - ``proto:byte-vector``, which corresponds to the Protobufs ``bytes`` type
664  - ``proto:list-of``, which corresponds to a repeated field
665  - ``proto:vector-of``, which corresponds to a repeated field
666
667 The following existing Lisp type correspond to other Protobufs types:
668
669  - ``string`` is the Protobufs UTF-8 encoded ``string`` type
670  - ``boolean``  is the Protobufs ``bool`` type
671  - ``float``  is the Protobufs ``float`` type
672  - ``double-float``  is the Protobufs ``double`` type
673  - ``member`` of a set of keywords generates a Protobufs ``enum`` type
674
675 Note that ``(or <T> null)`` corresponds to an optional field.
676
677
678 Protobufs service stubs
679 ~~~~~~~~~~~~~~~~~~~~~~~
680
681 When you use the ``proto:define-service`` macro to define a service
682 with some methods, the macro defines "stubs" (CLOS generic functions)
683 for each of the methods in the service. Each method named ``foo`` gets
684 a client stub and a server stub whose signatures are, respectively::
685
686   call-foo  (rpc-channel request &key callback) => response
687   foo-impl  (rpc-channel request) => response
688
689 These methods are interned in a different lisp package, ``XXX-RPC``,
690 where ``XXX`` is the name of the lisp package into which the rest of
691 the schema's symbols are interned. This is done so that message field
692 accessors methods can't collide with the stubs.
693
694 The type of *rpc-channel* is unspecified, but is meant to be a
695 "channel" over which the RPC call will be done. The types of *request*
696 and *response* are message classes that were defined via
697 Protobufs. *callback* is a function of two arguments, the RPC channel
698 and the response; it is intended for use by asynchronous RPC calls.
699
700 For example, this fragment defines four stubs::
701
702   (proto:define-service color-wheel ()
703     (get-color (get-color-request color))
704     (add-color (add-color-request color)))
705
706 The client stubs are ``call-get-color`` and ``call-add-color``, the
707 server stubs are ``get-color-impl`` and ``add-color-impl``. An RPC
708 library will implement a method for the client stub. You must fill in
709 the server stub yourself; it will implement the desired functionality.
710
711 The client stub also gets a single method defined for it that looks like
712 something like this::
713
714   (defmethod call-foo (rpc-channel (request input-type) &key callback)
715     (let ((call (and *rpc-package* *rpc-call-function*)))
716       (funcall call rpc-channel method request :callback callback)))
717
718 where *rpc-channel*, *request* and *callback* are as above.
719 The special variables ``*rpc-package*`` and ``*rpc-call-function*``
720 are filled in when the RPC package is loaded. *method* is the
721 ``proto:protobuf-method`` that describes the method; this is
722 included so that the RPC implementation can determine what type
723 of response object to create, what timeout to use, etc.
724
725 It is beyond the scope of this Protobufs library to provide the RPC
726 service; that is the domain of another library.
727
728
729 Serializing and deserializing
730 =============================
731
732 You can serialize from Lisp objects or deserialize into Lisp objects
733 using either the fast and compact Protobufs wire format, or the
734 human-readable text format.
735
736
737 Wire format
738 -----------
739
740 ::
741
742   proto:serialize-object-to-stream (object type                 [Function]
743                                     &key stream visited)
744
745 Serializes the object *object* of type *type* onto the stream *stream*
746 using the wire format. *type* is the Lisp name of a Protobufs message
747 (often the name of a Lisp class) or a ``proto:protobuf-message`` object.
748 *type* defaults to the class of *object*
749
750 The element type of *stream* must be ``(unsigned-byte 8)``.
751
752 *visited* is an ``eql`` hash table used to cache object sizes. If it is
753 supplied, it will be cleared before it is used; otherwise, a fresh table
754 will be created.
755
756 The returned value is a byte vector containing the serialized object.
757 If the stream is ``nil``, the buffer is not actually written anywhere.
758
759 ::
760
761   proto:serialize-object (object type buffer                    [Generic function]
762                           &optional start visited)
763
764 Serializes the object *object* of type *type* into the byte array
765 *buffer* using the wire format. *type* is the Lisp name of a Protobufs
766 message (often the name of a Lisp class) or a ``proto:protobuf-message``
767 object. *type* defaults to the class of *object*. The buffer is assumed
768 to be large enough to hold the serialized object; if it is not, an
769 out-of-bounds condition may be signaled.
770
771 The object is serialized using the wire format into the byte array
772 (i.e., a vector whose type is ``(unsigned-byte 8)``) given by *buffer*,
773 starting at the fixnum index *start* .
774
775 *visited* is an ``eql`` hash table used to cache object sizes.
776
777 The returned values are the modified buffer containing the serialized
778 object and the index that points one past the last serialized byte in
779 the buffer, which will be the number of bytes required to serialize the
780 object if *start* was 0.
781
782 Note that ``proto:serialize-object`` will not correctly serialize a
783 set of objects that has cycles. You must resolve these yourself.
784
785 ::
786
787   proto:deserialize-object-from-stream (type &key stream)       [Function]
788
789 Deserializes an object of the given type *type* as a Protobuf object.
790 *type* is the Lisp name of a Protobufs message (usually the name of a
791 Lisp class) or a ``proto:protobuf-message``.
792
793 The element type of *stream* must be ``(unsigned-byte 8)``.
794
795 The returned value is the deserialized object.
796
797 ::
798
799   proto:deserialize-object (type buffer &optional start end)    [Generic function]
800
801 Deserializes an object of the given type *type* as a Protobufs object.
802 *type* is the Lisp name of a Protobufs message (usually the name of a
803 Lisp class) or a ``proto:protobuf-message``.
804
805 The encoded bytes come from the byte array given by *buffer*, starting
806 at the fixnum index *start* up to the end of the buffer, given by *end*.
807 *start* defaults to 0, *end*' defaults to the length of the buffer.
808
809 If a zero byte is encountered in in the "tag position" during
810 deserialization, this is interpreted as an "end of object" marker
811 and deserialization stops.
812
813 The returned values are the deserialized object and the index into the
814 buffer at which the deserialization ended.
815
816 ::
817
818   proto:object-size (object type &optional visited)             [Generic function]
819
820 Computes the size in bytes of the object *object* of type *type*.
821 *type* is the Lisp name of a Protobufs message (usually the name of a
822 Lisp class) or a ``proto:protobuf-message``. *type* defaults to the
823 class of *object*
824
825 *visited* is an ``eql`` hash table used to cache object sizes.
826
827 The returned value is the size of the serialized object in bytes.
828
829
830 Text format
831 -----------
832
833 ::
834
835   proto:print-text-format (object &optional type                [Function]
836                            &key stream suppress-line-breaks)
837
838 Prints the object *object* of type *type* onto the stream *stream* using
839 the textual format. *type* defaults to the class of *object*.
840
841 If *suppress-line-breaks* is true, all the output is put on a single line.
842
843 ::
844
845   proto:parse-text-format (type &key stream)                    [Function]
846
847 Parses the textual format of an object of the given type *type*. *type*
848 is the Lisp name of a Protobufs message (usually the name of a Lisp
849 class) or a ``proto:protobuf-message``. The input is read from the
850 stream *stream*.
851
852 The returned value is the object.
853
854
855 Other API functions
856 ===================
857
858 Extensions functions
859 --------------------
860
861 ::
862
863 proto:get-extension (object slot)                               [Generic function]
864
865 Returns the value of the extended slot *slot* in the object *object*.
866
867 Since you can just use the ordinary slot reader function, you should
868 not need to call ``proto:get-extension``. It is included for compatibility
869 with other Protobufs APIs.
870
871 ::
872
873 proto:set-extension (object slot value)                         [Generic function]
874
875 Sets the value of the extended slot *slot* in the object *object*
876 to *value*.
877
878 Since you can just use the ordinary slot writer function, you should
879 not need to call ``proto:set-extension``. It is included for compatibility
880 with other Protobufs APIs.
881
882 ::
883
884 proto:has-extension (object slot)                               [Generic function]
885
886 Returns true iff the object *object* has any value for the extended
887 slot *slot*.
888
889 ::
890
891 proto:clear-extension (object slot)                             [Generic function]
892
893 Removes the value for the extended slot *slot* in the object *object*.
894
895
896 Initialization functions
897 ------------------------
898
899 ::
900
901   proto:object-initialized-p (object type)                      [Generic function]
902
903 Returns true iff all of the fields of *object* of type *type* are
904 initialized, i.e., there are no fields whose value is unbound.
905
906 ::
907
908   proto:slot-initialized-p (object type slot)                   [Generic function]
909
910 Returns true iff the field *slot* of *object* of type *type* is
911 initialized, i.e., there are no fields whose value is unbound.
912
913 ::
914
915   proto:reinitialize-object (object type)                       [Generic function]
916
917 Initializes all of the fields of *object* of type *type* to their
918 default values.
919
920
921 Python compatibility functions
922 ------------------------------
923
924 By popular demand, the Protobufs library provides an API that is very
925 similar to the API of the Python Protobufs library.
926
927 ::
928
929   proto:is-initialized (object)                                 [Generic function]
930
931 Returns true iff all of the fields of *object* are initialized, i.e.,
932 there are no fields whose value is unbound.
933
934 ::
935
936   proto:has-field (object slot)                                 [Generic function]
937
938 Returns true iff the field *slot* is initialized in *object*.
939
940 ::
941
942   proto:clear (object)                                          [Generic function]
943
944 Initializes all of the fields of *object* to their default values.
945
946 ::
947
948   proto:serialize (object &optional buffer start end)           [Generic function]
949
950 Serializes *object* into *buffer* using the wire format, starting at the
951 index *start* and going no further than *end*. *object* is an object
952 whose Lisp class corresponds to a Protobufs message.
953
954 ::
955
956   proto:merge-from-array (object buffer &optional start end)    [Generic function]
957
958 Deserializes the object encoded in *buffer* into *object*, starting at
959 the index *start* and ending at *end*. *object* is an object whose Lisp
960 class corresponds to a Protobufs message.
961
962 ::
963
964   proto:octet-size (object)                                     [Generic function]
965
966 Returns the number of bytes required to serialize *object* using the
967 wire format. *object* is an object whose Lisp class corresponds to a
968 Protobufs message.
969
970
971 Lisp-only extensions
972 ====================
973
974 CL-Protobufs includes some Lisp-only extensions that have no
975 counterpart in Protobufs, but which "ground out" to compatible
976 Protobufs code.
977
978
979 Type aliases
980 ------------
981
982 ::
983
984   proto:define-type-alias (type (&key name alias-for            [Macro]
985                                       documentation)
986                            &key lisp-type proto-type
987                                 serializer deserializer)
988
989 Defines a Lisp type alias named *type* whose Lisp type is *lisp-type*
990 and whose Protobufs type is *proto-type*.  *lisp-type* must be a valid
991 Lisp type expression; *proto-type* myst be a Protobufs primitive type
992 (e.g., ``int32``, ``string``).
993
994 *serializer* is a function of one argument that takes an object of
995 type *lisp-type* and returns an object having the Protobufs primitive
996 type *proto-type*. *deserializer* is a function of one argument that
997 takes an object of type *proto-type* and returns an object having the
998 type *lisp-type*.
999
1000 If *name* is not supplied, the Protobufs name of the type alias is the
1001 camel-cased rendition of *type*; otherwise the Protobufs name is the
1002 string *name*.
1003
1004 If *alias-for* is given, no Lisp deftype for ``type`` is
1005 defined. Instead, the type alias is assumed to refer to a
1006 previously-defined Lisp type.
1007
1008 For example, this Lisp schema::
1009
1010   (proto:define-schema revision-history
1011       (:package revision-history)
1012     (proto:define-type-alias date ()
1013       :lisp-type integer
1014       :proto-type string
1015       :serializer integer-to-date
1016       :deserializer date-to-integer)
1017     (proto:define-message revision ()
1018       (proto:define-message metadata ()
1019         (author :type (or null string))
1020         (revision :type (or null string))
1021         (date :type (or null date)))
1022       (name :type string)
1023       (description :type string)))
1024
1025 will generate this Protobufs schema::
1026
1027   message Revision {
1028     message Metadata {
1029       optional string author = 1;
1030       optional string revision = 2;
1031       // alias maps Lisp integer to Protobufs string
1032       optional string date = 3;
1033     }
1034     required string name = 1;
1035     required string description = 2;
1036   }