//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2021 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
//
//===----------------------------------------------------------------------===//

/// NOTE: THIS FILE IS AUTO-GENERATED BY dev/generate-bytebuffer-multi-int.sh

extension ByteBuffer {
    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger>(
        endianness: Endianness = .big,
        as: (T1, T2).Type = (T1, T2).self
    ) -> (T1, T2)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (T1(bigEndian: v1), T2(bigEndian: v2))
        case .little:
            return (T1(littleEndian: v1), T2(littleEndian: v2))
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger>(
        _ value1: T1,
        _ value2: T2,
        endianness: Endianness = .big,
        as: (T1, T2).Type = (T1, T2).self
    ) -> Int {
        var v1: T1
        var v2: T2
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger, T3: FixedWidthInteger>(
        endianness: Endianness = .big,
        as: (T1, T2, T3).Type = (T1, T2, T3).self
    ) -> (T1, T2, T3)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3))
        case .little:
            return (T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3))
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<T1: FixedWidthInteger, T2: FixedWidthInteger, T3: FixedWidthInteger>(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        endianness: Endianness = .big,
        as: (T1, T2, T3).Type = (T1, T2, T3).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger
    >(endianness: Endianness = .big, as: (T1, T2, T3, T4).Type = (T1, T2, T3, T4).self) -> (T1, T2, T3, T4)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4))
        case .little:
            return (T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4))
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4).Type = (T1, T2, T3, T4).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger
    >(endianness: Endianness = .big, as: (T1, T2, T3, T4, T5).Type = (T1, T2, T3, T4, T5).self) -> (T1, T2, T3, T4, T5)?
    {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5))
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5).Type = (T1, T2, T3, T4, T5).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6).Type = (T1, T2, T3, T4, T5, T6).self
    ) -> (T1, T2, T3, T4, T5, T6)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6).Type = (T1, T2, T3, T4, T5, T6).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7).Type = (T1, T2, T3, T4, T5, T6, T7).self
    ) -> (T1, T2, T3, T4, T5, T6, T7)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7).Type = (T1, T2, T3, T4, T5, T6, T7).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8).Type = (T1, T2, T3, T4, T5, T6, T7, T8).self
    ) -> (T1, T2, T3, T4, T5, T6, T7, T8)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size
        bytesRequired &+= MemoryLayout<T8>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var v8: T8 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            withUnsafeMutableBytes(of: &v8) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)
            }
            offset = offset &+ MemoryLayout<T8>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        _ value8: T8,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8).Type = (T1, T2, T3, T4, T5, T6, T7, T8).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        var v8: T8
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
            v8 = value8.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
            v8 = value8.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size
        spaceNeeded &+= MemoryLayout<T8>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)
            offset = offset &+ MemoryLayout<T8>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9).self
    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size
        bytesRequired &+= MemoryLayout<T8>.size
        bytesRequired &+= MemoryLayout<T9>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var v8: T8 = 0
        var v9: T9 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            withUnsafeMutableBytes(of: &v8) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)
            }
            offset = offset &+ MemoryLayout<T8>.size
            withUnsafeMutableBytes(of: &v9) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)
            }
            offset = offset &+ MemoryLayout<T9>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),
                T9(littleEndian: v9)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        _ value8: T8,
        _ value9: T9,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        var v8: T8
        var v9: T9
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
            v8 = value8.bigEndian
            v9 = value9.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
            v8 = value8.littleEndian
            v9 = value9.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size
        spaceNeeded &+= MemoryLayout<T8>.size
        spaceNeeded &+= MemoryLayout<T9>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)
            offset = offset &+ MemoryLayout<T8>.size
            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)
            offset = offset &+ MemoryLayout<T9>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).self
    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size
        bytesRequired &+= MemoryLayout<T8>.size
        bytesRequired &+= MemoryLayout<T9>.size
        bytesRequired &+= MemoryLayout<T10>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var v8: T8 = 0
        var v9: T9 = 0
        var v10: T10 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            withUnsafeMutableBytes(of: &v8) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)
            }
            offset = offset &+ MemoryLayout<T8>.size
            withUnsafeMutableBytes(of: &v9) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)
            }
            offset = offset &+ MemoryLayout<T9>.size
            withUnsafeMutableBytes(of: &v10) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)
            }
            offset = offset &+ MemoryLayout<T10>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),
                T9(littleEndian: v9), T10(littleEndian: v10)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        _ value8: T8,
        _ value9: T9,
        _ value10: T10,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        var v8: T8
        var v9: T9
        var v10: T10
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
            v8 = value8.bigEndian
            v9 = value9.bigEndian
            v10 = value10.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
            v8 = value8.littleEndian
            v9 = value9.littleEndian
            v10 = value10.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size
        spaceNeeded &+= MemoryLayout<T8>.size
        spaceNeeded &+= MemoryLayout<T9>.size
        spaceNeeded &+= MemoryLayout<T10>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)
            offset = offset &+ MemoryLayout<T8>.size
            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)
            offset = offset &+ MemoryLayout<T9>.size
            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)
            offset = offset &+ MemoryLayout<T10>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).self
    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size
        bytesRequired &+= MemoryLayout<T8>.size
        bytesRequired &+= MemoryLayout<T9>.size
        bytesRequired &+= MemoryLayout<T10>.size
        bytesRequired &+= MemoryLayout<T11>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var v8: T8 = 0
        var v9: T9 = 0
        var v10: T10 = 0
        var v11: T11 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            withUnsafeMutableBytes(of: &v8) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)
            }
            offset = offset &+ MemoryLayout<T8>.size
            withUnsafeMutableBytes(of: &v9) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)
            }
            offset = offset &+ MemoryLayout<T9>.size
            withUnsafeMutableBytes(of: &v10) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)
            }
            offset = offset &+ MemoryLayout<T10>.size
            withUnsafeMutableBytes(of: &v11) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)
            }
            offset = offset &+ MemoryLayout<T11>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),
                T11(bigEndian: v11)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),
                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        _ value8: T8,
        _ value9: T9,
        _ value10: T10,
        _ value11: T11,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).Type = (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        var v8: T8
        var v9: T9
        var v10: T10
        var v11: T11
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
            v8 = value8.bigEndian
            v9 = value9.bigEndian
            v10 = value10.bigEndian
            v11 = value11.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
            v8 = value8.littleEndian
            v9 = value9.littleEndian
            v10 = value10.littleEndian
            v11 = value11.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size
        spaceNeeded &+= MemoryLayout<T8>.size
        spaceNeeded &+= MemoryLayout<T9>.size
        spaceNeeded &+= MemoryLayout<T10>.size
        spaceNeeded &+= MemoryLayout<T11>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)
            offset = offset &+ MemoryLayout<T8>.size
            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)
            offset = offset &+ MemoryLayout<T9>.size
            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)
            offset = offset &+ MemoryLayout<T10>.size
            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)
            offset = offset &+ MemoryLayout<T11>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger,
        T12: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12).Type = (
            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12
        ).self
    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size
        bytesRequired &+= MemoryLayout<T8>.size
        bytesRequired &+= MemoryLayout<T9>.size
        bytesRequired &+= MemoryLayout<T10>.size
        bytesRequired &+= MemoryLayout<T11>.size
        bytesRequired &+= MemoryLayout<T12>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var v8: T8 = 0
        var v9: T9 = 0
        var v10: T10 = 0
        var v11: T11 = 0
        var v12: T12 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            withUnsafeMutableBytes(of: &v8) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)
            }
            offset = offset &+ MemoryLayout<T8>.size
            withUnsafeMutableBytes(of: &v9) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)
            }
            offset = offset &+ MemoryLayout<T9>.size
            withUnsafeMutableBytes(of: &v10) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)
            }
            offset = offset &+ MemoryLayout<T10>.size
            withUnsafeMutableBytes(of: &v11) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)
            }
            offset = offset &+ MemoryLayout<T11>.size
            withUnsafeMutableBytes(of: &v12) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T12>.size)
            }
            offset = offset &+ MemoryLayout<T12>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),
                T11(bigEndian: v11), T12(bigEndian: v12)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),
                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11), T12(littleEndian: v12)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger,
        T12: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        _ value8: T8,
        _ value9: T9,
        _ value10: T10,
        _ value11: T11,
        _ value12: T12,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12).Type = (
            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12
        ).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        var v8: T8
        var v9: T9
        var v10: T10
        var v11: T11
        var v12: T12
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
            v8 = value8.bigEndian
            v9 = value9.bigEndian
            v10 = value10.bigEndian
            v11 = value11.bigEndian
            v12 = value12.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
            v8 = value8.littleEndian
            v9 = value9.littleEndian
            v10 = value10.littleEndian
            v11 = value11.littleEndian
            v12 = value12.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size
        spaceNeeded &+= MemoryLayout<T8>.size
        spaceNeeded &+= MemoryLayout<T9>.size
        spaceNeeded &+= MemoryLayout<T10>.size
        spaceNeeded &+= MemoryLayout<T11>.size
        spaceNeeded &+= MemoryLayout<T12>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)
            offset = offset &+ MemoryLayout<T8>.size
            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)
            offset = offset &+ MemoryLayout<T9>.size
            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)
            offset = offset &+ MemoryLayout<T10>.size
            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)
            offset = offset &+ MemoryLayout<T11>.size
            (basePtr + offset).copyMemory(from: &v12, byteCount: MemoryLayout<T12>.size)
            offset = offset &+ MemoryLayout<T12>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger,
        T12: FixedWidthInteger,
        T13: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13).Type = (
            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13
        ).self
    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size
        bytesRequired &+= MemoryLayout<T8>.size
        bytesRequired &+= MemoryLayout<T9>.size
        bytesRequired &+= MemoryLayout<T10>.size
        bytesRequired &+= MemoryLayout<T11>.size
        bytesRequired &+= MemoryLayout<T12>.size
        bytesRequired &+= MemoryLayout<T13>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var v8: T8 = 0
        var v9: T9 = 0
        var v10: T10 = 0
        var v11: T11 = 0
        var v12: T12 = 0
        var v13: T13 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            withUnsafeMutableBytes(of: &v8) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)
            }
            offset = offset &+ MemoryLayout<T8>.size
            withUnsafeMutableBytes(of: &v9) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)
            }
            offset = offset &+ MemoryLayout<T9>.size
            withUnsafeMutableBytes(of: &v10) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)
            }
            offset = offset &+ MemoryLayout<T10>.size
            withUnsafeMutableBytes(of: &v11) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)
            }
            offset = offset &+ MemoryLayout<T11>.size
            withUnsafeMutableBytes(of: &v12) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T12>.size)
            }
            offset = offset &+ MemoryLayout<T12>.size
            withUnsafeMutableBytes(of: &v13) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T13>.size)
            }
            offset = offset &+ MemoryLayout<T13>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),
                T11(bigEndian: v11), T12(bigEndian: v12), T13(bigEndian: v13)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),
                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11), T12(littleEndian: v12),
                T13(littleEndian: v13)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger,
        T12: FixedWidthInteger,
        T13: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        _ value8: T8,
        _ value9: T9,
        _ value10: T10,
        _ value11: T11,
        _ value12: T12,
        _ value13: T13,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13).Type = (
            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13
        ).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        var v8: T8
        var v9: T9
        var v10: T10
        var v11: T11
        var v12: T12
        var v13: T13
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
            v8 = value8.bigEndian
            v9 = value9.bigEndian
            v10 = value10.bigEndian
            v11 = value11.bigEndian
            v12 = value12.bigEndian
            v13 = value13.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
            v8 = value8.littleEndian
            v9 = value9.littleEndian
            v10 = value10.littleEndian
            v11 = value11.littleEndian
            v12 = value12.littleEndian
            v13 = value13.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size
        spaceNeeded &+= MemoryLayout<T8>.size
        spaceNeeded &+= MemoryLayout<T9>.size
        spaceNeeded &+= MemoryLayout<T10>.size
        spaceNeeded &+= MemoryLayout<T11>.size
        spaceNeeded &+= MemoryLayout<T12>.size
        spaceNeeded &+= MemoryLayout<T13>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)
            offset = offset &+ MemoryLayout<T8>.size
            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)
            offset = offset &+ MemoryLayout<T9>.size
            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)
            offset = offset &+ MemoryLayout<T10>.size
            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)
            offset = offset &+ MemoryLayout<T11>.size
            (basePtr + offset).copyMemory(from: &v12, byteCount: MemoryLayout<T12>.size)
            offset = offset &+ MemoryLayout<T12>.size
            (basePtr + offset).copyMemory(from: &v13, byteCount: MemoryLayout<T13>.size)
            offset = offset &+ MemoryLayout<T13>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger,
        T12: FixedWidthInteger,
        T13: FixedWidthInteger,
        T14: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14).Type = (
            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
        ).self
    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size
        bytesRequired &+= MemoryLayout<T8>.size
        bytesRequired &+= MemoryLayout<T9>.size
        bytesRequired &+= MemoryLayout<T10>.size
        bytesRequired &+= MemoryLayout<T11>.size
        bytesRequired &+= MemoryLayout<T12>.size
        bytesRequired &+= MemoryLayout<T13>.size
        bytesRequired &+= MemoryLayout<T14>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var v8: T8 = 0
        var v9: T9 = 0
        var v10: T10 = 0
        var v11: T11 = 0
        var v12: T12 = 0
        var v13: T13 = 0
        var v14: T14 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            withUnsafeMutableBytes(of: &v8) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)
            }
            offset = offset &+ MemoryLayout<T8>.size
            withUnsafeMutableBytes(of: &v9) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)
            }
            offset = offset &+ MemoryLayout<T9>.size
            withUnsafeMutableBytes(of: &v10) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)
            }
            offset = offset &+ MemoryLayout<T10>.size
            withUnsafeMutableBytes(of: &v11) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)
            }
            offset = offset &+ MemoryLayout<T11>.size
            withUnsafeMutableBytes(of: &v12) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T12>.size)
            }
            offset = offset &+ MemoryLayout<T12>.size
            withUnsafeMutableBytes(of: &v13) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T13>.size)
            }
            offset = offset &+ MemoryLayout<T13>.size
            withUnsafeMutableBytes(of: &v14) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T14>.size)
            }
            offset = offset &+ MemoryLayout<T14>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),
                T11(bigEndian: v11), T12(bigEndian: v12), T13(bigEndian: v13), T14(bigEndian: v14)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),
                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11), T12(littleEndian: v12),
                T13(littleEndian: v13), T14(littleEndian: v14)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger,
        T12: FixedWidthInteger,
        T13: FixedWidthInteger,
        T14: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        _ value8: T8,
        _ value9: T9,
        _ value10: T10,
        _ value11: T11,
        _ value12: T12,
        _ value13: T13,
        _ value14: T14,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14).Type = (
            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
        ).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        var v8: T8
        var v9: T9
        var v10: T10
        var v11: T11
        var v12: T12
        var v13: T13
        var v14: T14
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
            v8 = value8.bigEndian
            v9 = value9.bigEndian
            v10 = value10.bigEndian
            v11 = value11.bigEndian
            v12 = value12.bigEndian
            v13 = value13.bigEndian
            v14 = value14.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
            v8 = value8.littleEndian
            v9 = value9.littleEndian
            v10 = value10.littleEndian
            v11 = value11.littleEndian
            v12 = value12.littleEndian
            v13 = value13.littleEndian
            v14 = value14.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size
        spaceNeeded &+= MemoryLayout<T8>.size
        spaceNeeded &+= MemoryLayout<T9>.size
        spaceNeeded &+= MemoryLayout<T10>.size
        spaceNeeded &+= MemoryLayout<T11>.size
        spaceNeeded &+= MemoryLayout<T12>.size
        spaceNeeded &+= MemoryLayout<T13>.size
        spaceNeeded &+= MemoryLayout<T14>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)
            offset = offset &+ MemoryLayout<T8>.size
            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)
            offset = offset &+ MemoryLayout<T9>.size
            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)
            offset = offset &+ MemoryLayout<T10>.size
            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)
            offset = offset &+ MemoryLayout<T11>.size
            (basePtr + offset).copyMemory(from: &v12, byteCount: MemoryLayout<T12>.size)
            offset = offset &+ MemoryLayout<T12>.size
            (basePtr + offset).copyMemory(from: &v13, byteCount: MemoryLayout<T13>.size)
            offset = offset &+ MemoryLayout<T13>.size
            (basePtr + offset).copyMemory(from: &v14, byteCount: MemoryLayout<T14>.size)
            offset = offset &+ MemoryLayout<T14>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    public mutating func readMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger,
        T12: FixedWidthInteger,
        T13: FixedWidthInteger,
        T14: FixedWidthInteger,
        T15: FixedWidthInteger
    >(
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15).Type = (
            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15
        ).self
    ) -> (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)? {
        var bytesRequired: Int = MemoryLayout<T1>.size
        bytesRequired &+= MemoryLayout<T2>.size
        bytesRequired &+= MemoryLayout<T3>.size
        bytesRequired &+= MemoryLayout<T4>.size
        bytesRequired &+= MemoryLayout<T5>.size
        bytesRequired &+= MemoryLayout<T6>.size
        bytesRequired &+= MemoryLayout<T7>.size
        bytesRequired &+= MemoryLayout<T8>.size
        bytesRequired &+= MemoryLayout<T9>.size
        bytesRequired &+= MemoryLayout<T10>.size
        bytesRequired &+= MemoryLayout<T11>.size
        bytesRequired &+= MemoryLayout<T12>.size
        bytesRequired &+= MemoryLayout<T13>.size
        bytesRequired &+= MemoryLayout<T14>.size
        bytesRequired &+= MemoryLayout<T15>.size

        guard self.readableBytes >= bytesRequired else {
            return nil
        }

        var v1: T1 = 0
        var v2: T2 = 0
        var v3: T3 = 0
        var v4: T4 = 0
        var v5: T5 = 0
        var v6: T6 = 0
        var v7: T7 = 0
        var v8: T8 = 0
        var v9: T9 = 0
        var v10: T10 = 0
        var v11: T11 = 0
        var v12: T12 = 0
        var v13: T13 = 0
        var v14: T14 = 0
        var v15: T15 = 0
        var offset = 0
        self.readWithUnsafeReadableBytes { ptr -> Int in
            assert(ptr.count >= bytesRequired)
            let basePtr = ptr.baseAddress!  // safe, ptr is non-empty
            withUnsafeMutableBytes(of: &v1) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T1>.size)
            }
            offset = offset &+ MemoryLayout<T1>.size
            withUnsafeMutableBytes(of: &v2) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T2>.size)
            }
            offset = offset &+ MemoryLayout<T2>.size
            withUnsafeMutableBytes(of: &v3) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T3>.size)
            }
            offset = offset &+ MemoryLayout<T3>.size
            withUnsafeMutableBytes(of: &v4) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T4>.size)
            }
            offset = offset &+ MemoryLayout<T4>.size
            withUnsafeMutableBytes(of: &v5) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T5>.size)
            }
            offset = offset &+ MemoryLayout<T5>.size
            withUnsafeMutableBytes(of: &v6) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T6>.size)
            }
            offset = offset &+ MemoryLayout<T6>.size
            withUnsafeMutableBytes(of: &v7) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T7>.size)
            }
            offset = offset &+ MemoryLayout<T7>.size
            withUnsafeMutableBytes(of: &v8) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T8>.size)
            }
            offset = offset &+ MemoryLayout<T8>.size
            withUnsafeMutableBytes(of: &v9) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T9>.size)
            }
            offset = offset &+ MemoryLayout<T9>.size
            withUnsafeMutableBytes(of: &v10) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T10>.size)
            }
            offset = offset &+ MemoryLayout<T10>.size
            withUnsafeMutableBytes(of: &v11) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T11>.size)
            }
            offset = offset &+ MemoryLayout<T11>.size
            withUnsafeMutableBytes(of: &v12) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T12>.size)
            }
            offset = offset &+ MemoryLayout<T12>.size
            withUnsafeMutableBytes(of: &v13) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T13>.size)
            }
            offset = offset &+ MemoryLayout<T13>.size
            withUnsafeMutableBytes(of: &v14) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T14>.size)
            }
            offset = offset &+ MemoryLayout<T14>.size
            withUnsafeMutableBytes(of: &v15) { destPtr in
                destPtr.baseAddress!.copyMemory(from: basePtr + offset, byteCount: MemoryLayout<T15>.size)
            }
            offset = offset &+ MemoryLayout<T15>.size
            assert(offset == bytesRequired)
            return offset
        }
        switch endianness {
        case .big:
            return (
                T1(bigEndian: v1), T2(bigEndian: v2), T3(bigEndian: v3), T4(bigEndian: v4), T5(bigEndian: v5),
                T6(bigEndian: v6), T7(bigEndian: v7), T8(bigEndian: v8), T9(bigEndian: v9), T10(bigEndian: v10),
                T11(bigEndian: v11), T12(bigEndian: v12), T13(bigEndian: v13), T14(bigEndian: v14), T15(bigEndian: v15)
            )
        case .little:
            return (
                T1(littleEndian: v1), T2(littleEndian: v2), T3(littleEndian: v3), T4(littleEndian: v4),
                T5(littleEndian: v5), T6(littleEndian: v6), T7(littleEndian: v7), T8(littleEndian: v8),
                T9(littleEndian: v9), T10(littleEndian: v10), T11(littleEndian: v11), T12(littleEndian: v12),
                T13(littleEndian: v13), T14(littleEndian: v14), T15(littleEndian: v15)
            )
        }
    }

    @inlinable
    @_alwaysEmitIntoClient
    @discardableResult
    public mutating func writeMultipleIntegers<
        T1: FixedWidthInteger,
        T2: FixedWidthInteger,
        T3: FixedWidthInteger,
        T4: FixedWidthInteger,
        T5: FixedWidthInteger,
        T6: FixedWidthInteger,
        T7: FixedWidthInteger,
        T8: FixedWidthInteger,
        T9: FixedWidthInteger,
        T10: FixedWidthInteger,
        T11: FixedWidthInteger,
        T12: FixedWidthInteger,
        T13: FixedWidthInteger,
        T14: FixedWidthInteger,
        T15: FixedWidthInteger
    >(
        _ value1: T1,
        _ value2: T2,
        _ value3: T3,
        _ value4: T4,
        _ value5: T5,
        _ value6: T6,
        _ value7: T7,
        _ value8: T8,
        _ value9: T9,
        _ value10: T10,
        _ value11: T11,
        _ value12: T12,
        _ value13: T13,
        _ value14: T14,
        _ value15: T15,
        endianness: Endianness = .big,
        as: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15).Type = (
            T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15
        ).self
    ) -> Int {
        var v1: T1
        var v2: T2
        var v3: T3
        var v4: T4
        var v5: T5
        var v6: T6
        var v7: T7
        var v8: T8
        var v9: T9
        var v10: T10
        var v11: T11
        var v12: T12
        var v13: T13
        var v14: T14
        var v15: T15
        switch endianness {
        case .big:
            v1 = value1.bigEndian
            v2 = value2.bigEndian
            v3 = value3.bigEndian
            v4 = value4.bigEndian
            v5 = value5.bigEndian
            v6 = value6.bigEndian
            v7 = value7.bigEndian
            v8 = value8.bigEndian
            v9 = value9.bigEndian
            v10 = value10.bigEndian
            v11 = value11.bigEndian
            v12 = value12.bigEndian
            v13 = value13.bigEndian
            v14 = value14.bigEndian
            v15 = value15.bigEndian
        case .little:
            v1 = value1.littleEndian
            v2 = value2.littleEndian
            v3 = value3.littleEndian
            v4 = value4.littleEndian
            v5 = value5.littleEndian
            v6 = value6.littleEndian
            v7 = value7.littleEndian
            v8 = value8.littleEndian
            v9 = value9.littleEndian
            v10 = value10.littleEndian
            v11 = value11.littleEndian
            v12 = value12.littleEndian
            v13 = value13.littleEndian
            v14 = value14.littleEndian
            v15 = value15.littleEndian
        }

        var spaceNeeded: Int = MemoryLayout<T1>.size
        spaceNeeded &+= MemoryLayout<T2>.size
        spaceNeeded &+= MemoryLayout<T3>.size
        spaceNeeded &+= MemoryLayout<T4>.size
        spaceNeeded &+= MemoryLayout<T5>.size
        spaceNeeded &+= MemoryLayout<T6>.size
        spaceNeeded &+= MemoryLayout<T7>.size
        spaceNeeded &+= MemoryLayout<T8>.size
        spaceNeeded &+= MemoryLayout<T9>.size
        spaceNeeded &+= MemoryLayout<T10>.size
        spaceNeeded &+= MemoryLayout<T11>.size
        spaceNeeded &+= MemoryLayout<T12>.size
        spaceNeeded &+= MemoryLayout<T13>.size
        spaceNeeded &+= MemoryLayout<T14>.size
        spaceNeeded &+= MemoryLayout<T15>.size

        return self.writeWithUnsafeMutableBytes(minimumWritableBytes: spaceNeeded) { ptr -> Int in
            assert(ptr.count >= spaceNeeded)
            var offset = 0
            let basePtr = ptr.baseAddress!  // safe: pointer is non zero length
            (basePtr + offset).copyMemory(from: &v1, byteCount: MemoryLayout<T1>.size)
            offset = offset &+ MemoryLayout<T1>.size
            (basePtr + offset).copyMemory(from: &v2, byteCount: MemoryLayout<T2>.size)
            offset = offset &+ MemoryLayout<T2>.size
            (basePtr + offset).copyMemory(from: &v3, byteCount: MemoryLayout<T3>.size)
            offset = offset &+ MemoryLayout<T3>.size
            (basePtr + offset).copyMemory(from: &v4, byteCount: MemoryLayout<T4>.size)
            offset = offset &+ MemoryLayout<T4>.size
            (basePtr + offset).copyMemory(from: &v5, byteCount: MemoryLayout<T5>.size)
            offset = offset &+ MemoryLayout<T5>.size
            (basePtr + offset).copyMemory(from: &v6, byteCount: MemoryLayout<T6>.size)
            offset = offset &+ MemoryLayout<T6>.size
            (basePtr + offset).copyMemory(from: &v7, byteCount: MemoryLayout<T7>.size)
            offset = offset &+ MemoryLayout<T7>.size
            (basePtr + offset).copyMemory(from: &v8, byteCount: MemoryLayout<T8>.size)
            offset = offset &+ MemoryLayout<T8>.size
            (basePtr + offset).copyMemory(from: &v9, byteCount: MemoryLayout<T9>.size)
            offset = offset &+ MemoryLayout<T9>.size
            (basePtr + offset).copyMemory(from: &v10, byteCount: MemoryLayout<T10>.size)
            offset = offset &+ MemoryLayout<T10>.size
            (basePtr + offset).copyMemory(from: &v11, byteCount: MemoryLayout<T11>.size)
            offset = offset &+ MemoryLayout<T11>.size
            (basePtr + offset).copyMemory(from: &v12, byteCount: MemoryLayout<T12>.size)
            offset = offset &+ MemoryLayout<T12>.size
            (basePtr + offset).copyMemory(from: &v13, byteCount: MemoryLayout<T13>.size)
            offset = offset &+ MemoryLayout<T13>.size
            (basePtr + offset).copyMemory(from: &v14, byteCount: MemoryLayout<T14>.size)
            offset = offset &+ MemoryLayout<T14>.size
            (basePtr + offset).copyMemory(from: &v15, byteCount: MemoryLayout<T15>.size)
            offset = offset &+ MemoryLayout<T15>.size
            assert(offset == spaceNeeded)
            return offset
        }
    }

}
