Browse code
feat: finish delta decoding
Edward Langley authored on 26/10/2023 00:46:12
Showing 1 changed files
Showing 1 changed files
... | ... |
@@ -3,7 +3,9 @@ |
3 | 3 |
(defclass delta (git-object) |
4 | 4 |
((%repository :initarg :repository :reader repository) |
5 | 5 |
(%base :initarg :base :reader base) |
6 |
- (%commands :initarg :commands :reader commands))) |
|
6 |
+ (%commands :initarg :commands :reader commands) |
|
7 |
+ (%src-size :initarg :src-size :reader src-size) |
|
8 |
+ (%delta-size :initarg :delta-size :reader delta-size))) |
|
7 | 9 |
|
8 | 10 |
(defclass+ ofs-delta (delta) |
9 | 11 |
()) |
... | ... |
@@ -11,8 +13,8 @@ |
11 | 13 |
(defclass+ ref-delta (delta) |
12 | 14 |
()) |
13 | 15 |
|
14 |
-(defun make-ofs-delta (base commands repository) |
|
15 |
- (fw.lu:new 'ofs-delta base commands repository)) |
|
16 |
+(defun make-ofs-delta (base commands repository src-size delta-size) |
|
17 |
+ (fw.lu:new 'ofs-delta base commands repository src-size delta-size)) |
|
16 | 18 |
(defun make-ref-delta (base commands repository) |
17 | 19 |
(fw.lu:new 'ofs-delta base commands repository)) |
18 | 20 |
|
... | ... |
@@ -35,8 +37,18 @@ |
35 | 37 |
:sum (expt 2 n)))) |
36 | 38 |
|
37 | 39 |
(defun expand-copy (copy) |
38 |
- ;; TODO: implement this |
|
39 |
- copy) |
|
40 |
+ (destructuring-bind (command layout numbers) copy |
|
41 |
+ (let* ((next-idx 0) |
|
42 |
+ (parts (map '(vector (unsigned-byte 8)) |
|
43 |
+ (lambda (layout-bit) |
|
44 |
+ (if (= layout-bit 1) |
|
45 |
+ (prog1 (elt numbers next-idx) |
|
46 |
+ (incf next-idx)) |
|
47 |
+ 0)) |
|
48 |
+ (reverse layout)))) |
|
49 |
+ (list command |
|
50 |
+ (fwoar.bin-parser:le->int (subseq parts 0 4)) |
|
51 |
+ (fwoar.bin-parser:le->int (subseq parts 4)))))) |
|
40 | 52 |
|
41 | 53 |
(defun partition-commands (data) |
42 | 54 |
(let ((idx 0)) |
... | ... |
@@ -70,45 +82,47 @@ |
70 | 82 |
(flet ((advance () |
71 | 83 |
(prog1 (elt buf idx) |
72 | 84 |
(incf idx)))) |
73 |
- (let* ((c (advance)) |
|
74 |
- (ofs (logand c 127))) |
|
75 |
- (loop |
|
76 |
- do (format t "~&~s ~s ~s" idx c ofs) |
|
77 |
- while (> (logand c 128) 0) |
|
78 |
- do |
|
79 |
- (setf c (advance)) |
|
80 |
- (setf ofs (+ (ash (1+ ofs) |
|
81 |
- 7) |
|
82 |
- (logand c 127)))) |
|
83 |
- (values (- ofs) idx))))) |
|
85 |
+ (loop for c = (advance) |
|
86 |
+ for ofs = (logand c 127) |
|
87 |
+ for morep = (> (logand c 128) 0) |
|
88 |
+ while morep |
|
89 |
+ finally |
|
90 |
+ (return (values (- ofs) idx)))))) |
|
91 |
+ |
|
92 |
+(defun decode-size (buf) |
|
93 |
+ (let ((parts ())) |
|
94 |
+ (loop for raw across buf |
|
95 |
+ for bits = (int->bit-vector raw) |
|
96 |
+ for morep = (= (elt bits 0) 1) |
|
97 |
+ do (push (subseq bits 1) parts) |
|
98 |
+ while morep) |
|
99 |
+ (let ((result (make-array (* 7 (length parts)) |
|
100 |
+ :element-type 'bit))) |
|
101 |
+ (loop for x from 0 by 7 |
|
102 |
+ for part in parts |
|
103 |
+ do |
|
104 |
+ (replace result part :start1 x)) |
|
105 |
+ (values (bit-vector->int result) |
|
106 |
+ (length parts))))) |
|
84 | 107 |
|
85 | 108 |
(defmethod -extract-object-of-type ((type (eql :ofs-delta)) s repository &key offset-from packfile) |
86 | 109 |
(multiple-value-bind (offset consumed) (get-ofs-delta-offset s) |
87 |
- (make-ofs-delta (list packfile |
|
88 |
- (+ offset-from offset)) |
|
89 |
- (partition-commands (chipz:decompress |
|
90 |
- nil |
|
91 |
- (chipz:make-dstate 'chipz:zlib) |
|
92 |
- (subseq s consumed))) |
|
93 |
- repository))) |
|
110 |
+ (let ((compressed-data (chipz:decompress |
|
111 |
+ nil |
|
112 |
+ (chipz:make-dstate 'chipz:zlib) |
|
113 |
+ (subseq s consumed)))) |
|
114 |
+ (multiple-value-bind (src-size consumed-1) (decode-size compressed-data) |
|
115 |
+ (multiple-value-bind (delta-size consumed-2) (decode-size (subseq compressed-data |
|
116 |
+ consumed-1)) |
|
117 |
+ (make-ofs-delta (list packfile |
|
118 |
+ (+ offset-from offset)) |
|
119 |
+ (partition-commands (subseq compressed-data |
|
120 |
+ (+ consumed-1 |
|
121 |
+ consumed-2))) |
|
122 |
+ repository |
|
123 |
+ src-size |
|
124 |
+ delta-size)))))) |
|
94 | 125 |
(defmethod -extract-object-of-type ((type (eql :ref-delta)) s repository &key offset-from) |
95 | 126 |
(make-ref-delta offset-from |
96 | 127 |
(partition-commands s) |
97 | 128 |
repository)) |
98 |
- |
|
99 |
- |
|
100 |
-#+(or) #+(or) #+(or) |
|
101 |
- |
|
102 |
-(defmethod component ((component (eql :tree)) (object git-commit)) |
|
103 |
- (ensure-ref |
|
104 |
- (cadr |
|
105 |
- (fw.lu:v-assoc :tree (metadata object) |
|
106 |
- :test 'string-equal)))) |
|
107 |
-(defmethod component ((component (eql :parents)) (object git-commit)) |
|
108 |
- (coerce (remove-if-not (serapeum:op |
|
109 |
- (string= "parent" _)) |
|
110 |
- (metadata object) |
|
111 |
- :key #'car) |
|
112 |
- 'list)) |
|
113 |
-(defmethod component ((component (eql :message)) (object git-commit)) |
|
114 |
- (data object)) |