feat(editor): complete P0 and P1 authoring services
This commit is contained in:
1 parent
b5d854ba95
commit
328e37e8ec
57 files changed
+6478
-394
No files matched your search
@@ -1,30 +1,9 @@
|
||||
#include "editor/EditorDocumentService.h"
|
||||
#include "editor/EditorValueJson.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
|
||||
namespace eve::editor {
|
||||
namespace {
|
||||
|
||||
std::size_t hashValue(const EditorValue& value) {
|
||||
std::size_t seed = static_cast<std::size_t>(value.type());
|
||||
auto combine = [&](std::size_t next) { seed ^= next + 0x9e3779b9 + (seed << 6) + (seed >> 2); };
|
||||
if (const auto* boolean = value.getIf<bool>()) combine(std::hash<bool>{}(*boolean));
|
||||
if (const auto* integer = value.getIf<std::int64_t>()) combine(std::hash<std::int64_t>{}(*integer));
|
||||
if (const auto* number = value.getIf<double>()) combine(std::hash<double>{}(*number));
|
||||
if (const auto* string = value.getIf<std::string>()) combine(std::hash<std::string>{}(*string));
|
||||
if (const auto* array = value.getIf<EditorValue::Array>())
|
||||
for (const EditorValue& child : *array) combine(hashValue(child));
|
||||
if (const auto* object = value.getIf<EditorValue::Object>())
|
||||
for (const auto& [key, child] : *object) {
|
||||
combine(std::hash<std::string>{}(key));
|
||||
combine(hashValue(child));
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EditorResult<StoredDocument> MemoryAtomicDocumentStore::read(const std::string& resourceUri) const {
|
||||
auto found = documents_.find(resourceUri);
|
||||
@@ -36,18 +15,18 @@ EditorResult<StoredDocument> MemoryAtomicDocumentStore::read(const std::string&
|
||||
|
||||
EditorResult<StoredDocument> MemoryAtomicDocumentStore::compareAndSwap(const std::string& resourceUri,
|
||||
Revision expectedRevision,
|
||||
const std::string& expectedContentHash,
|
||||
const EditorValue& content) {
|
||||
auto found = documents_.find(resourceUri);
|
||||
const Revision current = found == documents_.end() ? 0 : found->second.revision;
|
||||
if (current != expectedRevision)
|
||||
auto found = documents_.find(resourceUri);
|
||||
const Revision current = found == documents_.end() ? 0 : found->second.revision;
|
||||
const std::string currentHash = found == documents_.end() ? std::string{} : found->second.contentHash;
|
||||
if (current != expectedRevision || currentHash != expectedContentHash)
|
||||
return EditorResult<StoredDocument>::error(EditorStatus::Conflict, RuleId("editor.document.disk-conflict"),
|
||||
"Document store revision changed before save");
|
||||
StoredDocument stored;
|
||||
stored.content = content;
|
||||
stored.revision = current + 1;
|
||||
std::ostringstream hash;
|
||||
hash << std::hex << hashValue(content);
|
||||
stored.contentHash = hash.str();
|
||||
stored.content = content;
|
||||
stored.revision = current + 1;
|
||||
stored.contentHash = editorValueContentHash(content);
|
||||
documents_.insert_or_assign(resourceUri, stored);
|
||||
return EditorResult<StoredDocument>::applied(std::move(stored));
|
||||
}
|
||||
@@ -68,10 +47,11 @@ EditorResult<DocumentSnapshot> DocumentService::open(DocumentKey key, std::strin
|
||||
document.snapshot.state = DocumentState::Ready;
|
||||
EditorResult<StoredDocument> stored = store_->read(document.snapshot.resourceUri);
|
||||
if (stored.accepted() && stored.value) {
|
||||
document.content = stored.value->content;
|
||||
document.snapshot.revision.disk = stored.value->revision;
|
||||
document.snapshot.revision.edit = stored.value->revision;
|
||||
document.snapshot.revision.saved = stored.value->revision;
|
||||
document.content = stored.value->content;
|
||||
document.snapshot.revision.disk = stored.value->revision;
|
||||
document.snapshot.revision.edit = stored.value->revision;
|
||||
document.snapshot.revision.saved = stored.value->revision;
|
||||
document.snapshot.diskContentHash = stored.value->contentHash;
|
||||
} else if (stored.status == EditorStatus::NotFound) {
|
||||
document.content = std::move(initialContent);
|
||||
} else {
|
||||
@@ -105,7 +85,7 @@ EditorResult<SaveTicket> DocumentService::requestSave(const DocumentId& document
|
||||
ticket.document = document;
|
||||
ticket.capturedEditRevision = found->second.snapshot.revision.edit;
|
||||
ticket.expectedDiskRevision = found->second.snapshot.revision.disk;
|
||||
ticket.expectedContentHash = contentHash(found->second.content);
|
||||
ticket.expectedContentHash = found->second.snapshot.diskContentHash;
|
||||
pendingSaves_.emplace(ticket.id, PendingSave{ticket, found->second.content});
|
||||
return EditorResult<SaveTicket>::applied(std::move(ticket));
|
||||
}
|
||||
@@ -116,9 +96,10 @@ EditorResult<DocumentSnapshot> DocumentService::executeSave(const SaveTicket& ti
|
||||
if (pending == pendingSaves_.end() || document == open_.end())
|
||||
return error(EditorStatus::NotFound, "editor.document.save-ticket-not-found",
|
||||
"Save ticket or document is no longer available");
|
||||
document->second.snapshot.state = DocumentState::Saving;
|
||||
EditorResult<StoredDocument> stored = store_->compareAndSwap(document->second.snapshot.resourceUri,
|
||||
ticket.expectedDiskRevision, pending->second.content);
|
||||
document->second.snapshot.state = DocumentState::Saving;
|
||||
EditorResult<StoredDocument> stored =
|
||||
store_->compareAndSwap(document->second.snapshot.resourceUri, ticket.expectedDiskRevision,
|
||||
ticket.expectedContentHash, pending->second.content);
|
||||
pendingSaves_.erase(pending);
|
||||
if (!stored.accepted() || !stored.value) {
|
||||
document->second.snapshot.state =
|
||||
@@ -130,9 +111,10 @@ EditorResult<DocumentSnapshot> DocumentService::executeSave(const SaveTicket& ti
|
||||
result.diagnostics = std::move(stored.diagnostics);
|
||||
return result;
|
||||
}
|
||||
document->second.snapshot.revision.disk = stored.value->revision;
|
||||
document->second.snapshot.revision.saved = ticket.capturedEditRevision;
|
||||
document->second.snapshot.state = DocumentState::Ready;
|
||||
document->second.snapshot.revision.disk = stored.value->revision;
|
||||
document->second.snapshot.revision.saved = ticket.capturedEditRevision;
|
||||
document->second.snapshot.diskContentHash = stored.value->contentHash;
|
||||
document->second.snapshot.state = DocumentState::Ready;
|
||||
document->second.snapshot.diagnostics.clear();
|
||||
return EditorResult<DocumentSnapshot>::applied(document->second.snapshot);
|
||||
}
|
||||
@@ -171,12 +153,6 @@ EditorResult<void> DocumentService::close(const DocumentId& document) {
|
||||
return EditorResult<void>::applied();
|
||||
}
|
||||
|
||||
std::string DocumentService::contentHash(const EditorValue& value) {
|
||||
std::ostringstream stream;
|
||||
stream << std::hex << hashValue(value);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
EditorResult<DocumentSnapshot> DocumentService::error(EditorStatus status, const char* rule, std::string message) {
|
||||
return EditorResult<DocumentSnapshot>::error(status, RuleId(rule), std::move(message));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user