diff --git a/Sources/SwiftNetwork/Utilities/Deserializer.swift b/Sources/SwiftNetwork/Utilities/Deserializer.swift index 7f48d2d..fdb6a0d 100644 --- a/Sources/SwiftNetwork/Utilities/Deserializer.swift +++ b/Sources/SwiftNetwork/Utilities/Deserializer.swift @@ -42,6 +42,7 @@ public enum DeserializationResult: CustomStringConvertible, Equatable, Sendable case success(parsedBytes: Int, remainingBytes: Int) case error(DeserializationError) + @usableFromInline static let success: Self = .success(parsedBytes: 0, remainingBytes: 0) public var description: String { @@ -76,11 +77,11 @@ public enum DeserializationResult: CustomStringConvertible, Equatable, Sendable @available(Network 0.1.0, *) public struct Deserializer: ~Copyable, ~Escapable { private var factory: Factory - private var currentSpan: RawSpan - private var currentSpanByteCount = 0 + @usableFromInline internal var currentSpan: RawSpan + @usableFromInline internal var currentSpanByteCount = 0 private var availableByteCount: Int private var scratchSpace: [16 of UInt8]? // Initialized lazily - private var cursor = 0 + @usableFromInline internal var cursor = 0 private var previousSpanAggregateByteCount = 0 private(set) var internalResult: DeserializationResult = .success @@ -339,11 +340,32 @@ public struct Deserializer.size } + @_optimize(speed) + @inlinable + @inline(__always) public mutating func uint8(_ value: inout UInt8?) throws(DeserializationError) { + var temp: UInt8 = 0 + try uint8(&temp) + value = temp + } + + @usableFromInline + @inline(never) + internal mutating func readUInt8AtSpanBoundary(_ value: inout UInt8) throws(DeserializationError) { try readFixedSize(&value) } @@ -363,11 +385,31 @@ public struct Deserializer= MemoryLayout.size else { + // Fallback for multi-span cases + try readUInt16AtSpanBoundary(&value) + return + } + value = currentSpan.unsafeLoadUnaligned(fromByteOffset: cursor, as: UInt16.self) + cursor &+= MemoryLayout.size } + @_optimize(speed) + @inlinable + @inline(__always) public mutating func uint16(_ value: inout UInt16?) throws(DeserializationError) { + var temp: UInt16 = 0 + try uint16(&temp) + value = temp + } + + @usableFromInline + @inline(never) + internal mutating func readUInt16AtSpanBoundary(_ value: inout UInt16) throws(DeserializationError) { try readFixedSize(&value) } @@ -387,11 +429,31 @@ public struct Deserializer= MemoryLayout.size else { + // Fallback for multi-span cases + try readUInt32AtSpanBoundary(&value) + return + } + value = currentSpan.unsafeLoadUnaligned(fromByteOffset: cursor, as: UInt32.self) + cursor &+= MemoryLayout.size } + @_optimize(speed) + @inlinable + @inline(__always) public mutating func uint32(_ value: inout UInt32?) throws(DeserializationError) { + var temp: UInt32 = 0 + try uint32(&temp) + value = temp + } + + @usableFromInline + @inline(never) + internal mutating func readUInt32AtSpanBoundary(_ value: inout UInt32) throws(DeserializationError) { try readFixedSize(&value) } @@ -399,11 +461,32 @@ public struct Deserializer= MemoryLayout.size else { + // Fallback for multi-span cases + try readUInt64AtSpanBoundary(&value) + return + } + value = currentSpan.unsafeLoadUnaligned(fromByteOffset: cursor, as: UInt64.self) + // Move by eight bytes + cursor &+= MemoryLayout.size } + @_optimize(speed) + @inlinable + @inline(__always) public mutating func uint64(_ value: inout UInt64?) throws(DeserializationError) { + var temp: UInt64 = 0 + try uint64(&temp) + value = temp + } + + @usableFromInline + @inline(never) + internal mutating func readUInt64AtSpanBoundary(_ value: inout UInt64) throws(DeserializationError) { try readFixedSize(&value) } @@ -411,11 +494,31 @@ public struct Deserializer= MemoryLayout.size else { + // Fallback for multi-span cases + try readUInt16NBOAtSpanBoundary(&value) + return + } + value = UInt16(bigEndian: currentSpan.unsafeLoadUnaligned(fromByteOffset: cursor, as: UInt16.self)) + cursor &+= MemoryLayout.size } + @_optimize(speed) + @inlinable + @inline(__always) public mutating func uint16NetworkByteOrder(_ value: inout UInt16?) throws(DeserializationError) { + var temp: UInt16 = 0 + try uint16NetworkByteOrder(&temp) + value = temp + } + + @usableFromInline + @inline(never) + internal mutating func readUInt16NBOAtSpanBoundary(_ value: inout UInt16) throws(DeserializationError) { try readFixedSize(&value, networkByteOrder: true) } @@ -423,11 +526,31 @@ public struct Deserializer= MemoryLayout.size else { + // Fallback for multi-span cases + try readUInt32NBOAtSpanBoundary(&value) + return + } + value = UInt32(bigEndian: currentSpan.unsafeLoadUnaligned(fromByteOffset: cursor, as: UInt32.self)) + cursor &+= MemoryLayout.size } + @_optimize(speed) + @inlinable + @inline(__always) public mutating func uint32NetworkByteOrder(_ value: inout UInt32?) throws(DeserializationError) { + var temp: UInt32 = 0 + try uint32NetworkByteOrder(&temp) + value = temp + } + + @usableFromInline + @inline(never) + internal mutating func readUInt32NBOAtSpanBoundary(_ value: inout UInt32) throws(DeserializationError) { try readFixedSize(&value, networkByteOrder: true) } @@ -435,11 +558,31 @@ public struct Deserializer= MemoryLayout.size else { + // Fallback for multi-span cases + try readUInt64NBOAtSpanBoundary(&value) + return + } + value = UInt64(bigEndian: currentSpan.unsafeLoadUnaligned(fromByteOffset: cursor, as: UInt64.self)) + cursor &+= MemoryLayout.size } + @_optimize(speed) + @inlinable + @inline(__always) public mutating func uint64NetworkByteOrder(_ value: inout UInt64?) throws(DeserializationError) { + var temp: UInt64 = 0 + try uint64NetworkByteOrder(&temp) + value = temp + } + + @usableFromInline + @inline(never) + internal mutating func readUInt64NBOAtSpanBoundary(_ value: inout UInt64) throws(DeserializationError) { try readFixedSize(&value, networkByteOrder: true) } @@ -827,6 +970,7 @@ public struct Deserializer FrameArray { frameArray } @@ -119,6 +120,7 @@ public struct FrameArraySpanFactory: ~Copyable, ~Escapable, DeserializerSpanFact // lifetime dependency. @_lifetime(immortal) is correct for a self-contained // ~Escapable type whose data is fully owned. @_lifetime(immortal) + @usableFromInline init(_ frameArray: consuming FrameArray) { self.spanCount = frameArray.count self.availableByteCount = frameArray.unclaimedLength