diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2020-04-16 21:42:45 +0200 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2020-04-16 21:42:45 +0200 | 
| commit | 6cf5244bc514042fe419fffe1cd26a7f5e3c778f (patch) | |
| tree | 4a72abf80980c3d10656bd82606a69329867d057 /src | |
| parent | a76a9ad65fa549d2c1650bb5a7d9a657186edc43 (diff) | |
Remove optional from load result
Makes loading of data well-defined for arbitrary object contents.
Introduce zero reference and object to represent missing or mismatched
parts.
Diffstat (limited to 'src')
| -rw-r--r-- | src/channel.cpp | 102 | ||||
| -rw-r--r-- | src/channel.h | 6 | ||||
| -rw-r--r-- | src/identity.cpp | 45 | ||||
| -rw-r--r-- | src/identity.h | 2 | ||||
| -rw-r--r-- | src/message.cpp | 39 | ||||
| -rw-r--r-- | src/message.h | 8 | ||||
| -rw-r--r-- | src/network.cpp | 14 | ||||
| -rw-r--r-- | src/pubkey.cpp | 57 | ||||
| -rw-r--r-- | src/pubkey.h | 37 | ||||
| -rw-r--r-- | src/storage.cpp | 34 | 
10 files changed, 172 insertions, 172 deletions
| diff --git a/src/channel.cpp b/src/channel.cpp index 50c5f97..b13a71e 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -22,28 +22,25 @@ Ref ChannelRequestData::store(const Storage & st) const  	return st.storeObject(Record(std::move(items)));  } -optional<ChannelRequestData> ChannelRequestData::load(const Ref & ref) +ChannelRequestData ChannelRequestData::load(const Ref & ref)  { -	auto rec = ref->asRecord(); -	if (!rec) -		return nullopt; - -	remove_const<decltype(peers)>::type peers; -	for (const auto & i : rec->items("peer")) -		if (auto p = i.as<Signed<IdentityData>>()) -			peers.push_back(*p); - -	auto enc = rec->item("enc").asText(); -	if (!enc || enc != "aes-128-gcm") -		return nullopt; - -	auto key = rec->item("key").as<PublicKexKey>(); -	if (!key) -		return nullopt; +	if (auto rec = ref->asRecord()) { +		remove_const<decltype(peers)>::type peers; +		for (const auto & i : rec->items("peer")) +			if (auto p = i.as<Signed<IdentityData>>()) +				peers.push_back(*p); + +		if (rec->item("enc").asText() == "aes-128-gcm") +			if (auto key = rec->item("key").as<PublicKexKey>()) +				return ChannelRequestData { +					.peers = std::move(peers), +					.key = *key, +				}; +	}  	return ChannelRequestData { -		.peers = std::move(peers), -		.key = *key, +		.peers = {}, +		.key = Stored<PublicKexKey>::load(ref.storage().zref()),  	};  } @@ -58,27 +55,18 @@ Ref ChannelAcceptData::store(const Storage & st) const  	return st.storeObject(Record(std::move(items)));  } -optional<ChannelAcceptData> ChannelAcceptData::load(const Ref & ref) +ChannelAcceptData ChannelAcceptData::load(const Ref & ref)  { -	auto rec = ref->asRecord(); -	if (!rec) -		return nullopt; - -	auto request = rec->item("req").as<ChannelRequest>(); -	if (!request) -		return nullopt; - -	auto enc = rec->item("enc").asText(); -	if (!enc || enc != "aes-128-gcm") -		return nullopt; - -	auto key = rec->item("key").as<PublicKexKey>(); -	if (!key) -		return nullopt; +	if (auto rec = ref->asRecord()) +		if (rec->item("enc").asText() == "aes-128-gcm") +			return ChannelAcceptData { +				.request = *rec->item("req").as<ChannelRequest>(), +				.key = *rec->item("key").as<PublicKexKey>(), +			};  	return ChannelAcceptData { -		.request = *request, -		.key = *key, +		.request = Stored<ChannelRequest>::load(ref.storage().zref()), +		.key = Stored<PublicKexKey>::load(ref.storage().zref()),  	};  } @@ -114,26 +102,20 @@ Ref Channel::store(const Storage & st) const  	return st.storeObject(Record(std::move(items)));  } -optional<Channel> Channel::load(const Ref & ref) +Channel Channel::load(const Ref & ref)  { -	auto rec = ref->asRecord(); -	if (!rec) -		return nullopt; - -	remove_const<decltype(peers)>::type peers; -	for (const auto & i : rec->items("peer")) -		if (auto p = i.as<Signed<IdentityData>>()) -			peers.push_back(*p); - -	auto enc = rec->item("enc").asText(); -	if (!enc || enc != "aes-128-gcm") -		return nullopt; - -	auto key = rec->item("key").asBinary(); -	if (!key) -		return nullopt; - -	return Channel(peers, std::move(*key)); +	if (auto rec = ref->asRecord()) { +		remove_const<decltype(peers)>::type peers; +		for (const auto & i : rec->items("peer")) +			if (auto p = i.as<Signed<IdentityData>>()) +				peers.push_back(*p); + +		if (rec->item("enc").asText() == "aes-128-gcm") +			if (auto key = rec->item("key").asBinary()) +				return Channel(peers, std::move(*key)); +	} + +	return Channel({}, {});  }  Stored<ChannelRequest> Channel::generateRequest(const Storage & st, @@ -146,12 +128,12 @@ Stored<ChannelRequest> Channel::generateRequest(const Storage & st,  	return signKey->sign(st.store(ChannelRequestData {  		.peers = self.ref()->digest() < peer.ref()->digest() ?  			vector<Stored<Signed<IdentityData>>> { -				*Stored<Signed<IdentityData>>::load(*self.ref()), -				*Stored<Signed<IdentityData>>::load(*peer.ref()), +				Stored<Signed<IdentityData>>::load(*self.ref()), +				Stored<Signed<IdentityData>>::load(*peer.ref()),  			} :  			vector<Stored<Signed<IdentityData>>> { -				*Stored<Signed<IdentityData>>::load(*peer.ref()), -				*Stored<Signed<IdentityData>>::load(*self.ref()), +				Stored<Signed<IdentityData>>::load(*peer.ref()), +				Stored<Signed<IdentityData>>::load(*self.ref()),  			},  		.key = SecretKexKey::generate(st).pub(),  	})); diff --git a/src/channel.h b/src/channel.h index 100003c..1c7df30 100644 --- a/src/channel.h +++ b/src/channel.h @@ -9,7 +9,7 @@ namespace erebos {  struct ChannelRequestData  {  	Ref store(const Storage & st) const; -	static optional<ChannelRequestData> load(const Ref &); +	static ChannelRequestData load(const Ref &);  	const vector<Stored<Signed<IdentityData>>> peers;  	const Stored<PublicKexKey> key; @@ -20,7 +20,7 @@ typedef Signed<ChannelRequestData> ChannelRequest;  struct ChannelAcceptData  {  	Ref store(const Storage & st) const; -	static optional<ChannelAcceptData> load(const Ref &); +	static ChannelAcceptData load(const Ref &);  	Stored<class Channel> channel() const; @@ -40,7 +40,7 @@ public:  	{}  	Ref store(const Storage & st) const; -	static optional<Channel> load(const Ref &); +	static Channel load(const Ref &);  	static Stored<ChannelRequest> generateRequest(const Storage &,  			const Identity & self, const Identity & peer); diff --git a/src/identity.cpp b/src/identity.cpp index 3cba97c..2396b9f 100644 --- a/src/identity.cpp +++ b/src/identity.cpp @@ -24,12 +24,8 @@ optional<Identity> Identity::load(const vector<Ref> & refs)  	vector<Stored<Signed<IdentityData>>> data;  	data.reserve(refs.size()); -	for (const auto & ref : refs) { -		auto d = Stored<Signed<IdentityData>>::load(ref); -		if (!d) -			return nullopt; -		data.push_back(*d); -	} +	for (const auto & ref : refs) +		data.push_back(Stored<Signed<IdentityData>>::load(ref));  	if (auto ptr = Priv::validate(data))  		return Identity(ptr); @@ -124,27 +120,30 @@ void Identity::Builder::owner(const Identity & val)  	p->owner.emplace(val);  } -optional<IdentityData> IdentityData::load(const Ref & ref) +IdentityData IdentityData::load(const Ref & ref)  { -	auto rec = ref->asRecord(); -	if (!rec) -		return nullopt; - -	vector<Stored<Signed<IdentityData>>> prev; -	for (auto p : rec->items("SPREV")) -		if (const auto & x = p.as<Signed<IdentityData>>()) -			prev.push_back(x.value()); +	if (auto rec = ref->asRecord()) { +		vector<Stored<Signed<IdentityData>>> prev; +		for (auto p : rec->items("SPREV")) +			if (const auto & x = p.as<Signed<IdentityData>>()) +				prev.push_back(x.value()); -	auto keyIdentity = rec->item("key-id").as<PublicKey>(); -	if (!keyIdentity) -		return nullopt; +		if (auto keyIdentity = rec->item("key-id").as<PublicKey>()) +			return IdentityData { +				.prev = std::move(prev), +				.name = rec->item("name").asText(), +				.owner = rec->item("owner").as<Signed<IdentityData>>(), +				.keyIdentity = keyIdentity.value(), +				.keyMessage = rec->item("key-msg").as<PublicKey>(), +			}; +	}  	return IdentityData { -		.prev = std::move(prev), -		.name = rec->item("name").asText(), -		.owner = rec->item("owner").as<Signed<IdentityData>>(), -		.keyIdentity = keyIdentity.value(), -		.keyMessage = rec->item("key-msg").as<PublicKey>(), +		.prev = {}, +		.name = nullopt, +		.owner = nullopt, +		.keyIdentity = Stored<PublicKey>::load(ref.storage().zref()), +		.keyMessage = nullopt,  	};  } diff --git a/src/identity.h b/src/identity.h index 92ac34f..1dfc193 100644 --- a/src/identity.h +++ b/src/identity.h @@ -13,7 +13,7 @@ namespace erebos {  class IdentityData  {  public: -	static optional<IdentityData> load(const Ref &); +	static IdentityData load(const Ref &);  	Ref store(const Storage & st) const;  	const vector<Stored<Signed<IdentityData>>> prev; diff --git a/src/message.cpp b/src/message.cpp index b7d4bda..354703e 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -48,11 +48,11 @@ DirectMessage::DirectMessage(Priv * p):  	p(p)  {} -optional<DirectMessageData> DirectMessageData::load(const Ref & ref) +DirectMessageData DirectMessageData::load(const Ref & ref)  {  	auto rec = ref->asRecord();  	if (!rec) -		return nullopt; +		return DirectMessageData();  	vector<Stored<DirectMessageData>> prev;  	for (auto p : rec->items("PREV")) @@ -60,16 +60,10 @@ optional<DirectMessageData> DirectMessageData::load(const Ref & ref)  			prev.push_back(*x);  	auto fref = rec->item("from").asRef(); -	if (!fref) -		return nullopt; - -	auto from = Identity::load(*fref); -	if (!from) -		return nullopt;  	return DirectMessageData {  		.prev = std::move(prev), -		.from = *from, +		.from = fref ? Identity::load(*fref) : nullopt,  		.time = *rec->item("time").asDate(),  		.text = rec->item("text").asText().value(),  	}; @@ -81,27 +75,32 @@ Ref DirectMessageData::store(const Storage & st) const  	for (const auto prev : prev)  		items.emplace_back("PREV", prev.ref()); -	items.emplace_back("from", from.ref().value()); -	items.emplace_back("time", time); -	items.emplace_back("text", text); +	if (from) +		items.emplace_back("from", from->ref().value()); +	if (time) +		items.emplace_back("time", *time); +	if (text) +		items.emplace_back("text", *text);  	return st.storeObject(Record(std::move(items)));  } -const Identity & DirectMessage::from() const +const optional<Identity> & DirectMessage::from() const  {  	return p->data->from;  } -const ZonedTime & DirectMessage::time() const +const optional<ZonedTime> & DirectMessage::time() const  {  	return p->data->time;  } -const string & DirectMessage::text() const +string DirectMessage::text() const  { -	return p->data->text; +	if (p->data->text) +		return p->data->text.value(); +	return "";  } @@ -138,7 +137,7 @@ DirectMessageThread::Iterator & DirectMessageThread::Iterator::operator++()  		auto ncur = p->next[0];  		for (const auto & m : p->next) -			if (m->time.time >= ncur->time.time) +			if (!ncur->time || (m->time && m->time->time >= ncur->time->time))  				ncur = m;  		p->current.emplace(DirectMessage(new DirectMessage::Priv { @@ -216,10 +215,6 @@ UUID DirectMessageService::uuid() const  void DirectMessageService::handle(Context & ctx) const  { -	auto dm = Stored<DirectMessageData>::load(ctx.ref()); -	if (!dm) -		return; -  	auto pid = ctx.peer().identity();  	if (!pid)  		return; @@ -228,7 +223,7 @@ void DirectMessageService::handle(Context & ctx) const  	unique_lock lock(threadLock);  	vector<Stored<DirectMessageData>> head(DirectMessageThread::Priv::getThreadLocked(powner).p->head); -	head.push_back(*dm); +	head.push_back(Stored<DirectMessageData>::load(ctx.ref()));  	filterAncestors(head);  	auto dmt = DirectMessageThread::Priv::updateThreadLocked(powner, std::move(head)); diff --git a/src/message.h b/src/message.h index 7e0f597..c4a3549 100644 --- a/src/message.h +++ b/src/message.h @@ -19,13 +19,13 @@ namespace erebos {  struct DirectMessageData  { -	static optional<DirectMessageData> load(const Ref &); +	static DirectMessageData load(const Ref &);  	Ref store(const Storage &) const;  	vector<Stored<DirectMessageData>> prev; -	Identity from; -	ZonedTime time; -	string text; +	optional<Identity> from; +	optional<ZonedTime> time; +	optional<string> text;  };  struct DirectMessage::Priv diff --git a/src/network.cpp b/src/network.cpp index b31d949..91f1923 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -298,7 +298,7 @@ Server::Peer & Server::Priv::getPeer(const sockaddr_in & paddr)  void Server::Priv::handlePacket(Server::Peer & peer, const TransportHeader & header, ReplyBuilder & reply)  {  	unordered_set<Digest> plaintextRefs; -	for (const auto & obj : collectStoredObjects(*Stored<Object>::load(*self.ref()))) +	for (const auto & obj : collectStoredObjects(Stored<Object>::load(*self.ref())))  		plaintextRefs.insert(obj.ref().digest());  	optional<UUID> serviceType; @@ -397,9 +397,11 @@ void Server::Priv::handlePacket(Server::Peer & peer, const TransportHeader & hea  				auto cres = peer.tempStorage.copy(pref);  				if (auto r = std::get_if<Ref>(&cres)) { -					if (auto acc = ChannelAccept::load(*r)) { +					auto acc = ChannelAccept::load(*r); +					if (holds_alternative<Identity>(peer.identity) && +							acc.isSignedBy(std::get<Identity>(peer.identity).keyMessage())) {  						reply.header({ TransportHeader::Type::Acknowledged, pref }); -						peer.channel.emplace<Stored<Channel>>(acc->data->channel()); +						peer.channel.emplace<Stored<Channel>>(acc.data->channel());  					}  				}  			} @@ -485,8 +487,10 @@ void Server::Peer::updateChannel(ReplyBuilder & reply)  	if (holds_alternative<shared_ptr<WaitingRef>>(channel)) {  		if (auto ref = std::get<shared_ptr<WaitingRef>>(channel)->check(reply)) { -			if (auto req = Stored<ChannelRequest>::load(*ref)) { -				if (auto acc = Channel::acceptRequest(server.self, std::get<Identity>(identity), *req)) { +			auto req = Stored<ChannelRequest>::load(*ref); +			if (holds_alternative<Identity>(identity) && +					req->isSignedBy(std::get<Identity>(identity).keyMessage())) { +				if (auto acc = Channel::acceptRequest(server.self, std::get<Identity>(identity), req)) {  					channel.emplace<Stored<ChannelAccept>>(*acc);  					reply.header({ TransportHeader::Type::ChannelAccept, acc->ref() });  					reply.body(acc->ref()); diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 0e83136..6d85d33 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -8,11 +8,11 @@ using std::string;  using namespace erebos; -optional<PublicKey> PublicKey::load(const Ref & ref) +PublicKey PublicKey::load(const Ref & ref)  {  	auto rec = ref->asRecord();  	if (!rec) -		return nullopt; +		return PublicKey(nullptr);  	if (auto ktype = rec->item("type").asText())  		if (ktype.value() != "ed25519") @@ -22,7 +22,7 @@ optional<PublicKey> PublicKey::load(const Ref & ref)  		return PublicKey(EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, nullptr,  					pubkey.value().data(), pubkey.value().size())); -	return nullopt; +	return PublicKey(nullptr);  }  Ref PublicKey::store(const Storage & st) const @@ -31,12 +31,14 @@ Ref PublicKey::store(const Storage & st) const  	items.emplace_back("type", "ed25519"); -	vector<uint8_t> keyData; -	size_t keyLen; -	EVP_PKEY_get_raw_public_key(key.get(), nullptr, &keyLen); -	keyData.resize(keyLen); -	EVP_PKEY_get_raw_public_key(key.get(), keyData.data(), &keyLen); -	items.emplace_back("pubkey", keyData); +	if (key) { +		vector<uint8_t> keyData; +		size_t keyLen; +		EVP_PKEY_get_raw_public_key(key.get(), nullptr, &keyLen); +		keyData.resize(keyLen); +		EVP_PKEY_get_raw_public_key(key.get(), keyData.data(), &keyLen); +		items.emplace_back("pubkey", keyData); +	}  	return st.storeObject(Record(std::move(items)));  } @@ -110,19 +112,14 @@ vector<uint8_t> SecretKey::sign(const Digest & dgst) const  	return sigData;  } -optional<Signature> Signature::load(const Ref & ref) +Signature Signature::load(const Ref & ref)  { -	auto rec = ref->asRecord(); -	if (!rec) -		return nullopt; +	if (auto rec = ref->asRecord()) +		if (auto key = rec->item("key").as<PublicKey>()) +			if (auto sig = rec->item("sig").asBinary()) +				return Signature(*key, *sig); -	auto key = rec->item("key").as<PublicKey>(); -	auto sig = rec->item("sig").asBinary(); - -	if (!key || !sig) -		return nullopt; - -	return Signature(*key, *sig); +	return Signature(Stored<PublicKey>::load(ref.storage().zref()), {});  }  Ref Signature::store(const Storage & st) const @@ -151,11 +148,11 @@ bool Signature::verify(const Ref & ref) const  } -optional<PublicKexKey> PublicKexKey::load(const Ref & ref) +PublicKexKey PublicKexKey::load(const Ref & ref)  {  	auto rec = ref->asRecord();  	if (!rec) -		return nullopt; +		return PublicKexKey(nullptr);  	if (auto ktype = rec->item("type").asText())  		if (ktype.value() != "x25519") @@ -165,7 +162,7 @@ optional<PublicKexKey> PublicKexKey::load(const Ref & ref)  		return PublicKexKey(EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, nullptr,  					pubkey.value().data(), pubkey.value().size())); -	return nullopt; +	return PublicKexKey(nullptr);  }  Ref PublicKexKey::store(const Storage & st) const @@ -174,12 +171,14 @@ Ref PublicKexKey::store(const Storage & st) const  	items.emplace_back("type", "x25519"); -	vector<uint8_t> keyData; -	size_t keyLen; -	EVP_PKEY_get_raw_public_key(key.get(), nullptr, &keyLen); -	keyData.resize(keyLen); -	EVP_PKEY_get_raw_public_key(key.get(), keyData.data(), &keyLen); -	items.emplace_back("pubkey", keyData); +	if (key) { +		vector<uint8_t> keyData; +		size_t keyLen; +		EVP_PKEY_get_raw_public_key(key.get(), nullptr, &keyLen); +		keyData.resize(keyLen); +		EVP_PKEY_get_raw_public_key(key.get(), keyData.data(), &keyLen); +		items.emplace_back("pubkey", keyData); +	}  	return st.storeObject(Record(std::move(items)));  } diff --git a/src/pubkey.h b/src/pubkey.h index c922dc7..7b80752 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -18,7 +18,7 @@ class PublicKey  		key(key, EVP_PKEY_free) {}  	friend class SecretKey;  public: -	static optional<PublicKey> load(const Ref &); +	static PublicKey load(const Ref &);  	Ref store(const Storage &) const;  	const shared_ptr<EVP_PKEY> key; @@ -49,7 +49,7 @@ private:  class Signature  {  public: -	static optional<Signature> load(const Ref &); +	static Signature load(const Ref &);  	Ref store(const Storage &) const;  	bool verify(const Ref &) const; @@ -67,7 +67,7 @@ template<typename T>  class Signed  {  public: -	static optional<Signed<T>> load(const Ref &); +	static Signed<T> load(const Ref &);  	Ref store(const Storage &) const;  	bool isSignedBy(const Stored<PublicKey> &) const; @@ -90,23 +90,20 @@ Stored<Signed<T>> SecretKey::sign(const Stored<T> & val) const  }  template<typename T> -optional<Signed<T>> Signed<T>::load(const Ref & ref) +Signed<T> Signed<T>::load(const Ref & ref)  { -	auto rec = ref->asRecord(); -	if (!rec) -		return nullopt; - -	auto data = rec->item("SDATA").as<T>(); -	if (!data) -		return nullopt; - -	vector<Stored<Signature>> sigs; -	for (auto item : rec->items("sig")) -		if (auto sig = item.as<Signature>()) -			if (sig.value()->verify(data.value().ref())) -				sigs.push_back(sig.value()); - -	return Signed(*data, sigs); +	if (auto rec = ref->asRecord()) +		if (auto data = rec->item("SDATA").as<T>()) { +			vector<Stored<Signature>> sigs; +			for (auto item : rec->items("sig")) +				if (auto sig = item.as<Signature>()) +					if (sig.value()->verify(data.value().ref())) +						sigs.push_back(sig.value()); + +			return Signed(*data, sigs); +		} + +	return Signed(Stored<T>::load(ref.storage().zref()), {});  }  template<typename T> @@ -137,7 +134,7 @@ class PublicKexKey  		key(key, EVP_PKEY_free) {}  	friend class SecretKexKey;  public: -	static optional<PublicKexKey> load(const Ref &); +	static PublicKexKey load(const Ref &);  	Ref store(const Storage &) const;  	const shared_ptr<EVP_PKEY> key; diff --git a/src/storage.cpp b/src/storage.cpp index 81a70e1..6a0669c 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -315,6 +315,11 @@ optional<Ref> Storage::ref(const Digest & digest) const  	return Ref::create(*this, digest);  } +Ref Storage::zref() const +{ +	return Ref::zcreate(*this); +} +  Digest PartialStorage::Priv::storeBytes(const vector<uint8_t> & content) const  {  	array<uint8_t, Digest::size> arr; @@ -346,6 +351,8 @@ optional<vector<uint8_t>> PartialStorage::Priv::loadBytes(const Digest & digest)  optional<PartialObject> PartialStorage::loadObject(const Digest & digest) const  { +	if (digest.isZero()) +		return PartialObject(monostate());  	if (auto content = p->loadBytes(digest))  		return PartialObject::decode(*this, *content);  	return nullopt; @@ -362,6 +369,8 @@ PartialRef PartialStorage::storeObject(const Blob & val) const  optional<Object> Storage::loadObject(const Digest & digest) const  { +	if (digest.isZero()) +		return Object(monostate());  	if (auto content = p->loadBytes(digest))  		return Object::decode(*this, *content);  	return nullopt; @@ -466,6 +475,13 @@ Digest::operator string() const  	return res;  } +bool Digest::isZero() const +{ +	for (uint8_t x : value) +		if (x) return false; +	return true; +} +  PartialRef PartialRef::create(PartialStorage st, const Digest & digest)  { @@ -517,6 +533,16 @@ optional<Ref> Ref::create(Storage st, const Digest & digest)  	return Ref(shared_ptr<Priv>(p));  } +Ref Ref::zcreate(Storage st) +{ +	auto p = new Priv { +		.storage = make_unique<PartialStorage>(st), +		.digest = Digest(array<uint8_t, Digest::size> {}), +	}; + +	return Ref(shared_ptr<Priv>(p)); +} +  const Object Ref::operator*() const  {  	if (auto res = static_cast<Storage*>(p->storage.get())->loadObject(p->digest)) @@ -854,11 +880,9 @@ vector<uint8_t> ObjectT<S>::encode() const  }  template<class S> -optional<ObjectT<S>> ObjectT<S>::load(const typename S::Ref & ref) +ObjectT<S> ObjectT<S>::load(const typename S::Ref & ref)  { -	if (ref) -		return *ref; -	return nullopt; +	return *ref;  }  template<class S> @@ -899,7 +923,7 @@ vector<Stored<Object>> erebos::collectStoredObjects(const Stored<Object> & from)  		if (auto rec = cur->asRecord())  			for (const auto & item : rec->items())  				if (auto ref = item.asRef()) -					queue.push_back(*Stored<Object>::load(*ref)); +					queue.push_back(Stored<Object>::load(*ref));  	}  	return res; |