mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
357 lines
10 KiB
Plaintext
357 lines
10 KiB
Plaintext
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// MessagePack-based serialization and deserialization.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public struct MsgPackSerializer {
|
|
public static func serialize<
|
|
T : SerializableFixedDictionaryType
|
|
>(var value: T) -> [UInt8] {
|
|
// FIXME(performance): we could serialize directly into a byte stream
|
|
// without creating an intermediate data structure if our MsgPack
|
|
// serializer could accept arrays and dictionaries of unknown length and
|
|
// then back-patch the length into the byte stream when it becomes known.
|
|
var serializerImpl = _MsgPackSerializerImpl()
|
|
value.serializeDeserialize(&serializerImpl)
|
|
return serializerImpl._value!.serialize()
|
|
}
|
|
}
|
|
|
|
internal struct _MsgPackSerializerImpl {
|
|
internal var _value: MsgPackVariant? = nil
|
|
}
|
|
|
|
extension _MsgPackSerializerImpl : ScalarSerializerType {
|
|
internal mutating func add(inout value: Int64) {
|
|
_precondition(_value == nil, "value has been set already")
|
|
_value = .Int64(value)
|
|
}
|
|
|
|
internal mutating func add(inout value: UInt64) {
|
|
_precondition(_value == nil, "value has been set already")
|
|
_value = .UInt64(value)
|
|
}
|
|
|
|
internal mutating func add(inout value: Float) {
|
|
_precondition(_value == nil, "value has been set already")
|
|
_value = .Float32(value)
|
|
}
|
|
|
|
internal mutating func add(inout value: Double) {
|
|
_precondition(_value == nil, "value has been set already")
|
|
_value = .Float64(value)
|
|
}
|
|
|
|
internal mutating func add(inout value: Bool) {
|
|
_precondition(_value == nil, "value has been set already")
|
|
_value = .Bool(value)
|
|
}
|
|
|
|
internal mutating func add(inout value: String) {
|
|
_precondition(_value == nil, "value has been set already")
|
|
_value = .String(value)
|
|
}
|
|
}
|
|
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal func _toMsgPackVariant<
|
|
Value : RangeReplaceableCollectionType
|
|
where
|
|
Value.Generator.Element : Serializable${value_kind}Type
|
|
>(inout value: Value) -> MsgPackVariant {
|
|
% if value_kind == 'Scalar':
|
|
if let byteBlob as [UInt8] = value {
|
|
return .Binary(byteBlob)
|
|
}
|
|
% end
|
|
return .Array(MsgPackVariantArray(map(value) {
|
|
(var element) -> MsgPackVariant in
|
|
var serializerImpl = _MsgPackSerializerImpl()
|
|
element.serializeDeserialize(&serializerImpl)
|
|
return serializerImpl._value!
|
|
}))
|
|
}
|
|
% end
|
|
|
|
extension _MsgPackSerializerImpl : ArraySerializerType {
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal mutating func add<
|
|
Value : RangeReplaceableCollectionType
|
|
where
|
|
Value.Generator.Element : Serializable${value_kind}Type
|
|
>(inout value: Value) {
|
|
_precondition(_value == nil, "value has been set already")
|
|
_value = _toMsgPackVariant(&value)
|
|
}
|
|
% end
|
|
}
|
|
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal func _toMsgPackVariant<
|
|
Value : Serializable${value_kind}Type
|
|
>(inout value: [String : Value]) -> MsgPackVariant {
|
|
var variantDictionary: [String : MsgPackVariant] = [:]
|
|
for (dictKey, dictValue) in value {
|
|
var mutableValue = dictValue
|
|
var serializerImpl = _MsgPackSerializerImpl()
|
|
mutableValue.serializeDeserialize(&serializerImpl)
|
|
variantDictionary[dictKey] = serializerImpl._value!
|
|
}
|
|
return .Map(MsgPackVariantMap(variantDictionary))
|
|
}
|
|
% end
|
|
|
|
extension _MsgPackSerializerImpl : DictionarySerializerType {
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal mutating func add<
|
|
Value : Serializable${value_kind}Type
|
|
>(inout value: [String : Value]) {
|
|
_precondition(_value == nil, "value has been set already")
|
|
_value = _toMsgPackVariant(&value)
|
|
}
|
|
% end
|
|
}
|
|
|
|
extension _MsgPackSerializerImpl : FixedDictionarySerializerType {
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal mutating func addKey<
|
|
Value : Serializable${value_kind}Type
|
|
>(key: String, inout value: Value) {
|
|
var serializerImpl = _MsgPackSerializerImpl()
|
|
value.serializeDeserialize(&serializerImpl)
|
|
_addKeyImpl(key, value: serializerImpl._value!)
|
|
}
|
|
% end
|
|
|
|
internal mutating func addKey<
|
|
Value : SerializableScalarType
|
|
>(key: String, inout value: [Value]) {
|
|
_addKeyImpl(key, value: _toMsgPackVariant(&value))
|
|
}
|
|
|
|
internal mutating func addKey<
|
|
Value : SerializableScalarType
|
|
>(key: String, inout value: [String : Value]) {
|
|
_addKeyImpl(key, value: _toMsgPackVariant(&value))
|
|
}
|
|
|
|
internal mutating func _addKeyImpl(key: String, value: MsgPackVariant) {
|
|
if let existingValue? = _value {
|
|
switch existingValue {
|
|
case .Map(var map):
|
|
_value = nil
|
|
map._append(key: .String(key), value: value)
|
|
_value = .Map(map)
|
|
default:
|
|
_preconditionFailure("impossible")
|
|
}
|
|
} else {
|
|
_value = .Map(MsgPackVariantMap([key: value]))
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct MsgPackDeserializer {
|
|
public static func deserialize<
|
|
T : SerializableFixedDictionaryType
|
|
>(bytes: [UInt8]) -> T {
|
|
var value = T(forDeserialization: ())
|
|
var deserializerImpl =
|
|
_MsgPackDeserializerImpl(MsgPackVariant(bytes: bytes)!)
|
|
value.serializeDeserialize(&deserializerImpl)
|
|
return value
|
|
}
|
|
}
|
|
|
|
internal struct _MsgPackDeserializerImpl {
|
|
internal var _value: MsgPackVariant
|
|
|
|
internal init(_ value: MsgPackVariant) {
|
|
_value = value
|
|
}
|
|
}
|
|
|
|
extension _MsgPackDeserializerImpl : ScalarSerializerType {
|
|
internal mutating func add(inout value: Int64) {
|
|
switch _value {
|
|
case .Int64(let i):
|
|
value = i
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
|
|
internal mutating func add(inout value: UInt64) {
|
|
switch _value {
|
|
case .UInt64(let i):
|
|
value = i
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
|
|
internal mutating func add(inout value: Float) {
|
|
switch _value {
|
|
case .Float32(let f):
|
|
value = f
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
|
|
internal mutating func add(inout value: Double) {
|
|
switch _value {
|
|
case .Float64(let f):
|
|
value = f
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
|
|
internal mutating func add(inout value: Bool) {
|
|
switch _value {
|
|
case .Bool(let b):
|
|
value = b
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
|
|
internal mutating func add(inout value: String) {
|
|
switch _value {
|
|
case .String(let s):
|
|
value = s
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
}
|
|
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal func _fromMsgPackVariant<
|
|
Value : RangeReplaceableCollectionType
|
|
where
|
|
Value.Generator.Element : Serializable${value_kind}Type
|
|
>(msgPackVariant: MsgPackVariant, inout value: Value) {
|
|
switch msgPackVariant {
|
|
% if value_kind == 'Scalar':
|
|
case .Binary(let byteBlob):
|
|
value = byteBlob as! Value
|
|
% end
|
|
case .Array(let a):
|
|
var elements: [Value.Generator.Element] = []
|
|
elements.reserveCapacity(a.count)
|
|
for e in a {
|
|
var element = Value.Generator.Element(forDeserialization: ())
|
|
var deserializerImpl = _MsgPackDeserializerImpl(e)
|
|
element.serializeDeserialize(&deserializerImpl)
|
|
elements.append(element)
|
|
}
|
|
value.replaceRange(value.startIndex..<value.endIndex, with: elements)
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
% end
|
|
|
|
extension _MsgPackDeserializerImpl : ArraySerializerType {
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal mutating func add<
|
|
Value : RangeReplaceableCollectionType
|
|
where
|
|
Value.Generator.Element : Serializable${value_kind}Type
|
|
>(inout value: Value) {
|
|
_fromMsgPackVariant(_value, &value)
|
|
}
|
|
% end
|
|
}
|
|
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal func _fromMsgPackVariant<
|
|
Value : Serializable${value_kind}Type
|
|
>(msgPackVariant: MsgPackVariant, inout value: [String : Value]) {
|
|
switch msgPackVariant {
|
|
case .Map(let m):
|
|
value.removeAll()
|
|
for (k, v) in m {
|
|
switch k {
|
|
case .String(let s):
|
|
var element = Value(forDeserialization: ())
|
|
var deserializerImpl = _MsgPackDeserializerImpl(v)
|
|
element.serializeDeserialize(&deserializerImpl)
|
|
value[s] = element
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
% end
|
|
|
|
extension _MsgPackDeserializerImpl : DictionarySerializerType {
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal mutating func add<
|
|
Value : Serializable${value_kind}Type
|
|
>(inout value: [String : Value]) {
|
|
_fromMsgPackVariant(_value, &value)
|
|
}
|
|
% end
|
|
}
|
|
|
|
extension _MsgPackDeserializerImpl : FixedDictionarySerializerType {
|
|
% for value_kind in [ 'Scalar', 'Array', 'Dictionary', 'FixedDictionary' ]:
|
|
internal mutating func addKey<
|
|
Value : Serializable${value_kind}Type>(
|
|
key: String, inout value: Value) {
|
|
var deserializerImpl = _MsgPackDeserializerImpl(_findValueForKey(key))
|
|
value.serializeDeserialize(&deserializerImpl)
|
|
}
|
|
% end
|
|
|
|
internal mutating func addKey<
|
|
Value : SerializableScalarType
|
|
>(key: String, inout value: [Value]) {
|
|
_fromMsgPackVariant(_findValueForKey(key), &value)
|
|
}
|
|
|
|
internal mutating func addKey<
|
|
Value : SerializableScalarType
|
|
>(key: String, inout value: [String : Value]) {
|
|
_fromMsgPackVariant(_findValueForKey(key), &value)
|
|
}
|
|
|
|
internal func _findValueForKey(key: String) -> MsgPackVariant {
|
|
switch _value {
|
|
case .Map(let map):
|
|
for (k, v) in map {
|
|
switch k {
|
|
case .String(let s):
|
|
if key == s {
|
|
return v
|
|
}
|
|
default:
|
|
()
|
|
}
|
|
}
|
|
_preconditionFailure("key not found")
|
|
default:
|
|
_preconditionFailure("bad data")
|
|
}
|
|
}
|
|
}
|
|
|