VWT functions and when to use them #48
-
Echo's VWT exposes the following functions: typealias P = UnsafeMutableRawPointer
/// Given a buffer an instance of the type in the source buffer, initialize
/// the destination buffer with a copy of the source.
public func initializeBufferWithCopyOfBuffer(_ dest: P, _ source: P)
/// Given an invalid instance of this type and a valid instance of this type,
/// copy the source instance into the destination.
public func initializeWithCopy(_ dest: P, _ source: P)
/// Given a valid instance of this type and another valid instance of this
/// type, copy the contents from the source into the destination.
public func assignWithCopy(_ dest: P, _ source: P)
/// Given an invalid instance of this type and a valid instance of this type,
/// initialize the destination by destroying the source instance.
public func initializeWithTake(_ dest: P, _ source: P)
/// Given a valid instance of this type and another valid instance of this
/// type, copy the contents from the source instance into the destination
/// while also destroying the source instance.
public func assignWithTake(_ dest: P, _ source: P) Right now, my biggest source of confusion is the difference between Consider the following scenario: I have a non-POD and I want to store it in space I've just allocated for an object, struct, or enum payload. I currently have a pointer to whatever instance it is I'm populating, and I have the value I want to store as Let's look at my helper function for constructing an instance of a struct, given a dictionary of key-value pairs: extension StructMetadata {
func createInstance(props: [String: Any] = [:]) -> Any{
var box = AnyExistentialContainer(metadata: self)
for (key, value) in props {
let fieldType = self.fieldType(for: key)!
if !fieldType.vwt.flags.isPOD {
/* Use one of the above functions to perform the copy here */
} else {
// box.getValueBuffer() will automatically call
// allocateBoxForExistential as needed
self.set(value: value, forKey: key, pointer: box.getValueBuffer())
}
}
return box.toAny // unsafeBitCast(box, to: Any.self)
}
} I have three questions:
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
The idea of the VWT functions is that they do the necessary
extension StructMetadata {
func createInstance(props: [String: Any] = [:]) -> Any {
var box = AnyExistentialContainer(metadata: self)
for (i, record) in descriptor.fields.records.enumerated() {
guard let value = props[record.name] else {
fatalError("Cannot initialize a struct without property")
}
var valueBox = container(for: value)
vwt.initializeWithCopy(box.getValueBuffer() + fieldOffsets[i], valueBox.projectValue())
}
return box.toAny
}
}
|
Beta Was this translation helpful? Give feedback.
The idea of the VWT functions is that they do the necessary
retain
/releases
for us, so we don't need to do any of that.initialize
will make an invalid destination valid, andassign
will take a valid destination and make it a copy/will take the value from the source. The original value in destination before the assign will do whatever cleanup is required in the VWT function.