 (defmacro Go--slice-len (slice)    `(car (cdr (cdr ,slice))))
 (defmacro Go--slice-cap (slice)    `(cdr (cdr (cdr ,slice))))
 
-;; Setters (note that slice offset is conceptually immutable).
+;; Setters.
 (defmacro Go--slice-data! (slice data)
   (declare (indent 1))
   `(setcar ,slice ,data))
+(defmacro Go--slice-offset! (slice offset)
+  (declare (indent 1))
+  `(setcar (cdr ,slice) ,offset))
 (defmacro Go--slice-len! (slice len)
   (declare (indent 1))
   `(setcar (cdr (cdr ,slice)) ,len))

;;; -*- lexical-binding: t -*-

;; Constructors.
(defun Go--make-slice (len zero-val)
  (cons (make-vector cap zero-val)
        (cons 0 ;; offset
              (cons len len))))
(defun Go--make-slice-cap (len cap zero-val)
  (if (= len cap)
      (Go--make-slice len zero-val)
    (let ((data (make-vector cap nil)))
      (dotimes (i len)
        (aset data i zero-val))
      (cons data
            (cons 0
                  (cons len cap))))))
(defun Go--make-slice-from-list (&rest vals)
  (let* ((data (vconcat vals))
         (len (length data)))
    (cons data
          (cons 0 ;; offset
                (cons len len)))))

;; Getters.
(defmacro Go--slice-data (slice)   `(car ,slice))

        ;; then re-set slice data with `vconcat' of old and new data.
        (let ((new-data (make-vector 16 nil)))
          (aset new-data 0 val)
          ;; For slices with offset with should take sub-vector
          ;; to avoid memory leaks.
          (Go--slice-data! slice
            (vconcat (if (Go--slice-fast? slice)
                         (Go--slice-data slice)
                       (substring (Go--slice-data slice)
                                  (Go--slice-offset slice)))
                     new-data))
          (Go--slice-cap! slice
                  (+ (Go--slice-cap slice)
                     (length new-data)))
          (unless (Go--slice-fast? slice)
            (Go--slice-offset! slice 0)))
      ;; Insert new value directly.
      (Go--slice-set slice pos val))
    slice))
