forked from LoopKit/LoopKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJSONStreamEncoder.swift
More file actions
73 lines (61 loc) · 1.89 KB
/
JSONStreamEncoder.swift
File metadata and controls
73 lines (61 loc) · 1.89 KB
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
//
// JSONStreamEncoder.swift
// LoopKit
//
// Created by Darin Krauss on 6/25/20.
// Copyright © 2020 LoopKit Authors. All rights reserved.
//
import Foundation
public enum JSONStreamEncoderError: Error {
case encoderClosed
}
public class JSONStreamEncoder {
private let stream: DataOutputStream
private var encoded: Bool
private var closed: Bool
public init(stream: DataOutputStream) {
self.stream = stream
self.encoded = false
self.closed = false
}
public func close() -> Error? {
guard !closed else {
return nil
}
self.closed = true
do {
try stream.write(encoded ? "\n]" : "[]")
} catch let error {
return error
}
return nil
}
public func encode<T>(_ values: T) throws where T: Collection, T.Element: Encodable {
guard !closed else {
throw JSONStreamEncoderError.encoderClosed
}
for value in values {
try stream.write(encoded ? ",\n" : "[\n")
try stream.write(try Self.encoder.encode(value))
encoded = true
}
}
private static var encoder: JSONEncoder = {
let encoder = JSONEncoder()
if #available(watchOSApplicationExtension 6.0, *) {
encoder.outputFormatting = [.sortedKeys, .withoutEscapingSlashes]
} else {
encoder.outputFormatting = [.sortedKeys]
}
encoder.dateEncodingStrategy = .custom { (date, encoder) in
var encoder = encoder.singleValueContainer()
try encoder.encode(dateFormatter.string(from: date))
}
return encoder
}()
private static let dateFormatter: ISO8601DateFormatter = {
var dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return dateFormatter
}()
}