mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-09 21:24:14 +00:00
71e734b120
Add the option to calculate total size (inclusive size) by wrapping the existing iterator. This change provides a new iterator, `SizedIterator`, which wraps an existing iterator and adds a new field `size` to the output element. This is achieved with a two pass algorithm on the existing iterator: 1. Gather metadata for each element. This includes the total size up until that element and the range of elements that should be included in the size. 2. Return the result from the underlying iterator with the additional field. This algorithm is `O(N)` time on the number of elements in the iterator and `O(N)` time, storing 16 bytes per element. This isn't super expensive but is a lot more than the current algorithm which requires close to constant space. Because of this I've implemented it as a wrapper on the iterator rather than on by default, though it is now on in every one of our integration test cases. Test plan: - Added to the integration tests for full coverage.
114 lines
5.1 KiB
TOML
114 lines
5.1 KiB
TOML
# TODO: The tagged union tests should be updated when tagged union support is in:
|
|
# https://github.com/facebookexperimental/object-introspection/issues/234
|
|
includes = ["string", "unordered_map", "vector"]
|
|
definitions = '''
|
|
union MyUnion {
|
|
int n;
|
|
std::vector<int> vec;
|
|
std::unordered_map<std::string, std::string> map;
|
|
|
|
MyUnion(int n_) : n(n_) {}
|
|
MyUnion(const std::vector<int>& vec_) : vec(vec_) {}
|
|
MyUnion(const std::unordered_map<std::string, std::string>& map_) : map(map_) {}
|
|
MyUnion(const MyUnion& /*other*/) { /* we don't know which field to copy */ }
|
|
~MyUnion() {}
|
|
};
|
|
|
|
struct TaggedUnion {
|
|
MyUnion storage;
|
|
uint8_t tag;
|
|
|
|
TaggedUnion(const MyUnion& storage_, uint8_t tag_) : storage(0), tag(tag_) {
|
|
copyStorage(storage_);
|
|
}
|
|
|
|
TaggedUnion(const TaggedUnion& other) : storage(0), tag(other.tag) {
|
|
copyStorage(other.storage);
|
|
}
|
|
|
|
void copyStorage(const MyUnion& other) {
|
|
if (tag == 0) {
|
|
storage.n = other.n;
|
|
} else if (tag == 1) {
|
|
new (&storage.vec) decltype(MyUnion::vec){other.vec};
|
|
} else if (tag == 2) {
|
|
new (&storage.map) decltype(MyUnion::map){other.map};
|
|
} else {
|
|
assert(false);
|
|
}
|
|
}
|
|
};
|
|
'''
|
|
|
|
[cases]
|
|
[cases.int]
|
|
param_types = ["const MyUnion&"]
|
|
setup = "return 123;"
|
|
expect_json = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"}]'
|
|
expect_json_v2 = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "size":56, "members":[]}]'
|
|
[cases.vector]
|
|
param_types = ["const MyUnion&"]
|
|
setup = "return std::vector{1,2,3};"
|
|
expect_json = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"}]'
|
|
expect_json_v2 = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "size":56, "members":[]}]'
|
|
[cases.unordered_map]
|
|
param_types = ["const MyUnion&"]
|
|
setup = 'return std::unordered_map<std::string, std::string>{{"a", "b"}, {"c","d"}};'
|
|
expect_json = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"}]'
|
|
expect_json_v2 = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "size":56, "members":[]}]'
|
|
|
|
[cases.alignment]
|
|
# Wrap the union in a pair as a way of inferring its alignment
|
|
param_types = ["const std::pair<char, MyUnion>&"]
|
|
setup = 'return {{0, MyUnion{123}}};'
|
|
expect_json = '''[
|
|
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "members":[
|
|
{"staticSize":1, "dynamicSize":0, "exclusiveSize":1},
|
|
{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"}
|
|
]}]'''
|
|
expect_json_v2 = '''[
|
|
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "size":64, "members":[
|
|
{"staticSize":1, "dynamicSize":0, "exclusiveSize":1, "size":1},
|
|
{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "size":56, "members":[]}
|
|
]}]'''
|
|
|
|
[cases.tagged_int]
|
|
param_types = ["const TaggedUnion&"]
|
|
setup = "return TaggedUnion{MyUnion{123}, 0};"
|
|
expect_json = '''[
|
|
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "members":[
|
|
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"},
|
|
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "NOT":"members"}
|
|
]}]'''
|
|
expect_json_v2 = '''[
|
|
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "size":64, "members":[
|
|
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "size":56, "members":[]},
|
|
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "size":1, "members":[]}
|
|
]}]'''
|
|
[cases.tagged_vector]
|
|
param_types = ["const TaggedUnion&"]
|
|
setup = "return TaggedUnion{MyUnion{std::vector{1,2,3}}, 1};"
|
|
expect_json = '''[
|
|
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "members":[
|
|
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"},
|
|
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "NOT":"members"}
|
|
]}]'''
|
|
expect_json_v2 = '''[
|
|
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "size":64, "members":[
|
|
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "size":56, "members":[]},
|
|
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "size":1, "members":[]}
|
|
]}]'''
|
|
[cases.tagged_unordered_map]
|
|
param_types = ["const TaggedUnion&"]
|
|
setup = 'return TaggedUnion{MyUnion{std::unordered_map<std::string, std::string>{{"a", "b"}, {"c","d"}}}, 2};'
|
|
expect_json = '''[
|
|
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "members":[
|
|
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"},
|
|
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "NOT":"members"}
|
|
]}]'''
|
|
expect_json_v2 = '''[
|
|
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "size":64, "members":[
|
|
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "size":56, "members":[]},
|
|
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "size":1, "members":[]}
|
|
]}]'''
|