@@ -121,7 +121,7 @@ open class RedisChannelHandler : ChannelInboundHandler,
121121 let count = array. count
122122 out = ctx. channel. allocator. buffer ( capacity: 1 + 4 + 3 + count * 32 )
123123 out. write ( integer: UInt8 ( 42 ) ) // *
124- out. write ( string : String ( array. count, radix : 10 ) )
124+ out. write ( integerAsString : array. count)
125125 out. write ( bytes: eol)
126126 for item in array {
127127 encode ( ctx: ctx, data: item, level: 1 , out: & out)
@@ -229,7 +229,7 @@ open class RedisChannelHandler : ChannelInboundHandler,
229229 case . array( let array) : // *
230230 if let array = array {
231231 out. write ( integer: UInt8 ( 42 ) ) // *
232- out. write ( string : String ( array. count, radix : 10 ) )
232+ out. write ( integerAsString : array. count)
233233 out. write ( bytes: eol)
234234 for item in array {
235235 encode ( ctx: ctx, data: item, level: level + 1 , out: & out)
@@ -264,31 +264,69 @@ fileprivate enum ConstantBuffers {
264264 } ( )
265265}
266266
267+ fileprivate extension BinaryInteger {
268+
269+ var numberOfDecimalDigits : Int {
270+ @inline ( __always) get {
271+ var value = self
272+ var count = 0
273+
274+ repeat {
275+ value /= 10
276+ count += 1
277+ }
278+ while value != 0
279+
280+ return count
281+ }
282+ }
283+ }
284+
267285extension ByteBuffer {
268286
269287 @discardableResult
270- public mutating func write< T: FixedWidthInteger > ( integerAsString integer: T ,
271- as: T . Type = T . self) -> Int
288+ public mutating func write< T: SignedInteger > ( integerAsString integer: T ,
289+ as: T . Type = T . self) -> Int
272290 {
273291 let bytesWritten = set ( integerAsString: integer, at: self . writerIndex)
274292 moveWriterIndex ( forwardBy: bytesWritten)
275293 return Int ( bytesWritten)
276294 }
277295
278296 @discardableResult
279- public mutating func set< T: FixedWidthInteger > ( integerAsString integer: T ,
280- at index: Int ,
281- as: T . Type = T . self) -> Int
297+ public mutating func set< T: SignedInteger > ( integerAsString integer: T ,
298+ at index: Int ,
299+ as: T . Type = T . self) -> Int
282300 {
283- var value = integer
301+ let charCount = integer. numberOfDecimalDigits + ( integer < 0 ? 1 : 0 )
302+ let avail = capacity - index
284303
285- #if true // slow, fixme
286- let len = String ( value, radix: 10 )
287- return set ( string: len, at: index) ! // TBD: why is this returning an Opt?
288- #else
289- return Swift . withUnsafeBytes ( of: & value) { ptr in
290- // TODO: do the itoa thing to make it fast
304+ if avail < charCount {
305+ changeCapacity ( to: capacity + ( charCount - avail) )
306+ }
307+
308+ self . withVeryUnsafeBytes { rbpp in
309+ let mrbpp = UnsafeMutableRawBufferPointer ( mutating: rbpp)
310+ let base = mrbpp. baseAddress!. assumingMemoryBound ( to: UInt8 . self)
311+ . advanced ( by: index)
312+ var cursor = base. advanced ( by: charCount)
313+
314+ let c0 : T = 48
315+ var negativeAbsoluteValue = integer < 0 ? integer : - integer
316+ repeat {
317+ cursor -= 1
318+ cursor. pointee = UInt8 ( c0 - ( negativeAbsoluteValue % 10 ) )
319+ negativeAbsoluteValue /= 10 ;
291320 }
292- #endif
321+ while negativeAbsoluteValue != 0
322+
323+ if integer < 0 {
324+ cursor -= 1
325+ cursor. pointee = 45 // -
326+ }
327+
328+ }
329+
330+ return charCount
293331 }
294332}
0 commit comments