You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
2.2 KiB
69 lines
2.2 KiB
![]()
2 years ago
|
/*
|
||
|
* Copyright 1999-2101 Alibaba Group.
|
||
|
*
|
||
|
* 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.
|
||
|
*/
|
||
|
|
||
|
//
|
||
|
// Created by zhouzhuo on 07/01/2017.
|
||
|
//
|
||
|
|
||
|
|
||
|
/// An instance property
|
||
|
struct Property {
|
||
|
let key: String
|
||
|
let value: Any
|
||
|
|
||
|
/// An instance property description
|
||
|
struct Description {
|
||
|
public let key: String
|
||
|
public let type: Any.Type
|
||
|
public let offset: Int
|
||
|
public func write(_ value: Any, to storage: UnsafeMutableRawPointer) {
|
||
|
return extensions(of: type).write(value, to: storage.advanced(by: offset))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Retrieve properties for `instance`
|
||
|
func getProperties(forInstance instance: Any) -> [Property]? {
|
||
|
if let props = getProperties(forType: type(of: instance)) {
|
||
|
var copy = extensions(of: instance)
|
||
|
let storage = copy.storage()
|
||
|
return props.map {
|
||
|
nextProperty(description: $0, storage: storage)
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
private func nextProperty(description: Property.Description, storage: UnsafeRawPointer) -> Property {
|
||
|
return Property(
|
||
|
key: description.key,
|
||
|
value: extensions(of: description.type).value(from: storage.advanced(by: description.offset))
|
||
|
)
|
||
|
}
|
||
|
|
||
|
/// Retrieve property descriptions for `type`
|
||
|
func getProperties(forType type: Any.Type) -> [Property.Description]? {
|
||
|
if let structDescriptor = Metadata.Struct(anyType: type) {
|
||
|
return structDescriptor.propertyDescriptions()
|
||
|
} else if let classDescriptor = Metadata.Class(anyType: type) {
|
||
|
return classDescriptor.propertyDescriptions()
|
||
|
} else if let objcClassDescriptor = Metadata.ObjcClassWrapper(anyType: type),
|
||
|
let targetType = objcClassDescriptor.targetType {
|
||
|
return getProperties(forType: targetType)
|
||
|
}
|
||
|
return nil
|
||
|
}
|