JSONStreamEncoder.swift 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. //
  2. // JSONStreamEncoder.swift
  3. // LoopKit
  4. //
  5. // Created by Darin Krauss on 6/25/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import Foundation
  9. public enum JSONStreamEncoderError: Error {
  10. case encoderClosed
  11. }
  12. public class JSONStreamEncoder {
  13. private let stream: OutputStream
  14. private var encoded: Bool
  15. private var closed: Bool
  16. public init(stream: OutputStream) {
  17. self.stream = stream
  18. self.encoded = false
  19. self.closed = false
  20. }
  21. public func close() -> Error? {
  22. guard !closed else {
  23. return nil
  24. }
  25. self.closed = true
  26. do {
  27. try stream.write(encoded ? "\n]" : "[]")
  28. } catch let error {
  29. return error
  30. }
  31. return nil
  32. }
  33. public func encode<T>(_ values: T) throws where T: Collection, T.Element: Encodable {
  34. guard !closed else {
  35. throw JSONStreamEncoderError.encoderClosed
  36. }
  37. for value in values {
  38. try stream.write(encoded ? ",\n" : "[\n")
  39. try stream.write(try Self.encoder.encode(value))
  40. encoded = true
  41. }
  42. }
  43. private static var encoder: JSONEncoder = {
  44. let encoder = JSONEncoder()
  45. if #available(watchOSApplicationExtension 6.0, *) {
  46. encoder.outputFormatting = [.sortedKeys, .withoutEscapingSlashes]
  47. } else {
  48. encoder.outputFormatting = [.sortedKeys]
  49. }
  50. encoder.dateEncodingStrategy = .custom { (date, encoder) in
  51. var encoder = encoder.singleValueContainer()
  52. try encoder.encode(dateFormatter.string(from: date))
  53. }
  54. return encoder
  55. }()
  56. private static let dateFormatter: ISO8601DateFormatter = {
  57. var dateFormatter = ISO8601DateFormatter()
  58. dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
  59. return dateFormatter
  60. }()
  61. }