@@ -37,12 +37,15 @@ 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
4444
4545 public init ( initialSize: Int = 1024 , flags: BuilderFlag = . shareKeys) {
46+ assert (
47+ isLitteEndian,
48+ " Swift FlexBuffers currently only supports little-endian systems " )
4649 _bb = _InternalByteBuffer ( initialSize: initialSize)
4750 self . flags = flags
4851 }
@@ -148,7 +151,7 @@ public struct FlexBuffersWriter {
148151 typed: typed,
149152 fixed: fixed,
150153 keys: nil )
151- stack = Array ( stack [ ..< start] )
154+ stack. popLast ( start)
152155 stack. append ( vec)
153156 return vec. u
154157 }
@@ -217,7 +220,7 @@ public struct FlexBuffersWriter {
217220 typed: false ,
218221 fixed: false ,
219222 keys: keys)
220- stack = Array ( stack [ ..< start] )
223+ stack. popLast ( start)
221224 stack. append ( vec)
222225 return numericCast ( vec. u)
223226 }
@@ -721,7 +724,7 @@ public struct FlexBuffersWriter {
721724 assert (
722725 vectorType == stack [ i] . type,
723726 """
724- If you get this assert you are writing a typed vector
727+ If you get this assert you are writing a typed vector
725728 with elements that are not all the same type
726729 """ )
727730 }
@@ -757,7 +760,7 @@ public struct FlexBuffersWriter {
757760 }
758761
759762 if !fixed {
760- write ( value: count, byteWidth: byteWidth)
763+ write ( value: UInt64 ( count) , byteWidth: byteWidth)
761764 }
762765
763766 let vloc = _bb. writerIndex
@@ -830,13 +833,14 @@ public struct FlexBuffersWriter {
830833 let key , value : Value
831834 }
832835
833- stack [ start ... ] . withUnsafeMutableBytes { buffer in
836+ stack. withUnsafeMutableBytes ( start : start ) { buffer in
834837 var ptr = buffer. assumingMemoryBound ( to: TwoValue . self)
835838 ptr. sort { a, b in
836839 let aMem = _bb. memory. advanced ( by: numericCast ( a. key. u) )
837840 . assumingMemoryBound ( to: CChar . self)
838841 let bMem = _bb. memory. advanced ( by: numericCast ( b. key. u) )
839842 . assumingMemoryBound ( to: CChar . self)
843+
840844 let comp = strcmp ( aMem, bMem)
841845 if ( comp == 0 ) && a != b { hasDuplicatedKeys = true }
842846 return comp < 0
@@ -897,3 +901,129 @@ extension FlexBuffersWriter {
897901 return endMap ( start: start)
898902 }
899903}
904+
905+ fileprivate struct Stack : RandomAccessCollection {
906+ typealias Element = Value
907+ typealias Index = Int
908+
909+ private final class Storage {
910+ var memory : UnsafeMutableRawPointer
911+
912+ init ( capacity: Int , alignment: Int ) {
913+ memory = . allocate( byteCount: capacity, alignment: alignment)
914+ memset ( memory, 0 , capacity)
915+ }
916+
917+ deinit {
918+ memory. deallocate ( )
919+ }
920+ }
921+
922+ private static let initialCapacity = 10 &* MemoryLayout< Value> . stride
923+ private let storage : Storage
924+ private var capacity : Int
925+ private( set) var count : Int
926+
927+ var startIndex : Int {
928+ 0
929+ }
930+
931+ var endIndex : Int {
932+ count
933+ }
934+
935+ init ( ) {
936+ count = 0
937+ capacity = Self . initialCapacity
938+
939+ storage = Storage (
940+ capacity: capacity,
941+ alignment: MemoryLayout< Value> . alignment)
942+ }
943+
944+ @inline ( __always)
945+ subscript( position: Int ) -> Value {
946+ get {
947+ storage. memory. advanced ( by: position &* MemoryLayout< Value> . stride)
948+ . assumingMemoryBound ( to: Value . self) . pointee
949+ }
950+ set {
951+ storage. memory. advanced ( by: position &* MemoryLayout< Value> . stride)
952+ . assumingMemoryBound ( to: Value . self) . pointee = newValue
953+ }
954+ }
955+
956+ @inline ( __always)
957+ mutating func popLast( _ val: Int ) {
958+ count = if val < 0 {
959+ 0
960+ } else {
961+ val
962+ }
963+ }
964+
965+ mutating func append( _ value: Value ) {
966+ let writePosition = count &* MemoryLayout< Value> . stride
967+ if writePosition >= capacity {
968+ reallocate ( writePosition: writePosition)
969+ }
970+
971+ storage. memory. advanced ( by: writePosition) . storeBytes (
972+ of: value,
973+ as: Value . self)
974+ count += 1
975+ }
976+
977+ mutating func removeAll( keepingCapacity keepCapacity: Bool = false ) {
978+ count = 0
979+ if !keepCapacity {
980+ capacity = Self . initialCapacity
981+ storage. memory = UnsafeMutableRawPointer . allocate (
982+ byteCount: capacity,
983+ alignment: MemoryLayout< Value> . alignment)
984+ }
985+ memset ( storage. memory, 0 , capacity)
986+ }
987+
988+ @discardableResult
989+ mutating func withUnsafeMutableBytes< R> (
990+ start: Int ,
991+ _ body: ( UnsafeMutableRawBufferPointer ) throws -> R ) rethrows -> R
992+ {
993+ let startingPosition = start &* MemoryLayout< Value> . stride
994+ let pointer = storage. memory. advanced ( by: startingPosition)
995+ return try body ( UnsafeMutableRawBufferPointer (
996+ start: pointer,
997+ count: ( count &* MemoryLayout< Value> . stride) &- startingPosition) )
998+ }
999+
1000+ @discardableResult
1001+ mutating func withUnsafeMutableBytes< R> (
1002+ _ body: ( UnsafeMutableRawBufferPointer ) throws
1003+ -> R ) rethrows -> R
1004+ {
1005+ return try body ( UnsafeMutableRawBufferPointer (
1006+ start: storage. memory,
1007+ count: count &* MemoryLayout< Value> . stride) )
1008+ }
1009+
1010+ mutating private func reallocate( writePosition: Int ) {
1011+ while capacity <= writePosition {
1012+ capacity = capacity << 1
1013+ }
1014+
1015+ /// solution take from Apple-NIO
1016+ capacity = capacity. convertToPowerofTwo
1017+
1018+ let newData = UnsafeMutableRawPointer . allocate (
1019+ byteCount: capacity,
1020+ alignment: MemoryLayout< Value> . alignment)
1021+ memset ( newData, 0 , capacity)
1022+ memcpy (
1023+ newData,
1024+ storage. memory,
1025+ writePosition)
1026+ storage. memory. deallocate ( )
1027+ storage. memory = newData
1028+ }
1029+ }
0 commit comments