diff --git a/src/yang_access.cpp b/src/yang_access.cpp
new file mode 100644
index 0000000..71aebf1
--- /dev/null
+++ b/src/yang_access.cpp
@@ -0,0 +1,304 @@
+#include <boost/algorithm/string/predicate.hpp>
+#include <experimental/iterator>
+#include <iostream>
+#include <libyang/Tree_Data.hpp>
+#include <libyang/libyang.h>
+#include "UniqueResource.hpp"
+#include "libyang_utils.hpp"
+#include "utils.hpp"
+#include "yang_access.hpp"
+#include "yang_schema.hpp"
+
+namespace {
+template <typename Type> using lyPtrDeleter_type = void (*)(Type*);
+template <typename Type> const lyPtrDeleter_type<Type> lyPtrDeleter;
+template <> const auto lyPtrDeleter<ly_set> = ly_set_free;
+template <> const auto lyPtrDeleter<ly_ctx> = static_cast<lyPtrDeleter_type<ly_ctx>>([] (auto* ptr) {ly_ctx_destroy(ptr, nullptr);});
+template <> const auto lyPtrDeleter<lyd_node> = lyd_free_withsiblings;
+
+template <typename Type>
+auto lyWrap(Type* ptr)
+{
+    return std::unique_ptr<Type, lyPtrDeleter_type<Type>>{ptr, lyPtrDeleter<Type>};
+}
+
+// Convenient for functions that take m_datastore as an argument
+using DatastoreType = std::unique_ptr<lyd_node, lyPtrDeleter_type<lyd_node>>;
+}
+
+YangAccess::YangAccess()
+    : m_ctx(lyWrap(ly_ctx_new(nullptr, LY_CTX_DISABLE_SEARCHDIR_CWD)))
+    , m_datastore(lyWrap<lyd_node>(nullptr))
+    , m_schema(std::make_shared<YangSchema>(libyang::create_new_Context(m_ctx.get())))
+{
+}
+
+YangAccess::~YangAccess()
+{
+}
+
+[[noreturn]] void YangAccess::getErrorsAndThrow() const
+{
+    auto errors = libyang::get_ly_errors(libyang::create_new_Context(m_ctx.get()));
+    std::vector<DatastoreError> errorsRes;
+    for (const auto& error : errors) {
+        using namespace std::string_view_literals;
+        errorsRes.emplace_back(error->errmsg(), error->errpath() != ""sv ? std::optional{error->errpath()} : std::nullopt);
+    }
+
+    throw DatastoreException(errorsRes);
+}
+
+void YangAccess::impl_newPath(const std::string& path, const std::optional<std::string>& value)
+{
+    auto newNode = lyd_new_path(m_datastore.get(), m_ctx.get(), path.c_str(), value ? (void*)value->c_str() : nullptr, LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_UPDATE);
+    if (!newNode) {
+        getErrorsAndThrow();
+    }
+    if (!m_datastore) {
+        m_datastore = lyWrap(newNode);
+    }
+}
+
+namespace {
+void impl_unlink(DatastoreType& datastore, lyd_node* what)
+{
+    // If the node to be unlinked is the one our datastore variable points to, we need to find a new one to point to (one of its siblings)
+    if (datastore.get() == what) {
+        auto oldDatastore = datastore.release();
+        if (oldDatastore->prev != oldDatastore) {
+            datastore = lyWrap(oldDatastore->prev);
+        } else {
+            datastore = lyWrap(oldDatastore->next);
+        }
+    }
+
+    lyd_unlink(what);
+}
+}
+
+void YangAccess::impl_removeNode(const std::string& path)
+{
+    auto set = lyWrap(lyd_find_path(m_datastore.get(), path.c_str()));
+    if (!set || set->number == 0) {
+        // Check if schema node exists - lyd_find_path first checks if the first argument is non-null before checking for path validity
+        if (!ly_ctx_get_node(m_ctx.get(), nullptr, path.c_str(), 0)) {
+            throw DatastoreException{{DatastoreError{"Schema node doesn't exist.", path}}};
+        }
+        // Check if libyang found another error
+        if (ly_err_first(m_ctx.get())) {
+            getErrorsAndThrow();
+        }
+
+        // Otherwise the datastore just doesn't contain the wanted node.
+        throw DatastoreException{{DatastoreError{"Data node doesn't exist.", path}}};
+    }
+
+    auto toRemove = set->set.d[0];
+
+    impl_unlink(m_datastore, toRemove);
+
+    lyd_free(toRemove);
+}
+
+void YangAccess::validate()
+{
+    auto datastore = m_datastore.release();
+    lyd_validate(&datastore, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB, m_ctx.get());
+    m_datastore = lyWrap(datastore);
+}
+
+DatastoreAccess::Tree YangAccess::getItems(const std::string& path)
+{
+    DatastoreAccess::Tree res;
+    if (!m_datastore) {
+        return res;
+    }
+
+    auto set = lyWrap(lyd_find_path(m_datastore.get(), path == "/" ? "/*" : path.c_str()));
+    auto setWrapper = libyang::Set(set.get(), nullptr);
+
+    lyNodesToTree(res, setWrapper.data());
+    return res;
+}
+
+void YangAccess::setLeaf(const std::string& path, leaf_data_ value)
+{
+    auto lyValue = value.type() == typeid(empty_) ? std::nullopt : std::optional(leafDataToString(value));
+    impl_newPath(path, lyValue);
+}
+
+void YangAccess::createItem(const std::string& path)
+{
+    impl_newPath(path);
+}
+
+void YangAccess::deleteItem(const std::string& path)
+{
+    impl_removeNode(path);
+}
+
+namespace {
+struct impl_moveItem {
+    DatastoreType& m_datastore;
+    lyd_node* m_sourceNode;
+
+    void operator()(yang::move::Absolute absolute) const
+    {
+        auto set = lyWrap(lyd_find_instance(m_sourceNode, m_sourceNode->schema));
+        if (set->number == 1) { // m_sourceNode is the sole instance, do nothing
+            return;
+        }
+
+        doUnlink();
+        switch (absolute) {
+        case yang::move::Absolute::Begin:
+            if (set->set.d[0] == m_sourceNode) { // List is already at the beginning, do nothing
+                return;
+            }
+            lyd_insert_before(set->set.d[0], m_sourceNode);
+            return;
+        case yang::move::Absolute::End:
+            if (set->set.d[set->number - 1] == m_sourceNode) { // List is already at the end, do nothing
+                return;
+            }
+            lyd_insert_after(set->set.d[set->number - 1], m_sourceNode);
+            return;
+        }
+    }
+
+    void operator()(const yang::move::Relative& relative) const
+    {
+        auto keySuffix = m_sourceNode->schema->nodetype == LYS_LIST ? instanceToString(relative.m_path)
+                                                                    : leafDataToString(relative.m_path.at("."));
+        lyd_node* destNode;
+        lyd_find_sibling_val(m_sourceNode, m_sourceNode->schema, keySuffix.c_str(), &destNode);
+
+        doUnlink();
+        if (relative.m_position == yang::move::Relative::Position::After) {
+            lyd_insert_after(destNode, m_sourceNode);
+        } else {
+            lyd_insert_before(destNode, m_sourceNode);
+        }
+    }
+
+private:
+    void doUnlink() const
+    {
+        impl_unlink(m_datastore, m_sourceNode);
+    }
+};
+}
+
+void YangAccess::moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move)
+{
+    auto set = lyWrap(lyd_find_path(m_datastore.get(), source.c_str()));
+    if (!set) { // Error, the node probably doesn't exist in the schema
+        getErrorsAndThrow();
+    }
+    if (set->number == 0) {
+        return;
+    }
+    auto sourceNode = set->set.d[0];
+    std::visit(impl_moveItem{m_datastore, sourceNode}, move);
+}
+
+void YangAccess::commitChanges()
+{
+    validate();
+}
+
+void YangAccess::discardChanges()
+{
+}
+
+DatastoreAccess::Tree YangAccess::executeRpc(const std::string& path, const Tree& input)
+{
+    auto root = lyWrap(lyd_new_path(nullptr, m_ctx.get(), path.c_str(), nullptr, LYD_ANYDATA_CONSTSTRING, 0));
+    if (!root) {
+        getErrorsAndThrow();
+    }
+    for (const auto& [k, v] : input) {
+        auto node = lyd_new_path(root.get(), m_ctx.get(), joinPaths(path, k).c_str(), (void*)leafDataToString(v).c_str(), LYD_ANYDATA_CONSTSTRING, 0);
+        if (!node) {
+            getErrorsAndThrow();
+        }
+    }
+    throw std::logic_error("in-memory datastore doesn't support executing RPCs.");
+}
+
+void YangAccess::copyConfig(const Datastore source, const Datastore dest)
+{
+    if (source == Datastore::Startup && dest == Datastore::Running) {
+        m_datastore = nullptr;
+    }
+}
+
+std::shared_ptr<Schema> YangAccess::schema()
+{
+    return m_schema;
+}
+
+std::vector<ListInstance> YangAccess::listInstances(const std::string& path)
+{
+    std::vector<ListInstance> res;
+    if (!m_datastore) {
+        return res;
+    }
+
+    auto instances = lyWrap(lyd_find_path(m_datastore.get(), path.c_str()));
+    auto instancesWrapper = libyang::Set(instances.get(), nullptr);
+    for (const auto& list : instancesWrapper.data()) {
+        ListInstance instance;
+        for (const auto& child : list->child()->tree_for()) {
+            if (child->schema()->nodetype() == LYS_LEAF) {
+                libyang::Schema_Node_Leaf leafSchema(child->schema());
+                if (leafSchema.is_key()) {
+                    libyang::Data_Node_Leaf_List leafData(child);
+                    instance.insert({leafSchema.name(), leafValueFromValue(leafData.value(), leafSchema.type()->base())});
+                }
+            }
+        }
+        res.push_back(instance);
+    }
+    return res;
+}
+
+std::string impl_dumpConfig(const lyd_node* datastore, LYD_FORMAT format)
+{
+    char* output;
+    lyd_print_mem(&output, datastore, format, LYP_WITHSIBLINGS);
+
+    if (output) {
+        std::string res = output;
+        free(output);
+        return res;
+    }
+
+    return "";
+}
+
+std::string YangAccess::dumpXML() const
+{
+    return impl_dumpConfig(m_datastore.get(), LYD_XML);
+}
+
+std::string YangAccess::dumpJSON() const
+{
+    return impl_dumpConfig(m_datastore.get(), LYD_JSON);
+}
+
+void YangAccess::addSchemaFile(const std::string& path)
+{
+    m_schema->addSchemaFile(path.c_str());
+}
+
+void YangAccess::addSchemaDir(const std::string& path)
+{
+    m_schema->addSchemaDirectory(path.c_str());
+}
+
+void YangAccess::enableFeature(const std::string& module, const std::string& feature)
+{
+    m_schema->enableFeature(module, feature);
+}
