Commit ef07dd5bda4ebb6d6e9f63ebf742df7e23029f5f
Read all objects
Charles Lehner committed on 2/8/2016, 4:37:22 AMParent: 95a067249e90995c9d34e46ae4aa937180c1d2f6
Files changed
pack.js | changed |
package.json | changed |
pack.js | ||
---|---|---|
@@ -1,9 +1,9 @@ | ||
1 | -var zlib = require('zlib') | |
2 | 1 | var buffered = require('pull-buffered') |
3 | 2 | var crypto = require('crypto') |
4 | 3 | var pull = require('pull-stream') |
5 | 4 | var toPull = require('stream-to-pull-stream') |
5 | +var Inflate = require('pako/lib/inflate').Inflate | |
6 | 6 | |
7 | 7 | exports.decode = decodePack |
8 | 8 | |
9 | 9 | var objectTypes = [ |
@@ -18,13 +18,48 @@ | ||
18 | 18 | } |
19 | 19 | |
20 | 20 | function createHash(type) { |
21 | 21 | var hash = crypto.createHash(type) |
22 | - return pull.through(function (data) { | |
23 | - hash.update(data) | |
24 | - }) | |
22 | + var hasher = pull.through(hash.update.bind(hash)) | |
23 | + hasher.digest = hash.digest.bind(hash) | |
24 | + return hasher | |
25 | 25 | } |
26 | 26 | |
27 | +function inflateBytes(read) { | |
28 | + var inflate = new Inflate() | |
29 | + var ended, dataOut | |
30 | + | |
31 | + inflate.onData = function (data) { | |
32 | + dataOut = new Buffer(data) | |
33 | + // console.error('inflated data', data.length) | |
34 | + } | |
35 | + | |
36 | + inflate.onEnd = function (status) { | |
37 | + ended = (status === 0) ? true : new Error(inflate.msg) | |
38 | + // console.error('inflated end', status, ended) | |
39 | + } | |
40 | + | |
41 | + return function (abort, cb) { | |
42 | + if (ended) return cb(ended) | |
43 | + read(abort, function next(end, data) { | |
44 | + if (end === true) { | |
45 | + end = null | |
46 | + data = [] | |
47 | + } | |
48 | + if (ended = end) return cb(end) | |
49 | + if (data.length > 1) return cb(new Error('got more than one byte')) | |
50 | + dataOut = null | |
51 | + inflate.push(data, end === true) | |
52 | + if (dataOut) | |
53 | + cb(null, dataOut) | |
54 | + else if (ended) | |
55 | + cb(ended) | |
56 | + else | |
57 | + read(null, next) | |
58 | + }) | |
59 | + } | |
60 | +} | |
61 | + | |
27 | 62 | function decodePack(onEnd, read) { |
28 | 63 | if (read === undefined) |
29 | 64 | return decodePack.bind(this, onEnd) |
30 | 65 | |
@@ -35,8 +70,11 @@ | ||
35 | 70 | var readByte = b.chunks(1) |
36 | 71 | var readWord = b.chunks(4) |
37 | 72 | var readChecksum = b.chunks(20) |
38 | 73 | var expectChecksum = false |
74 | + var opts = { | |
75 | + verbosity: 2 | |
76 | + } | |
39 | 77 | |
40 | 78 | function readHeader(cb) { |
41 | 79 | readWord(null, function (end, header) { |
42 | 80 | if (ended = end) return cb(end) |
@@ -61,8 +99,10 @@ | ||
61 | 99 | function readNumObjects(cb) { |
62 | 100 | readWord(null, function (end, word) { |
63 | 101 | if (ended = end) return cb(end) |
64 | 102 | numObjects = word.readUInt32BE() |
103 | + if (opts.verbosity >= 1) | |
104 | + console.error(numObjects + ' objects') | |
65 | 105 | readObject(null, cb) |
66 | 106 | }) |
67 | 107 | } |
68 | 108 | |
@@ -71,43 +111,41 @@ | ||
71 | 111 | // https://codewords.recurse.com/images/three/varint.svg |
72 | 112 | readByte(null, function (end, buf) { |
73 | 113 | if (ended = end) return cb(end) |
74 | 114 | var firstByte = buf[0] |
75 | - type = objectTypes[(firstByte & 0b01110000) >> 4] | |
76 | - value = firstByte & 0b00001111 | |
115 | + type = objectTypes[(firstByte >> 4) & 7] | |
116 | + value = firstByte & 15 | |
77 | 117 | console.error('byte1', firstByte, firstByte.toString(2), value, value.toString(2)) |
78 | 118 | shift = 4 |
79 | 119 | checkByte(firstByte) |
80 | 120 | }) |
81 | 121 | |
82 | 122 | function checkByte(byte) { |
83 | - if (byte & 0b10000000) | |
123 | + if (byte & 0x80) | |
84 | 124 | readByte(null, gotByte) |
85 | 125 | else |
86 | 126 | cb(null, type, value) |
87 | 127 | } |
88 | 128 | |
89 | 129 | function gotByte(end, buf) { |
90 | 130 | if (ended = end) return cb(end) |
91 | 131 | var byte = buf[0] |
92 | - value |= ((byte & 0b01111111) << shift) | |
132 | + value += (byte & 0x7f) << shift | |
93 | 133 | shift += 7 |
94 | 134 | console.error('byte', byte, byte.toString(2), value, value.toString(2)) |
95 | 135 | checkByte(byte) |
96 | 136 | } |
97 | 137 | } |
98 | 138 | |
99 | 139 | function getObject(cb) { |
100 | 140 | readVarInt(function (end, type, length) { |
141 | + console.error('read var int', end, type, length) | |
101 | 142 | if (end === true && expectChecksum) |
102 | 143 | onEnd(new Error('Missing checksum')) |
103 | 144 | if (ended = end) return cb(end) |
104 | - console.error('length', length) | |
105 | 145 | numObjects-- |
106 | - cb(null, type, pull( | |
107 | - b.take(length), | |
108 | - toPull(zlib.createInflate()) | |
109 | - )) | |
146 | + // TODO: verify that the inflated data is the correct length | |
147 | + cb(null, type, inflateBytes(readByte)) | |
110 | 148 | }) |
111 | 149 | } |
112 | 150 | |
113 | 151 | function readTrailer(cb) { |
Built with git-ssb-web