1- import LibP2PCore
2-
31/// Resource-transfer header framing for PeerConnectivity (Embedded-clean).
42///
53/// Embedded-clean: no Foundation, no NIO, no `any`, no Mutex, no
6- /// ContinuousClock, no key paths. Operates over `[UInt8]` and uses
7- /// `LibP2PCore.decodeUTF8Strict` for strict UTF-8 decoding of the size token .
4+ /// ContinuousClock, no key paths. Operates over `[UInt8]` without pulling in
5+ /// the host libp2p facade .
86///
97/// A resource is sent over a libp2p stream as a sequence of length-prefixed
108/// frames (the length prefix is owned by the muxer's
@@ -68,7 +66,7 @@ public enum ResourceFrameCodec {
6866 /// - Throws: `ResourceFrameError` describing the specific framing failure.
6967 public static func decodeHeader( _ bytes: [ UInt8 ] ) throws ( ResourceFrameError) -> ResourceHeader {
7068 let layout = try parseHeaderLayout ( bytes)
71- let name = lossyUTF8 ( Array ( bytes [ 0 ..< layout. nameEnd] ) )
69+ let name = lossyUTF8 ( bytes [ 0 ..< layout. nameEnd] )
7270 return ResourceHeader ( name: name, size: layout. size)
7371 }
7472
@@ -103,7 +101,7 @@ public enum ResourceFrameCodec {
103101 guard availablePayload == layout. size else {
104102 throw . payloadSizeMismatch( declared: layout. size, available: availablePayload)
105103 }
106- let name = lossyUTF8 ( Array ( bytes [ 0 ..< layout. nameEnd] ) )
104+ let name = lossyUTF8 ( bytes [ 0 ..< layout. nameEnd] )
107105 return MaterializedHeader (
108106 header: ResourceHeader ( name: name, size: layout. size) ,
109107 payloadStart: layout. payloadStart
@@ -127,12 +125,10 @@ public enum ResourceFrameCodec {
127125 let sizeEnd = firstIndex ( of: separator, in: bytes, from: sizeStart) else {
128126 throw . missingSizeSeparator
129127 }
130- let sizeBytes = Array ( bytes [ sizeStart..< sizeEnd] )
131- guard !sizeBytes. isEmpty else {
128+ guard sizeStart < sizeEnd else {
132129 throw . emptySize
133130 }
134- guard let sizeString = decodeSizeToken ( sizeBytes) ,
135- let size = parseNonNegativeInt ( sizeString) else {
131+ guard let size = parseNonNegativeInt ( bytes, start: sizeStart, end: sizeEnd) else {
136132 throw . invalidSize
137133 }
138134 return HeaderLayout ( nameEnd: nameEnd, payloadStart: sizeEnd + 1 , size: size)
@@ -149,23 +145,21 @@ public enum ResourceFrameCodec {
149145 return nil
150146 }
151147
152- private static func decodeSizeToken( _ bytes: [ UInt8 ] ) -> String ? {
153- // Strict UTF-8: a non-numeric / malformed size token is a framing error,
154- // never substituted. Reuses the Embedded-clean helper from LibP2PCore.
155- decodeUTF8Strict ( bytes)
156- }
157-
158- /// Parses a non-negative base-10 integer from `string`, rejecting any
148+ /// Parses a non-negative base-10 integer from ASCII bytes, rejecting any
159149 /// non-digit character, leading sign, or overflow. Returns `nil` on failure.
160- private static func parseNonNegativeInt( _ string: String ) -> Int ? {
150+ private static func parseNonNegativeInt(
151+ _ bytes: [ UInt8 ] ,
152+ start: Int ,
153+ end: Int
154+ ) -> Int ? {
161155 var value = 0
162- var sawDigit = false
163- for scalar in string. unicodeScalars {
164- guard scalar. value >= 48 , scalar. value <= 57 else {
156+ var index = start
157+ while index < end {
158+ let byte = bytes [ index]
159+ guard byte >= 48 , byte <= 57 else {
165160 return nil
166161 }
167- sawDigit = true
168- let digit = Int ( scalar. value - 48 )
162+ let digit = Int ( byte - 48 )
169163 let ( multiplied, overflowMul) = value. multipliedReportingOverflow ( by: 10 )
170164 guard !overflowMul else {
171165 return nil
@@ -175,14 +169,12 @@ public enum ResourceFrameCodec {
175169 return nil
176170 }
177171 value = added
178- }
179- guard sawDigit else {
180- return nil
172+ index += 1
181173 }
182174 return value
183175 }
184176
185- private static func lossyUTF8( _ bytes: [ UInt8 ] ) -> String {
177+ private static func lossyUTF8< Bytes : Collection > ( _ bytes: Bytes ) -> String where Bytes . Element == UInt8 {
186178 String ( decoding: bytes, as: UTF8 . self)
187179 }
188180}
0 commit comments