Skip to content

Commit fa03121

Browse files
committed
Reader callback may be called again after we send a 0-length Data()
1 parent b0dfbc9 commit fa03121

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

Loop/Models/ZipArchive.swift

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ public class ZipArchive {
3232

3333
public class Stream: NSObject, DataOutputStream {
3434

35+
enum StreamState: Int {
36+
case open
37+
case closing
38+
case closed
39+
}
40+
3541
private let archive: Archive
3642
private let compressionMethod: CompressionMethod
3743

@@ -40,7 +46,7 @@ public class ZipArchive {
4046

4147
private let chunks = Locked<[Data]>([])
4248
private let error = Locked<Error?>(nil)
43-
private let finished = Locked<Bool>(false)
49+
private let state = Locked<StreamState>(.open)
4450

4551
fileprivate init(archive: Archive, path: String, compressionMethod: CompressionMethod) {
4652
self.archive = archive
@@ -58,13 +64,18 @@ public class ZipArchive {
5864
processingQueue.async {
5965
do {
6066
try self.archive.addEntry(with: path, type: .file, compressionMethod: self.compressionMethod.zfMethod) { position, size in
67+
68+
if self.state.value == .closed {
69+
return Data()
70+
}
6171
self.semaphore.wait()
6272
var chunk: Data!
6373
self.chunks.mutate { (value) in
6474
if value.count > 0 {
6575
chunk = value.removeFirst()
66-
} else if self.finished.value {
76+
} else if self.state.value == .closing {
6777
chunk = Data()
78+
self.state.value = .closed
6879
}
6980
}
7081
return chunk
@@ -82,7 +93,7 @@ public class ZipArchive {
8293
if let error = error.value {
8394
throw error
8495
}
85-
if finished.value {
96+
if self.state.value != .open {
8697
throw ZipArchiveError.streamFinished
8798
}
8899
chunks.mutate { value in
@@ -94,7 +105,7 @@ public class ZipArchive {
94105
public func finish(sync: Bool) throws {
95106
// An empty Data() is the sigil for the ZipFoundation read callback
96107
// to detect end of stream.
97-
finished.value = true
108+
state.value = .closing
98109
semaphore.signal()
99110
if sync {
100111
// Block until processingQueue is finished, and then check error state

0 commit comments

Comments
 (0)