Skip to content

Commit 6ab55af

Browse files
committed
XXX Dirty but the idea is there
1 parent b86a974 commit 6ab55af

File tree

9 files changed

+347
-133
lines changed

9 files changed

+347
-133
lines changed

immer/extra/archive/box/archive.hpp

+36-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#include <cereal/cereal.hpp>
1212

13+
#include <boost/hana/functional/id.hpp>
14+
1315
namespace immer::archive::box {
1416

1517
template <typename T, typename MemoryPolicy>
@@ -115,25 +117,48 @@ save_to_archive(immer::box<T, MemoryPolicy> box,
115117
return {std::move(archive), id};
116118
}
117119

118-
template <typename T, typename MemoryPolicy>
120+
template <typename T,
121+
typename MemoryPolicy,
122+
typename Archive = archive_load<T, MemoryPolicy>,
123+
typename TransformF = boost::hana::id_t>
119124
class loader
120125
{
121126
public:
122-
explicit loader(archive_load<T, MemoryPolicy> ar)
127+
explicit loader(Archive ar)
128+
requires std::is_same_v<TransformF, boost::hana::id_t>
129+
: ar_{std::move(ar)}
130+
{
131+
}
132+
133+
explicit loader(Archive ar, TransformF transform)
123134
: ar_{std::move(ar)}
135+
, transform_{std::move(transform)}
124136
{
125137
}
126138

127-
immer::box<T, MemoryPolicy> load(container_id id) const
139+
immer::box<T, MemoryPolicy> load(container_id id)
128140
{
129141
if (id.value >= ar_.boxes.size()) {
130142
throw invalid_container_id{id};
131143
}
132-
return ar_.boxes[id.value];
144+
if constexpr (std::is_same_v<TransformF, boost::hana::id_t>) {
145+
return ar_.boxes[id.value];
146+
} else {
147+
if (auto* b = boxes.find(id)) {
148+
return *b;
149+
}
150+
const auto& old_box = ar_.boxes[id.value];
151+
auto new_box =
152+
immer::box<T, MemoryPolicy>{transform_(old_box.get())};
153+
boxes = std::move(boxes).set(id, new_box);
154+
return new_box;
155+
}
133156
}
134157

135158
private:
136-
const archive_load<T, MemoryPolicy> ar_;
159+
const Archive ar_;
160+
const TransformF transform_;
161+
immer::map<container_id, immer::box<T, MemoryPolicy>> boxes;
137162
};
138163

139164
template <typename T, typename MemoryPolicy>
@@ -166,8 +191,12 @@ struct container_traits<immer::box<T, MemoryPolicy>>
166191
{
167192
using save_archive_t = box::archive_save<T, MemoryPolicy>;
168193
using load_archive_t = box::archive_load<T, MemoryPolicy>;
169-
using loader_t = box::loader<T, MemoryPolicy>;
170-
using container_id = immer::archive::container_id;
194+
195+
template <typename Archive = load_archive_t,
196+
typename TransformF = boost::hana::id_t>
197+
using loader_t = box::loader<T, MemoryPolicy, Archive, TransformF>;
198+
199+
using container_id = immer::archive::container_id;
171200

172201
template <class F>
173202
static auto transform(F&& func)
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include <cereal/cereal.hpp>
4+
#include <immer/box.hpp>
5+
6+
namespace cereal {
7+
8+
template <typename Archive, typename T, typename MemoryPolicy>
9+
void CEREAL_LOAD_FUNCTION_NAME(Archive& ar, immer::box<T, MemoryPolicy>& m)
10+
{
11+
T x;
12+
ar(x);
13+
m = x;
14+
}
15+
16+
template <typename Archive, typename T, typename MemoryPolicy>
17+
void CEREAL_SAVE_FUNCTION_NAME(Archive& ar,
18+
const immer::box<T, MemoryPolicy>& m)
19+
{
20+
ar(m.get());
21+
}
22+
23+
} // namespace cereal

immer/extra/archive/champ/champ.hpp

+18-4
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ class hash_validation_failed_exception : public archive_exception
4444
}
4545
};
4646

