1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; Confidential and proprietary information of ITA Software, Inc. ;;;
5 ;;; Copyright (c) 2012 ITA Software, Inc. All rights reserved. ;;;
7 ;;; Original author: Scott McKay ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11 (in-package "PROTO-IMPL")
14 ;;; Protocol buffers wire format
18 ;; Serialize 'val' of primitive type 'type' into the buffer
19 (defun serialize-prim (val type field buffer index)
20 "Serializes a Protobufs primitive (scalar) value into the buffer at the given index.
21 The value is given by 'val', the primitive type by 'type'.
22 'field' is the protobuf-field describing the value.
23 Modifies the buffer in place, and returns the new index into the buffer."
24 (declare (type (simple-array (unsigned-byte 8)) buffer)
26 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
29 (let* ((tag (ilogior $wire-type-varint (iash (proto-index field) 3)))
30 (idx (encode-uint32 tag buffer index)))
31 (declare (type (unsigned-byte 32) tag)
33 (encode-uint32 val buffer idx)))
35 (let* ((tag (ilogior $wire-type-varint (iash (proto-index field) 3)))
36 (idx (encode-uint32 tag buffer index)))
37 (declare (type (unsigned-byte 32) tag)
39 (encode-uint64 val buffer idx)))
41 (let* ((tag (ilogior $wire-type-varint (iash (proto-index field) 3)))
42 (idx (encode-uint32 tag buffer index)))
43 (declare (type (unsigned-byte 32) tag)
45 (encode-uint32 (zig-zag-encode32 val) buffer idx)))
47 (let* ((tag (ilogior $wire-type-varint (iash (proto-index field) 3)))
48 (idx (encode-uint32 tag buffer index)))
49 (declare (type (unsigned-byte 32) tag)
51 (encode-uint64 (zig-zag-encode64 val) buffer idx)))
53 (let* ((tag (ilogior $wire-type-32bit (iash (proto-index field) 3)))
54 (idx (encode-uint32 tag buffer index)))
55 (declare (type (unsigned-byte 32) tag)
57 (encode-fixed32 val buffer idx)))
59 (let* ((tag (ilogior $wire-type-32bit (iash (proto-index field) 3)))
60 (idx (encode-uint32 tag buffer index)))
61 (declare (type (unsigned-byte 32) tag)
63 (encode-sfixed32 val buffer idx)))
65 (let* ((tag (ilogior $wire-type-64bit (iash (proto-index field) 3)))
66 (idx (encode-uint32 tag buffer index)))
67 (declare (type (unsigned-byte 32) tag)
69 (encode-fixed64 val buffer idx)))
71 (let* ((tag (ilogior $wire-type-64bit (iash (proto-index field) 3)))
72 (idx (encode-uint32 tag buffer index)))
73 (declare (type (unsigned-byte 32) tag)
75 (encode-sfixed64 val buffer idx)))
77 (let* ((tag (ilogior $wire-type-string (iash (proto-index field) 3)))
78 (idx (encode-uint32 tag buffer index)))
79 (declare (type (unsigned-byte 32) tag)
81 (encode-octets (babel:string-to-octets val :encoding :utf-8) buffer idx)))
83 (let* ((tag (ilogior $wire-type-string (iash (proto-index field) 3)))
84 (idx (encode-uint32 tag buffer index)))
85 (declare (type (unsigned-byte 32) tag)
87 (encode-octets val buffer idx)))
89 (let* ((tag (ilogior $wire-type-varint (iash (proto-index field) 3)))
90 (idx (encode-uint32 tag buffer index)))
91 (declare (type (unsigned-byte 32) tag)
93 (encode-uint32 (if val 1 0) buffer idx)))
95 (let* ((tag (ilogior $wire-type-32bit (iash (proto-index field) 3)))
96 (idx (encode-uint32 tag buffer index)))
97 (declare (type (unsigned-byte 32) tag)
99 (encode-single val buffer idx)))
101 (let* ((tag (ilogior $wire-type-64bit (iash (proto-index field) 3)))
102 (idx (encode-uint32 tag buffer index)))
103 (declare (type (unsigned-byte 32) tag)
105 (encode-double val buffer idx)))
106 ;; A few of our homegrown types
108 (let* ((tag (ilogior $wire-type-string (iash (proto-index field) 3)))
109 (idx (encode-uint32 tag buffer index))
110 (val (format nil "~A:~A" (package-name (symbol-package val)) (symbol-name val))))
111 ;; Call 'string' in case we are trying to serialize a symbol name
112 (declare (type (unsigned-byte 32) tag)
114 (encode-octets (babel:string-to-octets val :encoding :utf-8) buffer idx)))
115 ((:date :time :datetime :timestamp)
116 (let* ((tag (ilogior $wire-type-64bit (iash (proto-index field) 3)))
117 (idx (encode-uint32 tag buffer index)))
118 (declare (type (unsigned-byte 32) tag)
120 (encode-uint64 val buffer idx))))))
122 (defun serialize-packed (values type field buffer index)
123 "Serializes a set of packed values into the buffer at the given index.
124 The values are given by 'values', the primitive type by 'type'.
125 'field' is the protobuf-field describing the value.
126 Modifies the buffer in place, and returns the new index into the buffer."
127 (declare (type (simple-array (unsigned-byte 8)) buffer)
129 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
130 (let* ((wtype (ecase type
131 ((:int32 :int64) $wire-type-varint)
132 ((:uint32 :uint64) $wire-type-varint)
133 ((:sint32 :sint64) $wire-type-varint)
134 ((:fixed32 :sfixed32) $wire-type-32bit)
135 ((:fixed64 :sfixed64) $wire-type-64bit)
136 ((:float) $wire-type-32bit)
137 ((:double) $wire-type-64bit)))
138 (tag (ilogior wtype (iash (proto-index field) 3)))
139 (idx (encode-uint32 tag buffer index)))
140 (declare (type (unsigned-byte 32) wtype tag)
142 (multiple-value-bind (full-len len)
143 (packed-size values type field)
144 (declare (type fixnum len) (ignore full-len))
145 (setq idx (encode-uint32 len buffer idx)))
148 (dolist (val values idx)
149 (setq idx (encode-uint32 val buffer idx))))
151 (dolist (val values idx)
152 (setq idx (encode-uint64 val buffer idx))))
154 (dolist (val values idx)
155 (setq idx (encode-uint32 (zig-zag-encode32 val) buffer idx))))
157 (dolist (val values idx)
158 (setq idx (encode-uint64 (zig-zag-encode64 val) buffer idx))))
160 (dolist (val values idx)
161 (setq idx (encode-fixed32 val buffer idx))))
163 (dolist (val values idx)
164 (setq idx (encode-sfixed32 val buffer idx))))
166 (dolist (val values idx)
167 (setq idx (encode-fixed64 val buffer idx))))
169 (dolist (val values idx)
170 (setq idx (encode-sfixed64 val buffer idx))))
172 (dolist (val values idx)
173 (setq idx (encode-single val buffer idx))))
175 (dolist (val values idx)
176 (setq idx (encode-double val buffer idx))))))))
178 ;; Serialize 'val' of enum type 'type' into the buffer
179 (defun serialize-enum (val enum field buffer index)
180 "Serializes a Protobufs enum value into the buffer at the given index.
181 The value is given by 'val', the enum type by 'enum'.
182 'field' is the protobuf-field describing the value.
183 Modifies the buffer in place, and returns the new index into the buffer."
184 (declare (type (simple-array (unsigned-byte 8)) buffer)
186 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
187 (let* ((val (let ((e (find val (proto-values enum) :key #'proto-value)))
188 (and e (proto-index e))))
189 (tag (ilogior $wire-type-varint (iash (proto-index field) 3)))
190 (idx (encode-uint32 tag buffer index)))
191 (declare (type (unsigned-byte 32) val tag)
193 (encode-uint32 val buffer idx))))
198 ;; Deserialize the next object of type 'type', described by the protobuf field 'field'
199 (defun deserialize-prim (type field buffer index)
200 "Deserializes the next object of primitive type 'type', described by the protobuf-field 'field'.
201 Deserializes from the byte vector 'buffer' starting at 'index'.
202 Returns the value and and the new index into the buffer."
203 (declare (type (simple-array (unsigned-byte 8)) buffer)
205 (declare (ignore field))
206 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
209 (decode-uint32 buffer index))
211 (decode-uint64 buffer index))
213 (multiple-value-bind (val idx)
214 (decode-uint32 buffer index)
215 (values (zig-zag-decode32 val) idx)))
217 (multiple-value-bind (val idx)
218 (decode-uint64 buffer index)
219 (values (zig-zag-decode64 val) idx)))
221 (decode-fixed32 buffer index))
223 (decode-sfixed32 buffer index))
225 (decode-fixed64 buffer index))
227 (decode-sfixed64 buffer index))
229 (multiple-value-bind (val idx)
230 (decode-octets buffer index)
231 (values (babel:octets-to-string val :encoding :utf-8) idx)))
233 (decode-octets buffer index))
235 (multiple-value-bind (val idx)
236 (decode-uint32 buffer index)
237 (values (if (zerop val) nil t) idx)))
239 (decode-single buffer index))
241 (decode-double buffer index))
242 ;; A few of our homegrown types
244 (multiple-value-bind (val idx)
245 (decode-octets buffer index)
246 (let* ((val (babel:octets-to-string val :encoding :utf-8))
247 (colon (position #\: val))
248 (pkg (subseq val 0 colon))
249 (sym (subseq val (i+ colon 1))))
250 (values (intern sym pkg) idx))))
251 ((:date :time :datetime :timestamp)
252 (decode-uint64 buffer index)))))
254 (defun deserialize-packed (type field buffer index)
255 "Deserializes the next packed values of type 'type', described by the protobuf-field 'field'.
256 Deserializes from the byte vector 'buffer' starting at 'index'.
257 Returns the value and and the new index into the buffer."
258 (declare (type (simple-array (unsigned-byte 8)) buffer)
260 (declare (ignore field))
261 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
262 (multiple-value-bind (len idx)
263 (decode-uint32 buffer index)
264 (declare (type (unsigned-byte 32) len)
266 (let ((end (i+ idx len)))
267 (declare (type (unsigned-byte 32) end))
268 (with-collectors ((values collect-value))
271 (return-from deserialize-packed (values values idx)))
272 (multiple-value-bind (val nidx)
275 (decode-uint32 buffer idx))
277 (decode-uint64 buffer idx))
279 (multiple-value-bind (val idx)
280 (decode-uint32 buffer idx)
281 (values (zig-zag-decode32 val) idx)))
283 (multiple-value-bind (val idx)
284 (decode-uint64 buffer idx)
285 (values (zig-zag-decode64 val) idx)))
287 (decode-fixed32 buffer idx))
289 (decode-sfixed32 buffer idx))
291 (decode-fixed64 buffer idx))
293 (decode-sfixed64 buffer idx))
295 (decode-single buffer idx))
297 (decode-double buffer idx)))
299 (setq idx nidx))))))))
301 (defun deserialize-enum (enum field buffer index)
302 "Deserializes the next enum of type 'type', described by the protobuf-field 'field'.
303 Deserializes from the byte vector 'buffer' starting at 'index'.
304 Returns the value and and the new index into the buffer."
305 (declare (type (simple-array (unsigned-byte 8)) buffer)
307 (declare (ignore field))
308 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
309 (multiple-value-bind (val idx)
310 (decode-uint32 buffer index)
311 (let ((val (let ((e (find val (proto-values enum) :key #'proto-index)))
312 (and e (proto-value e)))))
318 (defun prim-size (val type field)
319 "Returns the size in bytes that the primitive object will take when serialized."
320 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
323 (let ((tag (ilogior $wire-type-varint (iash (proto-index field) 3))))
324 (i+ (length32 tag) (length32 val))))
326 (let ((tag (ilogior $wire-type-varint (iash (proto-index field) 3))))
327 (i+ (length32 tag) (length64 val))))
329 (let ((tag (ilogior $wire-type-varint (iash (proto-index field) 3))))
330 (i+ (length32 tag) (length32 (zig-zag-encode32 val)))))
332 (let ((tag (ilogior $wire-type-varint (iash (proto-index field) 3))))
333 (i+ (length32 tag) (length64 (zig-zag-encode64 val)))))
334 ((:fixed32 :sfixed32)
335 (let ((tag (ilogior $wire-type-32bit (iash (proto-index field) 3))))
336 (i+ (length32 tag) 4)))
337 ((:fixed64 :sfixed64)
338 (let ((tag (ilogior $wire-type-64bit (iash (proto-index field) 3))))
339 (i+ (length32 tag) 8)))
341 (let ((tag (ilogior $wire-type-string (iash (proto-index field) 3)))
342 (len (babel:string-size-in-octets val :encoding :utf-8)))
343 (i+ (length32 tag) (length32 len) len)))
345 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
346 (let ((tag (ilogior $wire-type-string (iash (proto-index field) 3)))
348 (i+ (length32 tag) (length32 len) len))))
350 (let ((tag (ilogior $wire-type-varint (iash (proto-index field) 3))))
351 (i+ (length32 tag) 1)))
353 (let ((tag (ilogior $wire-type-32bit (iash (proto-index field) 3))))
354 (i+ (length32 tag) 4)))
356 (let ((tag (ilogior $wire-type-64bit (iash (proto-index field) 3))))
357 (i+ (length32 tag) 8)))
358 ;; A few of our homegrown types
360 (let* ((tag (ilogior $wire-type-string (iash (proto-index field) 3)))
361 (len (i+ (length (package-name (symbol-package val))) 1 (length (symbol-name val)))))
362 (i+ (length32 tag) (length32 len) len)))
363 ((:date :time :datetime :timestamp)
364 (let ((tag (ilogior $wire-type-64bit (iash (proto-index field) 3))))
365 (i+ (length32 tag) 8))))))
367 (defun packed-size (values type field)
368 "Returns the size in bytes that the packed object will take when serialized."
369 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
370 (let ((tag (ilogior $wire-type-varint (iash (proto-index field) 3)))
371 (len (loop for val in values
373 ((:int32 :uint32) (length32 val))
374 ((:int64 :uint64) (length64 val))
375 ((:sint32) (length32 (zig-zag-encode32 val)))
376 ((:sint64) (length64 (zig-zag-encode64 val)))
377 ((:fixed32 :sfixed32) 4)
378 ((:fixed64 :sfixed64) 8)
381 (declare (type (unsigned-byte 32) tag len))
382 ;; Two value: the full size of the packed object, and the size
383 ;; of just the payload
384 (values (i+ (length32 tag) (length32 len) len) len))))
386 (defun enum-size (val enum field)
387 "Returns the size in bytes that the enum object will take when serialized."
388 (let ((val (let ((e (find val (proto-values enum) :key #'proto-value)))
389 (and e (proto-index e))))
390 (tag (ilogior $wire-type-varint (iash (proto-index field) 3))))
391 (declare (type (unsigned-byte 32) tag val))
392 (i+ (length32 tag) (length32 val))))
397 (defun encode-uint32 (val buffer index)
398 "Encodes the unsigned 32-bit integer 'val' as a varint into the buffer
400 Modifies the buffer, and returns the new index into the buffer."
401 (declare (type (unsigned-byte 32) val)
402 (type (simple-array (unsigned-byte 8)) buffer)
404 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
405 ;; Seven bits at a time, least significant bits first
406 (loop do (let ((bits (ldb #.(byte 7 0) val)))
407 (declare (type (unsigned-byte 8) bits))
408 (setq val (ash val -7))
409 (setf (aref buffer index) (ilogior bits (if (zerop val) 0 128)))
412 (values index buffer)) ;return the buffer to improve 'trace'
414 (defun encode-uint64 (val buffer index)
415 "Encodes the unsigned 64-bit integer 'val' as a varint into the buffer
417 Modifies the buffer, and returns the new index into the buffer."
418 (declare (type (unsigned-byte 64) val)
419 (type (simple-array (unsigned-byte 8)) buffer)
421 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
422 (loop do (let ((bits (ldb #.(byte 7 0) val)))
423 (declare (type (unsigned-byte 8) bits))
424 (setq val (ash val -7))
425 (setf (aref buffer index) (ilogior bits (if (zerop val) 0 128)))
428 (values index buffer))
430 (defun encode-fixed32 (val buffer index)
431 "Encodes the unsigned 32-bit integer 'val' as a fixed int into the buffer
433 Modifies the buffer, and returns the new index into the buffer."
434 (declare (type (unsigned-byte 32) val)
435 (type (simple-array (unsigned-byte 8)) buffer)
437 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
439 (let ((byte (ldb #.(byte 8 0) val)))
440 (declare (type (unsigned-byte 8) byte))
441 (setq val (ash val -8))
442 (setf (aref buffer index) byte)
444 (values index buffer))
446 (defun encode-fixed64 (val buffer index)
447 "Encodes the unsigned 64-bit integer 'val' as a fixed int into the buffer
449 Modifies the buffer, and returns the new index into the buffer."
450 (declare (type (unsigned-byte 64) val)
451 (type (simple-array (unsigned-byte 8)) buffer)
453 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
455 (let ((byte (ldb #.(byte 8 0) val)))
456 (declare (type (unsigned-byte 8) byte))
457 (setq val (ash val -8))
458 (setf (aref buffer index) byte)
460 (values index buffer))
462 (defun encode-sfixed32 (val buffer index)
463 "Encodes the signed 32-bit integer 'val' as a fixed int into the buffer
465 Modifies the buffer, and returns the new index into the buffer."
466 (declare (type (signed-byte 32) val)
467 (type (simple-array (unsigned-byte 8)) buffer)
469 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
471 (let ((byte (ldb #.(byte 8 0) val)))
472 (declare (type (unsigned-byte 8) byte))
473 (setq val (ash val -8))
474 (setf (aref buffer index) byte)
476 (values index buffer))
478 (defun encode-sfixed64 (val buffer index)
479 "Encodes the signed 32-bit integer 'val' as a fixed int into the buffer
481 Modifies the buffer, and returns the new index into the buffer."
482 (declare (type (signed-byte 64) val)
483 (type (simple-array (unsigned-byte 8)) buffer)
485 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
487 (let ((byte (ldb #.(byte 8 0) val)))
488 (declare (type (unsigned-byte 8) byte))
489 (setq val (ash val -8))
490 (setf (aref buffer index) byte)
492 (values index buffer))
494 (defun encode-single (val buffer index)
495 "Encodes the single float 'val' into the buffer at the given index.
496 Modifies the buffer, and returns the new index into the buffer."
497 (declare (type single-float val)
498 (type (simple-array (unsigned-byte 8)) buffer)
500 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
501 (let ((bits (single-float-bits val)))
503 (let ((byte (ldb #.(byte 8 0) bits)))
504 (declare (type (unsigned-byte 8) byte))
505 (setq bits (ash bits -8))
506 (setf (aref buffer index) byte)
508 (values index buffer))
510 (defun encode-double (val buffer index)
511 "Encodes the double float 'val' into the buffer at the given index.
512 Modifies the buffer, and returns the new index into the buffer."
513 (declare (type double-float val)
514 (type (simple-array (unsigned-byte 8)) buffer)
516 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
517 (multiple-value-bind (low high)
518 (double-float-bits val)
520 (let ((byte (ldb #.(byte 8 0) low)))
521 (declare (type (unsigned-byte 8) byte))
522 (setq low (ash low -8))
523 (setf (aref buffer index) byte)
526 (let ((byte (ldb #.(byte 8 0) high)))
527 (declare (type (unsigned-byte 8) byte))
528 (setq high (ash high -8))
529 (setf (aref buffer index) byte)
531 (values index buffer))
533 (defun encode-octets (octets buffer index)
534 "Encodes the octets into the buffer at the given index.
535 Modifies the buffer, and returns the new index into the buffer."
536 (declare (type (simple-array (unsigned-byte 8)) buffer)
538 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
539 (let* ((len (length octets))
540 (idx (encode-uint32 len buffer index)))
541 (declare (type fixnum len)
542 (type (unsigned-byte 32) idx))
543 (replace buffer octets :start1 idx)
544 (values (i+ idx len) buffer))))
546 (defun zig-zag-encode32 (val)
547 (check-type val (signed-byte 32))
548 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
549 (logxor (ash val 1) (ash val -31))))
551 (defun zig-zag-encode64 (val)
552 (check-type val (signed-byte 64))
553 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
554 (logxor (ash val 1) (ash val -63))))
559 ;; Decode the value from the buffer at the given index,
560 ;; then return the value and new index into the buffer
561 (defun decode-uint32 (buffer index)
562 "Decodes the next 32-bit varint integer in the buffer at the given index.
563 Returns both the decoded value and the new index into the buffer."
564 (declare (type (simple-array (unsigned-byte 8)) buffer)
566 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
567 ;; Seven bits at a time, least significant bits first
569 for places fixnum upfrom 0 by 7
570 for byte fixnum = (prog1 (aref buffer index) (iincf index))
571 do (setq val (logior val (ash (ldb #.(byte 7 0) byte) places)))
574 (assert (< val #.(ash 1 32)) ()
575 "The value ~D is longer than 32 bits" val)
576 (return (values val index))))))
578 (defun decode-uint64 (buffer index)
579 "Decodes the next 64-bit varint integer in the buffer at the given index.
580 Returns both the decoded value and the new index into the buffer."
581 (declare (type (simple-array (unsigned-byte 8)) buffer)
583 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
584 ;; Seven bits at a time, least significant bits first
586 for places fixnum upfrom 0 by 7
587 for byte fixnum = (prog1 (aref buffer index) (iincf index))
588 do (setq val (logior val (ash (ldb #.(byte 7 0) byte) places)))
590 finally (return (values val index)))))
592 (defun decode-fixed32 (buffer index)
593 "Decodes the next 32-bit unsigned fixed integer in the buffer at the given index.
594 Returns both the decoded value and the new index into the buffer."
595 (declare (type (simple-array (unsigned-byte 8)) buffer)
597 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
598 ;; Eight bits at a time, least significant bits first
601 for places fixnum upfrom 0 by 8
602 for byte fixnum = (prog1 (aref buffer index) (iincf index))
603 do (setq val (logior val (ash byte places))))
604 (values val index))))
606 (defun decode-sfixed32 (buffer index)
607 "Decodes the next 32-bit signed fixed integer in the buffer at the given index.
608 Returns both the decoded value and the new index into the buffer."
609 (declare (type (simple-array (unsigned-byte 8)) buffer)
611 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
612 ;; Eight bits at a time, least significant bits first
615 for places fixnum upfrom 0 by 8
616 for byte fixnum = (prog1 (aref buffer index) (iincf index))
617 do (setq val (logior val (ash byte places))))
618 (when (i= (ldb #.(byte 1 31) val) 1) ;sign bit set, so negative value
619 (decf val #.(ash 1 32)))
620 (values val index))))
622 (defun decode-fixed64 (buffer index)
623 "Decodes the next unsigned 64-bit fixed integer in the buffer at the given index.
624 Returns both the decoded value and the new index into the buffer."
625 (declare (type (simple-array (unsigned-byte 8)) buffer)
627 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
628 ;; Eight bits at a time, least significant bits first
631 for places fixnum upfrom 0 by 8
632 for byte fixnum = (prog1 (aref buffer index) (iincf index))
633 do (setq val (logior val (ash byte places))))
634 (values val index))))
636 (defun decode-sfixed64 (buffer index)
637 "Decodes the next signed 64-bit fixed integer in the buffer at the given index.
638 Returns both the decoded value and the new index into the buffer."
639 (declare (type (simple-array (unsigned-byte 8)) buffer)
641 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
642 ;; Eight bits at a time, least significant bits first
645 for places fixnum upfrom 0 by 8
646 for byte fixnum = (prog1 (aref buffer index) (iincf index))
647 do (setq val (logior val (ash byte places))))
648 (when (i= (ldb #.(byte 1 63) val) 1) ;sign bit set, so negative value
649 (decf val #.(ash 1 64)))
650 (values val index))))
652 (defun decode-single (buffer index)
653 "Decodes the next single float in the buffer at the given index.
654 Returns both the decoded value and the new index into the buffer."
655 (declare (type (simple-array (unsigned-byte 8)) buffer)
657 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
658 ;; Eight bits at a time, least significant bits first
661 for places fixnum upfrom 0 by 8
662 for byte fixnum = (prog1 (aref buffer index) (iincf index))
663 do (setq bits (logior bits (ash byte places))))
664 (when (i= (ldb #.(byte 1 31) bits) 1) ;sign bit set, so negative value
665 (decf bits #.(ash 1 32)))
666 (values (make-single-float bits) index))))
668 (defun decode-double (buffer index)
669 "Decodes the next double float in the buffer at the given index.
670 Returns both the decoded value and the new index into the buffer."
671 (declare (type (simple-array (unsigned-byte 8)) buffer)
673 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
674 ;; Eight bits at a time, least significant bits first
678 for places fixnum upfrom 0 by 8
679 for byte fixnum = (prog1 (aref buffer index) (iincf index))
680 do (setq low (logior low (ash byte places))))
682 for places fixnum upfrom 0 by 8
683 for byte fixnum = (prog1 (aref buffer index) (iincf index))
684 do (setq high (logior high (ash byte places))))
685 ;; High bits are signed, but low bits are unsigned
686 (when (i= (ldb #.(byte 1 31) high) 1) ;sign bit set, so negative value
687 (decf high #.(ash 1 32)))
688 (values (make-double-float low high) index))))
690 (defun decode-octets (buffer index)
691 "Decodes the next octets in the buffer at the given index.
692 Returns both the decoded value and the new index into the buffer."
693 (declare (type (simple-array (unsigned-byte 8)) buffer)
695 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
696 (multiple-value-bind (len idx)
697 (decode-uint32 buffer index)
698 (declare (type (unsigned-byte 32) len)
700 (values (subseq buffer idx (i+ idx len)) (i+ idx len)))))
702 (defun zig-zag-decode32 (val)
703 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
704 (logxor (ash val -1) (- (logand val 1)))))
706 (defun zig-zag-decode64 (val)
707 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
708 (logxor (ash val -1) (- (logand val 1)))))
713 (defun length32 (val)
714 "Returns the length that 'val' will take when encoded as a 32-bit integer."
715 (assert (< val #.(ash 1 32)) ()
716 "The value ~D is longer than 32 bits" val)
717 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
719 (declare (type fixnum size))
721 (setq val (ash val -7))
726 (defun length64 (val)
727 "Returns the length that 'val' will take when encoded as a 64-bit integer."
728 (locally (declare (optimize (speed 3) (safety 0) (debug 0)))
730 (declare (type fixnum size))
732 (setq val (ash val -7))