@@ -37,7 +37,7 @@ public struct FlexBuffersWriter {
3737 private var hasDuplicatedKeys = false
3838 private var minBitWidth : BitWidth = . w8
3939 private var _bb : _InternalByteBuffer
40- private var stack : [ Value ] = [ ]
40+ private var stack : Stack = Stack ( )
4141 private var keyPool : [ Int : UInt ] = [ : ]
4242 private var stringPool : [ Int : UInt ] = [ : ]
4343 private var flags : BuilderFlag
@@ -148,7 +148,7 @@ public struct FlexBuffersWriter {
148148 typed: typed,
149149 fixed: fixed,
150150 keys: nil )
151- stack = Array ( stack [ ..< start] )
151+ stack. popLast ( start)
152152 stack. append ( vec)
153153 return vec. u
154154 }
@@ -217,7 +217,7 @@ public struct FlexBuffersWriter {
217217 typed: false ,
218218 fixed: false ,
219219 keys: keys)
220- stack = Array ( stack [ ..< start] )
220+ stack. popLast ( start)
221221 stack. append ( vec)
222222 return numericCast ( vec. u)
223223 }
@@ -830,13 +830,14 @@ public struct FlexBuffersWriter {
830830 let key , value : Value
831831 }
832832
833- stack [ start ... ] . withUnsafeMutableBytes { buffer in
833+ stack. withUnsafeMutableBytes ( start : start ) { buffer in
834834 var ptr = buffer. assumingMemoryBound ( to: TwoValue . self)
835835 ptr. sort { a, b in
836836 let aMem = _bb. memory. advanced ( by: numericCast ( a. key. u) )
837837 . assumingMemoryBound ( to: CChar . self)
838838 let bMem = _bb. memory. advanced ( by: numericCast ( b. key. u) )
839839 . assumingMemoryBound ( to: CChar . self)
840+
840841 let comp = strcmp ( aMem, bMem)
841842 if ( comp == 0 ) && a != b { hasDuplicatedKeys = true }
842843 return comp < 0
@@ -897,3 +898,129 @@ extension FlexBuffersWriter {
897898 return endMap ( start: start)
898899 }
899900}
901+
902+ fileprivate struct Stack : RandomAccessCollection {
903+ typealias Element = Value
904+ typealias Index = Int
905+
906+ private final class Storage {
907+ var memory : UnsafeMutableRawPointer
908+
909+ init ( capacity: Int , alignment: Int ) {
910+ memory = . allocate( byteCount: capacity, alignment: alignment)
911+ memset ( memory, 0 , capacity)
912+ }
913+
914+ deinit {
915+ memory. deallocate ( )
916+ }
917+ }
918+
919+ private static let initialCapacity = 10 &* MemoryLayout< Value> . stride
920+ private let storage : Storage
921+ private var capacity : Int
922+ private( set) var count : Int
923+
924+ var startIndex : Int {
925+ 0
926+ }
927+
928+ var endIndex : Int {
929+ count
930+ }
931+
932+ init ( ) {
933+ count = 0
934+ capacity = Self . initialCapacity
935+
936+ storage = Storage (
937+ capacity: capacity,
938+ alignment: MemoryLayout< Value> . alignment)
939+ }
940+
941+ @inline ( __always)
942+ subscript( position: Int ) -> Value {
943+ get {
944+ storage. memory. advanced ( by: position &* MemoryLayout< Value> . stride)
945+ . assumingMemoryBound ( to: Value . self) . pointee
946+ }
947+ set {
948+ storage. memory. advanced ( by: position &* MemoryLayout< Value> . stride)
949+ . assumingMemoryBound ( to: Value . self) . pointee = newValue
950+ }
951+ }
952+
953+ @inline ( __always)
954+ mutating func popLast( _ val: Int ) {
955+ count = if val < 0 {
956+ 0
957+ } else {
958+ val
959+ }
960+ }
961+
962+ mutating func append( _ value: Value ) {
963+ let writePosition = count &* MemoryLayout< Value> . stride
964+ if writePosition >= capacity {
965+ reallocate ( writePosition: writePosition)
966+ }
967+
968+ storage. memory. advanced ( by: writePosition) . storeBytes (
969+ of: value,
970+ as: Value . self)
971+ count += 1
972+ }
973+
974+ mutating func removeAll( keepingCapacity keepCapacity: Bool = false ) {
975+ count = 0
976+ if !keepCapacity {
977+ capacity = Self . initialCapacity
978+ storage. memory = UnsafeMutableRawPointer . allocate (
979+ byteCount: capacity,
980+ alignment: MemoryLayout< Value> . alignment)
981+ }
982+ memset ( storage. memory, 0 , capacity)
983+ }
984+
985+ @discardableResult
986+ mutating func withUnsafeMutableBytes< R> (
987+ start: Int ,
988+ _ body: ( UnsafeMutableRawBufferPointer ) throws -> R ) rethrows -> R
989+ {
990+ let startingPosition = start &* MemoryLayout< Value> . stride
991+ let pointer = storage. memory. advanced ( by: startingPosition)
992+ return try body ( UnsafeMutableRawBufferPointer (
993+ start: pointer,
994+ count: ( count &* MemoryLayout< Value> . stride) &- startingPosition) )
995+ }
996+
997+ @discardableResult
998+ mutating func withUnsafeMutableBytes< R> (
999+ _ body: ( UnsafeMutableRawBufferPointer ) throws
1000+ -> R ) rethrows -> R
1001+ {
1002+ return try body ( UnsafeMutableRawBufferPointer (
1003+ start: storage. memory,
1004+ count: count &* MemoryLayout< Value> . stride) )
1005+ }
1006+
1007+ mutating private func reallocate( writePosition: Int ) {
1008+ while capacity <= writePosition {
1009+ capacity = capacity << 1
1010+ }
1011+
1012+ /// solution take from Apple-NIO
1013+ capacity = capacity. convertToPowerofTwo
1014+
1015+ let newData = UnsafeMutableRawPointer . allocate (
1016+ byteCount: capacity,
1017+ alignment: MemoryLayout< Value> . alignment)
1018+ memset ( newData, 0 , capacity)
1019+ memcpy (
1020+ newData,
1021+ storage. memory,
1022+ writePosition)
1023+ storage. memory. deallocate ( )
1024+ storage. memory = newData
1025+ }
1026+ }
0 commit comments