@@ -15,64 +15,50 @@ public class ByteReader {
1515 public let data : Data
1616
1717 /// Offset to the byte in `data` which will be read next.
18- public var offset : Int {
19- get {
20- return self . _offset + self . dataStartIndex
21- }
22- set {
23- self . _offset = newValue - self . dataStartIndex
24- }
25- }
26-
27- var _offset : Int
28-
29- /*
30- Generally speaking, what we are doing here is not really safe: pointer can become invalid if the storage of `data`
31- is non-contiguous, but (unfortunately, in a way) I was unable to produce an example which would cause any issues.
32-
33- Despite this, it was still decided to use this implementation strategy because:
34- 1. We cannot use `Data.withUnsafeBytes` because it is ridiculously slow.
35- 2. We cannot use `Data.copyBytes` because, well, it copies bytes.
36- 3. We would like to switch to `UnsafePointer` instead of `Data` to eliminate redundant out of bounds checks
37- (because we check indices ourselves and can guarantee that they are correct), and, thus, significantly improve
38- performance.
39-
40- Finally, it is worth mentioning that `NSData` actually has a convenient property `bytes` which provides access
41- to the pointer to the storage, but, for some reason, `Data` doesn't have it. We also cannot convert between `Data`
42- to `NSData` using `as` operator since it is not supposed to work on non-Darwin platforms (but, surprisingly, it
43- works with Swift 4.2).
44- */
45- final let ptr : UnsafeBufferPointer < UInt8 >
46- private final let dataStartIndex : Int // For efficient (without access to `data`) implementation of `offset`.
18+ public var offset : Int
4719
4820 /**
4921 True, if `offset` points at any position after the last byte in `data`.
5022
5123 - Note: It generally means that all bytes have been read.
5224 */
5325 public var isFinished : Bool {
54- return self . size <= self . _offset
26+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
27+ return { ( data: Data , offset: Int ) -> Bool in
28+ return data. endIndex <= offset
29+ } ( self . data, self . offset)
30+ #else
31+ return self . data. endIndex <= self . offset
32+ #endif
5533 }
5634
5735 /// Amount of bytes left to read.
5836 public var bytesLeft : Int {
59- return self . size - self . _offset
37+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
38+ return { ( data: Data , offset: Int ) -> Int in
39+ return data. endIndex - offset
40+ } ( self . data, self . offset)
41+ #else
42+ return self . data. endIndex - self . offset
43+ #endif
6044 }
6145
6246 /// Amount of bytes that were already read.
6347 public var bytesRead : Int {
64- return self . _offset
48+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
49+ return { ( data: Data , offset: Int ) -> Int in
50+ return offset - data. startIndex
51+ } ( self . data, self . offset)
52+ #else
53+ return self . offset - self . data. startIndex
54+ #endif
6555 }
6656
6757 /// Creates an instance for reading bytes from `data`.
6858 public init ( data: Data ) {
6959 self . size = data. count
7060 self . data = data
71- self . _offset = 0
72- self . ptr = data. withUnsafeBytes { ( ptr: UnsafePointer < UInt8 > ) -> UnsafeBufferPointer < UInt8 > in
73- return UnsafeBufferPointer < UInt8 > ( start: ptr, count: data. count)
74- }
75- self . dataStartIndex = data. startIndex
61+ self . offset = data. startIndex
7662 }
7763
7864 /**
@@ -81,9 +67,17 @@ public class ByteReader {
8167 - Precondition: There MUST be enough data left.
8268 */
8369 public func byte( ) -> UInt8 {
84- precondition ( self . _offset < self . size)
85- defer { self . _offset += 1 }
86- return self . ptr [ self . _offset]
70+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
71+ return { ( data: Data , offset: inout Int ) -> UInt8 in
72+ precondition ( offset < data. endIndex)
73+ defer { offset += 1 }
74+ return data [ offset]
75+ } ( self . data, & self . offset)
76+ #else
77+ precondition ( self . offset < self . data. endIndex)
78+ defer { self . offset += 1 }
79+ return self . data [ self . offset]
80+ #endif
8781 }
8882
8983 /**
@@ -94,14 +88,17 @@ public class ByteReader {
9488 */
9589 public func bytes( count: Int ) -> [ UInt8 ] {
9690 precondition ( count >= 0 )
97- precondition ( bytesLeft >= count)
98- var result = [ UInt8] ( )
99- result. reserveCapacity ( count)
100- for _ in 0 ..< count {
101- result. append ( self . ptr [ self . _offset] )
102- self . _offset += 1
103- }
104- return result
91+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
92+ return { ( data: Data , offset: inout Int ) -> [ UInt8 ] in
93+ precondition ( data. endIndex - offset >= count)
94+ defer { offset += count }
95+ return data [ offset..< offset + count] . toArray ( type: UInt8 . self, count: count)
96+ } ( self . data, & self . offset)
97+ #else
98+ precondition ( bytesLeft >= count)
99+ defer { self . offset += count }
100+ return self . data [ self . offset..< self . offset + count] . toArray ( type: UInt8 . self, count: count)
101+ #endif
105102 }
106103
107104 /**
@@ -114,12 +111,25 @@ public class ByteReader {
114111 precondition ( count >= 0 )
115112 // TODO: If uintX() could be force inlined or something in the future then probably it would make sense
116113 // to use them for `count` == 2, 4 or 8.
117- var result = 0
118- for i in 0 ..< count {
119- result += Int ( truncatingIfNeeded: self . ptr [ self . _offset] ) << ( 8 * i)
120- self . _offset += 1
121- }
122- return result
114+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
115+ return { ( data: Data , offset: inout Int ) -> Int in
116+ precondition ( data. endIndex - offset >= count)
117+ var result = 0
118+ for i in 0 ..< count {
119+ result += Int ( truncatingIfNeeded: data [ offset] ) << ( 8 * i)
120+ offset += 1
121+ }
122+ return result
123+ } ( self . data, & self . offset)
124+ #else
125+ precondition ( bytesLeft >= count)
126+ var result = 0
127+ for i in 0 ..< count {
128+ result += Int ( truncatingIfNeeded: self . data [ self . offset] ) << ( 8 * i)
129+ self . offset += 1
130+ }
131+ return result
132+ #endif
123133 }
124134
125135 /**
@@ -128,7 +138,17 @@ public class ByteReader {
128138 - Precondition: There MUST be enough data left.
129139 */
130140 public func uint64( ) -> UInt64 {
131- return self . uint64 ( fromBytes: 8 )
141+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
142+ return { ( data: Data , offset: inout Int ) -> UInt64 in
143+ precondition ( data. endIndex - offset >= 8 )
144+ defer { offset += 8 }
145+ return data [ offset..< offset + 8 ] . to ( type: UInt64 . self)
146+ } ( self . data, & self . offset)
147+ #else
148+ precondition ( bytesLeft >= 8 )
149+ defer { self . offset += 8 }
150+ return self . data [ self . offset..< self . offset + 8 ] . to ( type: UInt64 . self)
151+ #endif
132152 }
133153
134154 /**
@@ -142,13 +162,25 @@ public class ByteReader {
142162 */
143163 public func uint64( fromBytes count: Int ) -> UInt64 {
144164 precondition ( 0 ... 8 ~= count)
145- precondition ( bytesLeft >= count)
146- var result = 0 as UInt64
147- for i in 0 ..< count {
148- result += UInt64 ( truncatingIfNeeded: self . ptr [ self . _offset] ) << ( 8 * i)
149- self . _offset += 1
150- }
151- return result
165+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
166+ return { ( data: Data , offset: inout Int ) -> UInt64 in
167+ precondition ( data. endIndex - offset >= count)
168+ var result = 0 as UInt64
169+ for i in 0 ..< count {
170+ result += UInt64 ( truncatingIfNeeded: data [ offset] ) << ( 8 * i)
171+ offset += 1
172+ }
173+ return result
174+ } ( self . data, & self . offset)
175+ #else
176+ precondition ( bytesLeft >= count)
177+ var result = 0 as UInt64
178+ for i in 0 ..< count {
179+ result += UInt64 ( truncatingIfNeeded: self . data [ self . offset] ) << ( 8 * i)
180+ self . offset += 1
181+ }
182+ return result
183+ #endif
152184 }
153185
154186 /**
@@ -157,7 +189,17 @@ public class ByteReader {
157189 - Precondition: There MUST be enough data left.
158190 */
159191 public func uint32( ) -> UInt32 {
160- return self . uint32 ( fromBytes: 4 )
192+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
193+ return { ( data: Data , offset: inout Int ) -> UInt32 in
194+ precondition ( data. endIndex - offset >= 4 )
195+ defer { offset += 4 }
196+ return data [ offset..< offset + 4 ] . to ( type: UInt32 . self)
197+ } ( self . data, & self . offset)
198+ #else
199+ precondition ( bytesLeft >= 4 )
200+ defer { self . offset += 4 }
201+ return self . data [ self . offset..< self . offset + 4 ] . to ( type: UInt32 . self)
202+ #endif
161203 }
162204
163205 /**
@@ -171,13 +213,25 @@ public class ByteReader {
171213 */
172214 public func uint32( fromBytes count: Int ) -> UInt32 {
173215 precondition ( 0 ... 4 ~= count)
174- precondition ( bytesLeft >= count)
175- var result = 0 as UInt32
176- for i in 0 ..< count {
177- result += UInt32 ( truncatingIfNeeded: self . ptr [ self . _offset] ) << ( 8 * i)
178- self . _offset += 1
179- }
180- return result
216+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
217+ return { ( data: Data , offset: inout Int ) -> UInt32 in
218+ precondition ( data. endIndex - offset >= count)
219+ var result = 0 as UInt32
220+ for i in 0 ..< count {
221+ result += UInt32 ( truncatingIfNeeded: data [ offset] ) << ( 8 * i)
222+ offset += 1
223+ }
224+ return result
225+ } ( self . data, & self . offset)
226+ #else
227+ precondition ( bytesLeft >= count)
228+ var result = 0 as UInt32
229+ for i in 0 ..< count {
230+ result += UInt32 ( truncatingIfNeeded: self . data [ self . offset] ) << ( 8 * i)
231+ self . offset += 1
232+ }
233+ return result
234+ #endif
181235 }
182236
183237 /**
@@ -186,7 +240,17 @@ public class ByteReader {
186240 - Precondition: There MUST be enough data left.
187241 */
188242 public func uint16( ) -> UInt16 {
189- return self . uint16 ( fromBytes: 2 )
243+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
244+ return { ( data: Data , offset: inout Int ) -> UInt16 in
245+ precondition ( data. endIndex - offset >= 2 )
246+ defer { offset += 2 }
247+ return data [ offset..< offset + 2 ] . to ( type: UInt16 . self)
248+ } ( self . data, & self . offset)
249+ #else
250+ precondition ( bytesLeft >= 2 )
251+ defer { self . offset += 2 }
252+ return self . data [ self . offset..< self . offset + 2 ] . to ( type: UInt16 . self)
253+ #endif
190254 }
191255
192256 /**
@@ -200,13 +264,25 @@ public class ByteReader {
200264 */
201265 public func uint16( fromBytes count: Int ) -> UInt16 {
202266 precondition ( 0 ... 2 ~= count)
203- precondition ( bytesLeft >= count)
204- var result = 0 as UInt16
205- for i in 0 ..< count {
206- result += UInt16 ( truncatingIfNeeded: self . ptr [ self . _offset] ) << ( 8 * i)
207- self . _offset += 1
208- }
209- return result
267+ #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
268+ return { ( data: Data , offset: inout Int ) -> UInt16 in
269+ precondition ( data. endIndex - offset >= count)
270+ var result = 0 as UInt16
271+ for i in 0 ..< count {
272+ result += UInt16 ( truncatingIfNeeded: data [ offset] ) << ( 8 * i)
273+ offset += 1
274+ }
275+ return result
276+ } ( self . data, & self . offset)
277+ #else
278+ precondition ( bytesLeft >= count)
279+ var result = 0 as UInt16
280+ for i in 0 ..< count {
281+ result += UInt16 ( truncatingIfNeeded: self . data [ self . offset] ) << ( 8 * i)
282+ self . offset += 1
283+ }
284+ return result
285+ #endif
210286 }
211287
212288}
0 commit comments