add MetaEnv implementation

This commit is contained in:
falsycat 2023-09-09 09:21:17 +09:00
parent d7c4364255
commit efe922f835
3 changed files with 167 additions and 0 deletions

View File

@ -32,6 +32,7 @@ target_sources(nf7_core
clock.hh
dealer.hh
logger.hh
meta_env.hh
version.hh
)
@ -50,6 +51,7 @@ target_sources(nf7_core_test
uv/file_test.cc
uv/parallelism_test.cc
clock_test.cc
meta_env_test.cc
)
target_link_libraries(nf7_core_test
PRIVATE

91
core/meta_env.hh Normal file
View File

@ -0,0 +1,91 @@
// No copyright
#pragma once
#include <algorithm>
#include <cassert>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "iface/subsys/meta_env.hh"
namespace nf7::core {
class NullMetaEnv : public subsys::MetaEnv {
public:
static inline const auto kInstance = std::make_shared<NullMetaEnv>();
public:
NullMetaEnv() noexcept : subsys::MetaEnv("nf7::core::NullMetaEnv") { }
public:
Env* FindOr(std::string_view) const noexcept override { return nullptr; }
std::optional<Pair> FindOr(uint64_t) const noexcept override { return std::nullopt; }
std::vector<Pair> FetchAll() const override { return {}; }
std::shared_ptr<subsys::MetaEnv> parent() const noexcept override { return nullptr; }
};
class MetaEnv : public subsys::MetaEnv {
public:
using SharedPair = std::pair<std::string, std::shared_ptr<Env>>;
private:
static std::vector<SharedPair>&& Sort(std::vector<SharedPair>&& v) noexcept {
std::sort(v.begin(), v.end(),
[](const auto& a, const auto& b) { return a.first < b.first; });
return v;
}
public:
explicit MetaEnv(std::vector<SharedPair>&& children,
const std::weak_ptr<subsys::MetaEnv>& parent = {}) noexcept
: subsys::MetaEnv("nf7::core::MetaEnv"),
children_(Sort(std::move(children))),
parent_(parent) {
assert(std::all_of(children_.begin(), children_.end(),
[](auto& x) { return x.second; }));
}
public:
Env* FindOr(std::string_view name) const noexcept override {
const auto itr = std::lower_bound(
children_.cbegin(), children_.cend(), name,
[](const auto& a, const auto& b) { return a.first < b; });
if (children_.cend() == itr || itr->first != name) {
return nullptr;
}
return itr->second.get();
}
std::optional<Pair> FindOr(uint64_t index) const noexcept override {
if (index >= children_.size()) {
return std::nullopt;
}
const auto& child = children_[index];
return Pair {child.first, *child.second};
}
std::vector<Pair> FetchAll() const override
try {
std::vector<Pair> ret;
ret.reserve(children_.size());
for (const auto& child : children_) {
ret.emplace_back(child.first, *child.second);
}
return ret;
} catch (const std::bad_alloc&) {
throw MemoryException {};
}
public:
std::shared_ptr<subsys::MetaEnv> parent() const noexcept override {
return parent_.lock();
}
private:
const std::vector<SharedPair> children_;
const std::weak_ptr<subsys::MetaEnv> parent_;
};
} // namespace nf7::core

74
core/meta_env_test.cc Normal file
View File

@ -0,0 +1,74 @@
// No copyright
#include "core/meta_env.hh"
#include <gtest/gtest.h>
#include "iface/env.hh"
static inline std::shared_ptr<nf7::Env> MakeEmptyEnv() {
return std::make_shared<nf7::SimpleEnv>(nf7::SimpleEnv::FactoryMap {});
}
static inline bool MatchPair(const std::optional<nf7::subsys::MetaEnv::Pair>& a,
const nf7::subsys::MetaEnv::Pair& b) {
return a && a->first == b.first && &a->second == &b.second;
}
TEST(MetaEnv, FindOrByName) {
const auto a = MakeEmptyEnv();
const auto b = MakeEmptyEnv();
const auto c = MakeEmptyEnv();
nf7::core::MetaEnv sut {
{
{"b", b},
{"c", c},
{"a", a},
},
};
EXPECT_EQ(sut.FindOr(""), nullptr);
EXPECT_EQ(sut.FindOr("a"), a.get());
EXPECT_EQ(sut.FindOr("b"), b.get());
EXPECT_EQ(sut.FindOr("c"), c.get());
EXPECT_EQ(sut.FindOr("d"), nullptr);
}
TEST(MetaEnv, FindOrByIndex) {
const auto a = MakeEmptyEnv();
const auto b = MakeEmptyEnv();
const auto c = MakeEmptyEnv();
nf7::core::MetaEnv sut {
{
{"b", b},
{"c", c},
{"a", a},
},
};
EXPECT_TRUE(MatchPair(sut.FindOr(0), {"a", *a}));
EXPECT_TRUE(MatchPair(sut.FindOr(1), {"b", *b}));
EXPECT_TRUE(MatchPair(sut.FindOr(2), {"c", *c}));
EXPECT_EQ(sut.FindOr(3), std::nullopt);
}
TEST(MetaEnv, FetchAll) {
const auto a = MakeEmptyEnv();
const auto b = MakeEmptyEnv();
const auto c = MakeEmptyEnv();
nf7::core::MetaEnv sut {
{
{"b", b},
{"c", c},
{"a", a},
},
};
const auto all = sut.FetchAll();
EXPECT_EQ(all.size(), 3);
EXPECT_TRUE(MatchPair(all[0], {"a", *a}));
EXPECT_TRUE(MatchPair(all[1], {"b", *b}));
EXPECT_TRUE(MatchPair(all[2], {"c", *c}));
}