File: Codable%2BByteBuffer.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (139 lines) | stat: -rw-r--r-- 6,558 bytes parent folder | download
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2019 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import NIO
import Foundation

extension ByteBuffer {
    /// Attempts to decode the `length` bytes from `index` using the `JSONDecoder` `decoder` as `T`.
    ///
    /// - parameters:
    ///    - type: The type type that is attempted to be decoded.
    ///    - decoder: The `JSONDecoder` that is used for the decoding.
    ///    - index: The index of the first byte to decode.
    ///    - length: The number of bytes to decode.
    /// - returns: The decoded value if successful or `nil` if there are not enough readable bytes available.
    @inlinable
    public func getJSONDecodable<T: Decodable>(_ type: T.Type,
                                               decoder: JSONDecoder = JSONDecoder(),
                                               at index: Int, length: Int) throws -> T? {
        guard let data = self.getData(at: index, length: length, byteTransferStrategy: .noCopy) else {
            return nil
        }
        return try decoder.decode(T.self, from: data)
    }

    /// Reads `length` bytes from this `ByteBuffer` and then attempts to decode them using the `JSONDecoder` `decoder`.
    ///
    /// - parameters:
    ///    - type: The type type that is attempted to be decoded.
    ///    - decoder: The `JSONDecoder` that is used for the decoding.
    ///    - length: The number of bytes to decode.
    /// - returns: The decoded value is successful or `nil` if there are not enough readable bytes available.
    @inlinable
    public mutating func readJSONDecodable<T: Decodable>(_ type: T.Type,
                                                         decoder: JSONDecoder = JSONDecoder(),
                                                         length: Int) throws -> T? {
        guard let decoded = try self.getJSONDecodable(T.self,
                                                      decoder: decoder,
                                                      at: self.readerIndex,
                                                      length: length) else {
            return nil
        }
        self.moveReaderIndex(forwardBy: length)
        return decoded
    }

    /// Encodes `value` using the `JSONEncoder` `encoder` and set the resulting bytes into this `ByteBuffer` at the
    /// given `index`.
    ///
    /// - note: The `writerIndex` remains unchanged.
    ///
    /// - parameters:
    ///     - value: An `Encodable` value to encode.
    ///     - encoder: The `JSONEncoder` to encode `value` with.
    /// - returns: The number of bytes written.
    @inlinable
    @discardableResult
    public mutating func setJSONEncodable<T: Encodable>(_ value: T,
                                                        encoder: JSONEncoder = JSONEncoder(),
                                                        at index: Int) throws -> Int {
        let data = try encoder.encode(value)
        return self.setBytes(data, at: index)
    }

    /// Encodes `value` using the `JSONEncoder` `encoder` and writes the resulting bytes into this `ByteBuffer`.
    ///
    /// If successful, this will move the writer index forward by the number of bytes written.
    ///
    /// - parameters:
    ///     - value: An `Encodable` value to encode.
    ///     - encoder: The `JSONEncoder` to encode `value` with.
    /// - returns: The number of bytes written.
    @inlinable
    @discardableResult
    public mutating func writeJSONEncodable<T: Encodable>(_ value: T,
                                                          encoder: JSONEncoder = JSONEncoder()) throws -> Int {
        let result = try self.setJSONEncodable(value, encoder: encoder, at: self.writerIndex)
        self.moveWriterIndex(forwardBy: result)
        return result
    }
}

extension JSONDecoder {
    /// Returns a value of the type you specify, decoded from a JSON object inside the readable bytes of a `ByteBuffer`.
    ///
    /// If the `ByteBuffer` does not contain valid JSON, this method throws the
    /// `DecodingError.dataCorrupted(_:)` error. If a value within the JSON
    /// fails to decode, this method throws the corresponding error.
    ///
    /// - note: The provided `ByteBuffer` remains unchanged, neither the `readerIndex` nor the `writerIndex` will move.
    ///         If you would like the `readerIndex` to move, consider using `ByteBuffer.readJSONDecodable(_:length:)`.
    ///
    /// - parameters:
    ///     - type: The type of the value to decode from the supplied JSON object.
    ///     - buffer: The `ByteBuffer` that contains JSON object to decode.
    /// - returns: The decoded object.
    public func decode<T: Decodable>(_ type: T.Type, from buffer: ByteBuffer) throws -> T {
        return try buffer.getJSONDecodable(T.self,
                                           decoder: self,
                                           at: buffer.readerIndex,
                                           length: buffer.readableBytes)! // must work, enough readable bytes
    }
}

extension JSONEncoder {
    /// Writes a JSON-encoded representation of the value you supply into the supplied `ByteBuffer`.
    ///
    /// - parameters:
    ///     - value: The value to encode as JSON.
    ///     - buffer: The `ByteBuffer` to encode into.
    public func encode<T: Encodable>(_ value: T,
                                     into buffer: inout ByteBuffer) throws {
        try buffer.writeJSONEncodable(value, encoder: self)
    }

    /// Writes a JSON-encoded representation of the value you supply into a `ByteBuffer` that is freshly allocated.
    ///
    /// - parameters:
    ///     - value: The value to encode as JSON.
    ///     - allocator: The `ByteBufferAllocator` which is used to allocate the `ByteBuffer` to be returned.
    /// - returns: The `ByteBuffer` containing the encoded JSON.
    public func encodeAsByteBuffer<T: Encodable>(_ value: T, allocator: ByteBufferAllocator) throws -> ByteBuffer {
        let data = try self.encode(value)
        var buffer = allocator.buffer(capacity: data.count)
        try buffer.writeJSONEncodable(value, encoder: self)
        return buffer
    }
}