-
Notifications
You must be signed in to change notification settings - Fork 26
/
NRStorageProvider.swift
116 lines (92 loc) · 4.22 KB
/
NRStorageProvider.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//
// NRStorageProvider.swift
// Nora
//
// Created by Steven on 4/4/17.
// Copyright © 2017 NoraFirebase. All rights reserved.
//
import Foundation
import FirebaseStorage
import Result
public typealias StorageCompletion = (Result<NRStorageResponse, NRError>) -> Void
public class NRStorageProvider<Target: NRStorageTarget> {
/// Default init
public init() {}
@discardableResult
public func request(_ target: Target, completion: @escaping StorageCompletion) -> StorageObservableTask? {
let request = NRStorageRequest(target)
switch request.task {
case .upload, .uploadFile, .update, .downloadMetadata, .delete:
return processUpload(request, completion)
case .downloadToURL, .downloadData, .downloadURL:
return processDownload(request, completion)
}
}
private func processUpload(_ request: NRStorageRequest, _ completion: @escaping StorageCompletion) -> StorageUploadTask? {
let writeBlock = { (metaData: StorageMetadata?, error: Error?) in
let response = self.convertResponseToResult(data: nil, metaData: metaData, url: nil, error: error)
completion(response)
}
let deleteBlock = { (error: Error?) in
let response = self.convertResponseToResult(data: nil, metaData: nil, url: nil, error: error)
completion(response)
}
var uploadTask: StorageUploadTask?
switch request.task {
case .upload(let data, let metaData):
uploadTask = request.reference.putData(data, metadata: metaData, completion: writeBlock)
case .uploadFile(let url, let metaData):
uploadTask = request.reference.putFile(from: url, metadata: metaData, completion: writeBlock)
case .update(let metadata):
request.reference.updateMetadata(metadata, completion: writeBlock)
case .downloadMetadata: // this is really a download task
request.reference.getMetadata(completion: writeBlock)
case .delete:
request.reference.delete(completion: deleteBlock)
default:
completion(.failure(NRError.requestMapping))
}
return uploadTask
}
private func processDownload(_ request: NRStorageRequest, _ completion: @escaping StorageCompletion) -> StorageDownloadTask? {
let dataCompletion = { (data: Data?, error: Error?) in
let response = self.convertResponseToResult(data: data, metaData: nil, url: nil, error: error)
completion(response)
}
let urlCompletion = { (url: URL?, error: Error?) in
let response = self.convertResponseToResult(data: nil, metaData: nil, url: url, error: error)
completion(response)
}
var downloadTask: StorageDownloadTask?
switch request.task {
case .downloadData(let maxSize):
downloadTask = request.reference.getData(maxSize: maxSize, completion: dataCompletion)
case .downloadToURL(let url):
downloadTask = request.reference.write(toFile: url, completion: urlCompletion)
case .downloadURL:
request.reference.downloadURL(completion: urlCompletion)
default:
completion(.failure(NRError.requestMapping))
}
return downloadTask
}
}
private extension NRStorageProvider {
func convertResponseToResult(data: Data?, metaData: StorageMetadata?, url: URL?, error: Error?) -> Result<NRStorageResponse, NRError> {
switch (data, metaData, url, error) {
case let (.some(data), _, _, .none):
let response = NRStorageResponse(data: data)
return .success(response)
case let (_, _, .some(url), .none):
let response = NRStorageResponse(url: url)
return .success(response)
case let (_, .some(metaData), _, .none):
let response = NRStorageResponse(metaData: metaData)
return .success(response)
case let (_, _, _, .some(error)):
return .failure(NRError.underlying(error))
default:
return .failure(NRError.resultConversion)
}
}
}