47-
template <class Container>
47+
template <class Container,
48+
typename Archive = container_archive_load<Container>,
49+
typename TransformF = boost::hana::id_t>
4850
class container_loader
4951
{
5052
using champ_t = std::decay_t<decltype(std::declval<Container>().impl())>;
@@ -61,12 +63,19 @@ class container_loader
6163
};
6264

6365
public:
64-
explicit container_loader(container_archive_load<Container> archive)
66+
explicit container_loader(Archive archive)
67+
requires std::is_same_v<TransformF, boost::hana::id_t>
6568
: archive_{std::move(archive)}
6669
, nodes_{archive_.nodes}
6770
{
6871
}
6972

73+
explicit container_loader(Archive archive, TransformF transform)
74+
: archive_{std::move(archive)}
75+
, nodes_{archive_.nodes, std::move(transform)}
76+
{
77+
}
78+
7079
Container load(node_id root_id)
7180
{
7281
if (root_id.value >= archive_.nodes.size()) {
@@ -106,15 +115,20 @@ class container_loader
106115
}
107116

108117
private:
109-
const container_archive_load<Container> archive_;
118+
const Archive archive_;
110119
nodes_loader<typename node_t::value_t,
111120
typename traits::Hash,
112121
typename traits::Equal,
113122
typename traits::MemoryPolicy,
114-
traits::bits>
123+
traits::bits,
124+
TransformF>
115125
nodes_;
116126
};
117127

128+
template <class Container>
129+
container_loader(container_archive_load<Container> archive)
130+
-> container_loader<Container>;
131+
118132
template <class Container>
119133
std::pair<container_archive_save<Container>, node_id>
120134
save_to_archive(Container container, container_archive_save<Container> archive)

immer/extra/archive/champ/load.hpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
#include <immer/flex_vector.hpp>
88

9+
#include <boost/hana/functional/id.hpp>
910
#include <boost/range/adaptor/indexed.hpp>
11+
1012
#include <spdlog/spdlog.h>
1113

1214
namespace immer::archive {
@@ -54,7 +56,8 @@ template <class T,
5456
typename Hash = std::hash<T>,
5557
typename Equal = std::equal_to<T>,
5658
typename MemoryPolicy = immer::default_memory_policy,
57-
immer::detail::hamts::bits_t B = immer::default_bits>
59+
immer::detail::hamts::bits_t B = immer::default_bits,
60+
typename TransformF = boost::hana::id_t>
5861
class nodes_loader
5962
{
6063
public:
@@ -66,7 +69,14 @@ class nodes_loader
6669
using values_t = immer::flex_vector<immer::array<T>>;
6770

6871
explicit nodes_loader(nodes_load<T, B> archive)
72+
requires std::is_same_v<TransformF, boost::hana::id_t>
73+
: archive_{std::move(archive)}
74+
{
75+
}
76+
77+
explicit nodes_loader(nodes_load<T, B> archive, TransformF transform)
6978
: archive_{std::move(archive)}
79+
, transform_{std::move(transform)}
7080
{
7181
}
7282

@@ -219,6 +229,7 @@ class nodes_loader
219229

220230
private:
221231
const nodes_load<T, B> archive_;
232+
const TransformF transform_;
222233
immer::map<node_id, std::pair<node_ptr, values_t>> collisions_;
223234
immer::map<node_id, std::pair<node_ptr, values_t>> inners_;
224235
};

immer/extra/archive/champ/traits.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <immer/extra/archive/champ/champ.hpp>
55
#include <immer/extra/archive/traits.hpp>
66

7+
#include <boost/hana/functional/id.hpp>
8+
79
namespace immer::archive {
810

911
template <class Container>
@@ -13,8 +15,12 @@ struct champ_traits
1315
immer::archive::champ::container_archive_save<Container>;
1416
using load_archive_t =
1517
immer::archive::champ::container_archive_load<Container>;
16-
using loader_t = immer::archive::champ::container_loader<Container>;
1718
using container_id = immer::archive::node_id;
19+
20+
template <typename Archive = load_archive_t,
21+
typename TransformF = boost::hana::id_t>
22+
using loader_t =
23+
immer::archive::champ::container_loader<Container, Archive, TransformF>;
1824
};
1925

2026
template <typename K,

0 commit comments

Comments
 (0)