mirror of
https://github.com/google/flatbuffers.git
synced 2026-07-03 12:54:12 +00:00
[Swift] Flexbuffers native swift port (#8577)
* Offical Swift port for FlexBuffers This is the offical port for FlexBuffers within swift, and it introcudes a Common Module where code is shared between flatbuffers and flexbuffers. Writing most supported values like maps, vectors, nil and scalars into a flexbuffer buffer. And includes tests to verify that its similar to cpp * Reading a flexbuffer Implementing reading from a flexbuffer, enabling most of the buffers features, like most types, maps, vectors, typedvectors, and fixedtypedvectors. Currently, if an offset/object cant be read we default to a swift nil instead of the default flexbuffers 'null' with all values. * Fixes bazel breaking due to new project structure Address warnings within the library * Adds comment on why we added the code & properly enforce the amout of bytes needed
This commit is contained in:
137
swift/Sources/FlexBuffers/Utils/Value.swift
Normal file
137
swift/Sources/FlexBuffers/Utils/Value.swift
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2024 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Value: Equatable {
|
||||
|
||||
@usableFromInline
|
||||
enum Union: Equatable {
|
||||
case i(Int64)
|
||||
case u(UInt64)
|
||||
case f(Double)
|
||||
}
|
||||
|
||||
var sloc: Union
|
||||
let type: FlexBufferType
|
||||
let bitWidth: BitWidth
|
||||
|
||||
@inline(__always)
|
||||
private init() {
|
||||
sloc = .i(0)
|
||||
type = .null
|
||||
bitWidth = .w8
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
init(bool: Bool) {
|
||||
sloc = .u(bool ? 1 : 0)
|
||||
type = .bool
|
||||
bitWidth = .w8
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
init(v: UInt64, type: FlexBufferType, bitWidth: BitWidth) {
|
||||
sloc = .u(v)
|
||||
self.type = type
|
||||
self.bitWidth = bitWidth
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
init(v: Int64, type: FlexBufferType, bitWidth: BitWidth) {
|
||||
sloc = .i(v)
|
||||
self.type = type
|
||||
self.bitWidth = bitWidth
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
init(v: Double, type: FlexBufferType, bitWidth: BitWidth) {
|
||||
sloc = .f(v)
|
||||
self.type = type
|
||||
self.bitWidth = bitWidth
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
init(sloc: Union, type: FlexBufferType, bitWidth: BitWidth) {
|
||||
self.sloc = sloc
|
||||
self.type = type
|
||||
self.bitWidth = bitWidth
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
var i: Int64 {
|
||||
switch sloc {
|
||||
case .i(let v): v
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
var u: UInt64 {
|
||||
switch sloc {
|
||||
case .u(let v): v
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
var f: Double {
|
||||
switch sloc {
|
||||
case .f(let v): v
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
|
||||
static let `nil` = Value()
|
||||
}
|
||||
|
||||
extension Value {
|
||||
@usableFromInline
|
||||
@inline(__always)
|
||||
func elementWidth(size: Int, index: UInt64) -> BitWidth {
|
||||
if isInline(type) {
|
||||
return bitWidth
|
||||
} else {
|
||||
for byteWidth in stride(from: 1, to: MemoryLayout<UInt64>.size, by: 2) {
|
||||
let _offsetLoc: UInt64 = numericCast(numericCast(size) &+ padding(
|
||||
bufSize: numericCast(size),
|
||||
elementSize: numericCast(byteWidth)))
|
||||
let offsetLoc = _offsetLoc &+ (index &* numericCast(byteWidth))
|
||||
let offset = offsetLoc &- u
|
||||
|
||||
let bitWidth = widthU(offset)
|
||||
if (UInt32.one << bitWidth.rawValue) == byteWidth {
|
||||
return bitWidth
|
||||
}
|
||||
}
|
||||
return .w64
|
||||
}
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
func storedPackedType(width: BitWidth = .w8) -> UInt8 {
|
||||
packedType(bitWidth: storedWidth(width: width), type: type)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
private func storedWidth(width: BitWidth) -> BitWidth {
|
||||
if isInline(type) {
|
||||
return max(bitWidth, width)
|
||||
} else {
|
||||
return bitWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user