Skip to content
This repository was archived by the owner on Aug 12, 2020. It is now read-only.

Commit 526c15c

Browse files
committed
chore: Conform to spec for stream slices - see ipfs-inactive/interface-js-ipfs-core#242
1 parent 6082762 commit 526c15c

File tree

5 files changed

+94
-130
lines changed

5 files changed

+94
-130
lines changed

README.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,9 @@ Creates a new readable stream in object mode that outputs objects of the form
178178
}
179179
```
180180

181-
#### `begin` and `end`
181+
#### `offset` and `length`
182182

183-
`begin` and `end` arguments can optionally be passed to the reader function. These follow the same semantics as the JavaScript [`Array.slice(begin, end)`][] method.
184-
185-
That is: `begin` is the index in the stream to start sending data, `end` is the index *before* which to stop sending data.
186-
187-
A negative `begin` starts the slice from the end of the stream and a negative `end` ends the slice by subtracting `end` from the total stream length.
183+
`offset` and `length` arguments can optionally be passed to the reader function. These will cause the returned stream to only emit bytes starting at `offset` and with length of `length`.
188184

189185
See [the tests](test/reader.js) for examples of using these arguments.
190186

@@ -195,8 +191,8 @@ const drain = require('pull-stream/sinks/drain')
195191

196192
pull(
197193
exporter(cid, ipldResolver, {
198-
begin: 0,
199-
end: 10
194+
offset: 0,
195+
length: 10
200196
})
201197
drain((file) => {
202198
// file.content() is a pull stream containing only the first 10 bytes of the file

src/exporter/file.js

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const pull = require('pull-stream')
77
const paramap = require('pull-paramap')
88

99
// Logic to export a single (possibly chunked) unixfs file.
10-
module.exports = (node, name, path, pathRest, resolve, size, dag, parent, depth, begin, end) => {
10+
module.exports = (node, name, path, pathRest, resolve, size, dag, parent, depth, offset, length) => {
1111
const accepts = pathRest[0]
1212

1313
if (accepts !== undefined && accepts !== path) {
@@ -16,46 +16,50 @@ module.exports = (node, name, path, pathRest, resolve, size, dag, parent, depth,
1616

1717
const file = UnixFS.unmarshal(node.data)
1818
const fileSize = size || file.fileSize()
19-
const content = streamBytes(dag, node, fileSize, findByteRange(fileSize, begin, end))
2019

21-
return pull.values([{
22-
depth: depth,
23-
content: content,
24-
name: name,
25-
path: path,
26-
hash: node.multihash,
27-
size: fileSize,
28-
type: 'file'
29-
}])
30-
}
20+
if (offset < 0) {
21+
return pull.error(new Error('Offset must be greater than 0'))
22+
}
3123

32-
function findByteRange (fileSize, begin, end) {
33-
if (!begin) {
34-
begin = 0
24+
if (offset > fileSize) {
25+
return pull.error(new Error('Offset must be less than the file size'))
3526
}
3627

37-
if (!end || end > fileSize) {
38-
end = fileSize
28+
if (length < 0) {
29+
return pull.error(new Error('Length must be greater than or equal to 0'))
3930
}
4031

41-
if (begin < 0) {
42-
begin = fileSize + begin
32+
if (length === 0) {
33+
return pull.empty()
4334
}
4435

45-
if (end < 0) {
46-
end = fileSize + end
36+
if (!offset) {
37+
offset = 0
4738
}
4839

49-
return {
50-
begin, end
40+
if (!length || (offset + length > fileSize)) {
41+
length = fileSize - offset
5142
}
43+
44+
const content = streamBytes(dag, node, fileSize, offset, length)
45+
46+
return pull.values([{
47+
depth: depth,
48+
content: content,
49+
name: name,
50+
path: path,
51+
hash: node.multihash,
52+
size: fileSize,
53+
type: 'file'
54+
}])
5255
}
5356

54-
function streamBytes (dag, node, fileSize, { begin, end }) {
55-
if (begin === end) {
57+
function streamBytes (dag, node, fileSize, offset, length) {
58+
if (offset === fileSize || length === 0) {
5659
return pull.empty()
5760
}
5861

62+
const end = offset + length
5963
let streamPosition = 0
6064

6165
function getData ({ node, start }) {
@@ -70,11 +74,13 @@ function streamBytes (dag, node, fileSize, { begin, end }) {
7074
return
7175
}
7276

73-
const block = extractDataFromBlock(file.data, start, begin, end)
77+
const block = extractDataFromBlock(file.data, start, offset, end)
78+
79+
streamPosition += block.length
7480

7581
return block
76-
} catch (err) {
77-
throw new Error('Failed to unmarshal node')
82+
} catch (error) {
83+
throw new Error(`Failed to unmarshal node - ${error.message}`)
7884
}
7985
}
8086

@@ -95,9 +101,9 @@ function streamBytes (dag, node, fileSize, { begin, end }) {
95101
return child
96102
})
97103
.filter((child, index) => {
98-
return (begin >= child.start && begin < child.end) || // child has begin byte
104+
return (offset >= child.start && offset < child.end) || // child has offset byte
99105
(end > child.start && end <= child.end) || // child has end byte
100-
(begin < child.start && end > child.end) // child is between begin and end bytes
106+
(offset < child.start && end > child.end) // child is between offset and end bytes
101107
})
102108

103109
if (filteredLinks.length) {
@@ -111,7 +117,8 @@ function streamBytes (dag, node, fileSize, { begin, end }) {
111117
dag.get(new CID(child.link.multihash), (error, result) => cb(error, {
112118
start: child.start,
113119
end: child.end,
114-
node: result && result.value
120+
node: result && result.value,
121+
size: child.size
115122
}))
116123
})
117124
)

src/exporter/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ function pathBaseAndRest (path) {
3737

3838
const defaultOptions = {
3939
maxDepth: Infinity,
40-
begin: undefined,
41-
end: undefined
40+
offset: undefined,
41+
length: undefined
4242
}
4343

4444
module.exports = (path, dag, options) => {

src/exporter/resolve.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,33 @@ function createResolver (dag, options, depth, parent) {
3232
return pull.error(new Error('no depth'))
3333
}
3434
if (item.object) {
35-
return cb(null, resolveItem(item.object, item, options.begin, options.end))
35+
return cb(null, resolveItem(item.object, item, options.offset, options.length))
3636
}
3737
dag.get(new CID(item.multihash), (err, node) => {
3838
if (err) {
3939
return cb(err)
4040
}
4141
// const name = item.fromPathRest ? item.name : item.path
42-
cb(null, resolveItem(node.value, item, options.begin, options.end))
42+
cb(null, resolveItem(node.value, item, options.offset, options.length))
4343
})
4444
}),
4545
pull.flatten(),
4646
pull.filter(Boolean),
4747
pull.filter((node) => node.depth <= options.maxDepth)
4848
)
4949

50-
function resolveItem (node, item, begin, end) {
51-
return resolve(node, item.name, item.path, item.pathRest, item.size, dag, item.parent || parent, item.depth, begin, end)
50+
function resolveItem (node, item, offset, length) {
51+
return resolve(node, item.name, item.path, item.pathRest, item.size, dag, item.parent || parent, item.depth, offset, length)
5252
}
5353

54-
function resolve (node, name, path, pathRest, size, dag, parentNode, depth, begin, end) {
54+
function resolve (node, name, path, pathRest, size, dag, parentNode, depth, offset, length) {
5555
const type = typeOf(node)
5656
const nodeResolver = resolvers[type]
5757
if (!nodeResolver) {
5858
return pull.error(new Error('Unkown node type ' + type))
5959
}
6060
const resolveDeep = createResolver(dag, options, depth, node)
61-
return nodeResolver(node, name, path, pathRest, resolveDeep, size, dag, parentNode, depth, begin, end)
61+
return nodeResolver(node, name, path, pathRest, resolveDeep, size, dag, parentNode, depth, offset, length)
6262
}
6363
}
6464

0 commit comments

Comments
 (0)