From a48d63a66494538b4b55f98e9cb63d7d1f35439e Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Thu, 11 Jan 2024 21:32:08 -0800 Subject: [PATCH] [Yunq] Add support for nested fields in messages. --- lib/yunq/message_view.h | 12 ++ lib/yunq/serialize.h | 23 ++ sys/denali/denali_server.cpp | 11 +- sys/denali/lib/denali/denali.yunq | 9 +- sys/denali/lib/denali/denali.yunq.cpp | 56 ++++- sys/denali/lib/denali/denali.yunq.h | 36 +++- .../fs/ext2/ext2_block_reader.cpp | 8 +- sys/yellowstone/hw/gpt.cpp | 8 +- yunq/example/example.yunq.client.cpp | 7 +- yunq/example/example.yunq.client.h | 2 +- yunq/example/example.yunq.cpp | 200 +++++------------- yunq/example/example.yunq.h | 19 +- yunq/example/example.yunq.server.cpp | 26 +-- yunq/example/example.yunq.server.h | 9 +- yunq/message.cpp.jinja | 18 +- yunq/message.h.jinja | 8 + yunq/parser.py | 23 +- yunq/yunq.py | 1 + 18 files changed, 257 insertions(+), 219 deletions(-) diff --git a/lib/yunq/message_view.h b/lib/yunq/message_view.h index 996ba8f..069c00c 100644 --- a/lib/yunq/message_view.h +++ b/lib/yunq/message_view.h @@ -28,6 +28,9 @@ class MessageView { glcr::ErrorOr ReadCapability(uint64_t field_index, const glcr::CapBuffer& caps) const; + template + glcr::Status ReadMessage(uint64_t field_index, T& message) const; + private: const glcr::ByteBuffer& buffer_; uint64_t offset_; @@ -49,4 +52,13 @@ template <> glcr::ErrorOr> MessageView::ReadRepeated( uint64_t field_index) const; +template +glcr::Status MessageView::ReadMessage(uint64_t field_index, T& message) const { + ExtensionPointer ptr = + buffer_.At(field_offset(field_index)); + + MessageView subview(buffer_, offset_ + ptr.offset); + return message.ParseFromBytes(subview); +} + } // namespace yunq diff --git a/lib/yunq/serialize.h b/lib/yunq/serialize.h index 68f9775..ac0b2ff 100644 --- a/lib/yunq/serialize.h +++ b/lib/yunq/serialize.h @@ -38,6 +38,9 @@ class Serializer { void WriteRepeatedCapability(uint64_t field_index, const glcr::Vector& value); + template + void WriteMessage(uint64_t field_index, const T& value); + void WriteHeader(); uint64_t size() const { return next_extension_; } @@ -67,4 +70,24 @@ template <> void Serializer::WriteRepeated(uint64_t field_index, const glcr::Vector& value); +template +void Serializer::WriteMessage(uint64_t field_index, const T& value) { + uint64_t length = 0; + if (caps_) { + length = value.SerializeToBytes(buffer_, offset_ + next_extension_, + caps_.value().get()); + } else { + length = value.SerializeToBytes(buffer_, offset_ + next_extension_); + } + + ExtensionPointer ptr{ + .offset = (uint32_t)next_extension_, + .length = (uint32_t)length, + }; + + next_extension_ += length; + + buffer_.WriteAt(field_offset(field_index), ptr); +} + } // namespace yunq diff --git a/sys/denali/denali_server.cpp b/sys/denali/denali_server.cpp index ba99e3e..1b3cbc7 100644 --- a/sys/denali/denali_server.cpp +++ b/sys/denali/denali_server.cpp @@ -17,15 +17,16 @@ glcr::Status DenaliServer::HandleRead(const ReadRequest& req, ASSIGN_OR_RETURN(AhciPort * device, driver_.GetDevice(req.device_id())); uint64_t paddr; - mmth::OwnedMemoryRegion region = - mmth::OwnedMemoryRegion::ContiguousPhysical(req.size() * 512, &paddr); + mmth::OwnedMemoryRegion region = mmth::OwnedMemoryRegion::ContiguousPhysical( + req.block().size() * 512, &paddr); - ASSIGN_OR_RETURN(auto semaphore, - device->IssueRead(req.lba(), req.size(), paddr)); + ASSIGN_OR_RETURN( + auto semaphore, + device->IssueRead(req.block().lba(), req.block().size(), paddr)); semaphore->Wait(); resp.set_device_id(req.device_id()); - resp.set_size(req.size()); + resp.set_size(req.block().size()); resp.set_memory(region.DuplicateCap()); return glcr::Status::Ok(); } diff --git a/sys/denali/lib/denali/denali.yunq b/sys/denali/lib/denali/denali.yunq index 340861b..cc3225b 100644 --- a/sys/denali/lib/denali/denali.yunq +++ b/sys/denali/lib/denali/denali.yunq @@ -3,12 +3,17 @@ interface Denali { method ReadMany(ReadManyRequest) -> (ReadResponse); } -message ReadRequest { - u64 device_id; +message DiskBlock { u64 lba; u64 size; } +message ReadRequest { + u64 device_id; + DiskBlock block; +} + + message ReadManyRequest { u64 device_id; // FIXME: Add repeated message fields. diff --git a/sys/denali/lib/denali/denali.yunq.cpp b/sys/denali/lib/denali/denali.yunq.cpp index 5ba2a69..81e82f0 100644 --- a/sys/denali/lib/denali/denali.yunq.cpp +++ b/sys/denali/lib/denali/denali.yunq.cpp @@ -15,6 +15,46 @@ struct ExtPointer { }; } // namespace +glcr::Status DiskBlock::ParseFromBytes(const yunq::MessageView& message) { + RETURN_ERROR(ParseFromBytesInternal(message)); + return glcr::Status::Ok(); +} + +glcr::Status DiskBlock::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) { + RETURN_ERROR(ParseFromBytesInternal(message)); + return glcr::Status::Ok(); +} + +glcr::Status DiskBlock::ParseFromBytesInternal(const yunq::MessageView& message) { + RETURN_ERROR(message.CheckHeader()); + // Parse lba. + ASSIGN_OR_RETURN(lba_, message.ReadField(0)); + // Parse size. + ASSIGN_OR_RETURN(size_, message.ReadField(1)); + + return glcr::Status::Ok(); +} + +uint64_t DiskBlock::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const { + yunq::Serializer serializer(bytes, offset, 2); + return SerializeInternal(serializer); +} + +uint64_t DiskBlock::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const { + yunq::Serializer serializer(bytes, offset, 2, caps); + return SerializeInternal(serializer); +} + +uint64_t DiskBlock::SerializeInternal(yunq::Serializer& serializer) const { + // Write lba. + serializer.WriteField(0, lba_); + // Write size. + serializer.WriteField(1, size_); + + serializer.WriteHeader(); + + return serializer.size(); +} glcr::Status ReadRequest::ParseFromBytes(const yunq::MessageView& message) { RETURN_ERROR(ParseFromBytesInternal(message)); return glcr::Status::Ok(); @@ -29,31 +69,27 @@ glcr::Status ReadRequest::ParseFromBytesInternal(const yunq::MessageView& messag RETURN_ERROR(message.CheckHeader()); // Parse device_id. ASSIGN_OR_RETURN(device_id_, message.ReadField(0)); - // Parse lba. - ASSIGN_OR_RETURN(lba_, message.ReadField(1)); - // Parse size. - ASSIGN_OR_RETURN(size_, message.ReadField(2)); + // Parse block. + message.ReadMessage(1, block_); return glcr::Status::Ok(); } uint64_t ReadRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const { - yunq::Serializer serializer(bytes, offset, 3); + yunq::Serializer serializer(bytes, offset, 2); return SerializeInternal(serializer); } uint64_t ReadRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const { - yunq::Serializer serializer(bytes, offset, 3, caps); + yunq::Serializer serializer(bytes, offset, 2, caps); return SerializeInternal(serializer); } uint64_t ReadRequest::SerializeInternal(yunq::Serializer& serializer) const { // Write device_id. serializer.WriteField(0, device_id_); - // Write lba. - serializer.WriteField(1, lba_); - // Write size. - serializer.WriteField(2, size_); + // Write block. + serializer.WriteMessage(1, block_); serializer.WriteHeader(); diff --git a/sys/denali/lib/denali/denali.yunq.h b/sys/denali/lib/denali/denali.yunq.h index d4b093c..2707234 100644 --- a/sys/denali/lib/denali/denali.yunq.h +++ b/sys/denali/lib/denali/denali.yunq.h @@ -11,6 +11,31 @@ #include +class DiskBlock { + public: + DiskBlock() {} + // Delete copy and move until implemented. + DiskBlock(const DiskBlock&) = delete; + DiskBlock(DiskBlock&&) = delete; + + [[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message); + [[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const; + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const; + const uint64_t& lba() const { return lba_; } + void set_lba(const uint64_t& value) { lba_ = value; } + const uint64_t& size() const { return size_; } + void set_size(const uint64_t& value) { size_ = value; } + + private: + uint64_t lba_; + uint64_t size_; + + // Parses everything except for caps. + glcr::Status ParseFromBytesInternal(const yunq::MessageView& message); + + uint64_t SerializeInternal(yunq::Serializer& serializer) const; +}; class ReadRequest { public: ReadRequest() {} @@ -23,16 +48,13 @@ class ReadRequest { uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const; uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const; const uint64_t& device_id() const { return device_id_; } - void set_device_id(const uint64_t& value) { device_id_ = value; } - const uint64_t& lba() const { return lba_; } - void set_lba(const uint64_t& value) { lba_ = value; } - const uint64_t& size() const { return size_; } - void set_size(const uint64_t& value) { size_ = value; } + void set_device_id(const uint64_t& value) { device_id_ = value; } + const DiskBlock& block() const { return block_; } + DiskBlock& mutable_block() { return block_; } private: uint64_t device_id_; - uint64_t lba_; - uint64_t size_; + DiskBlock block_; // Parses everything except for caps. glcr::Status ParseFromBytesInternal(const yunq::MessageView& message); diff --git a/sys/victoriafalls/fs/ext2/ext2_block_reader.cpp b/sys/victoriafalls/fs/ext2/ext2_block_reader.cpp index d8a6006..9de13f8 100644 --- a/sys/victoriafalls/fs/ext2/ext2_block_reader.cpp +++ b/sys/victoriafalls/fs/ext2/ext2_block_reader.cpp @@ -9,8 +9,8 @@ glcr::ErrorOr> Ext2BlockReader::Init( DenaliClient client(denali_info.denali_endpoint()); ReadRequest req; req.set_device_id(denali_info.device_id()); - req.set_lba(denali_info.lba_offset() + 2); - req.set_size(2); + req.mutable_block().set_lba(denali_info.lba_offset() + 2); + req.mutable_block().set_size(2); ReadResponse resp; auto status = client.Read(req, resp); if (!status.ok()) { @@ -71,8 +71,8 @@ glcr::ErrorOr Ext2BlockReader::ReadBlocks( uint64_t block_number, uint64_t num_blocks) { ReadRequest req; req.set_device_id(device_id_); - req.set_lba(lba_offset_ + block_number * SectorsPerBlock()); - req.set_size(num_blocks * SectorsPerBlock()); + req.mutable_block().set_lba(lba_offset_ + block_number * SectorsPerBlock()); + req.mutable_block().set_size(num_blocks * SectorsPerBlock()); ReadResponse resp; auto status = denali_.Read(req, resp); if (!status.ok()) { diff --git a/sys/yellowstone/hw/gpt.cpp b/sys/yellowstone/hw/gpt.cpp index b4eddc7..43704cd 100644 --- a/sys/yellowstone/hw/gpt.cpp +++ b/sys/yellowstone/hw/gpt.cpp @@ -59,8 +59,8 @@ GptReader::GptReader(glcr::UniquePtr denali) glcr::Status GptReader::ParsePartitionTables() { ReadRequest req; req.set_device_id(0); - req.set_lba(0); - req.set_size(2); + req.mutable_block().set_lba(0); + req.mutable_block().set_size(2); ReadResponse resp; RETURN_ERROR(denali_->Read(req, resp)); mmth::OwnedMemoryRegion lba_1_and_2 = @@ -102,8 +102,8 @@ glcr::Status GptReader::ParsePartitionTables() { #endif req.set_device_id(0); - req.set_lba(header->lba_partition_entries); - req.set_size(num_blocks); + req.mutable_block().set_lba(header->lba_partition_entries); + req.mutable_block().set_size(num_blocks); RETURN_ERROR(denali_->Read(req, resp)); mmth::OwnedMemoryRegion part_table = mmth::OwnedMemoryRegion::FromCapability(resp.memory()); diff --git a/yunq/example/example.yunq.client.cpp b/yunq/example/example.yunq.client.cpp index 1d3dd21..406e895 100644 --- a/yunq/example/example.yunq.client.cpp +++ b/yunq/example/example.yunq.client.cpp @@ -20,7 +20,7 @@ VFSClient::~VFSClient() { -glcr::ErrorCode VFSClient::open(const OpenFileRequest& request, File& response) { +glcr::Status VFSClient::open(const OpenFileRequest& request, File& response) { uint64_t buffer_size = kBufferSize; uint64_t cap_size = kCapBufferSize; @@ -43,14 +43,15 @@ glcr::ErrorCode VFSClient::open(const OpenFileRequest& request, File& response) RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr())); if (buffer_.At(0) != kSentinel) { - return glcr::INVALID_RESPONSE; + return glcr::InvalidResponse("Got an invalid response from server."); } // Check Response Code. RET_ERR(buffer_.At(8)); - response.ParseFromBytes(buffer_, 16, cap_buffer_); + yunq::MessageView resp_view(buffer_, 16); + RETURN_ERROR(response.ParseFromBytes(resp_view, cap_buffer_)); return glcr::OK; diff --git a/yunq/example/example.yunq.client.h b/yunq/example/example.yunq.client.h index d9fdb3c..826d920 100644 --- a/yunq/example/example.yunq.client.h +++ b/yunq/example/example.yunq.client.h @@ -22,7 +22,7 @@ class VFSClient { - [[nodiscard]] glcr::ErrorCode open(const OpenFileRequest& request, File& response); + [[nodiscard]] glcr::Status open(const OpenFileRequest& request, File& response); private: diff --git a/yunq/example/example.yunq.cpp b/yunq/example/example.yunq.cpp index 1211542..4033cfc 100644 --- a/yunq/example/example.yunq.cpp +++ b/yunq/example/example.yunq.cpp @@ -1,6 +1,9 @@ // Generated file -- DO NOT MODIFY. #include "example.yunq.h" +#include +#include + namespace srv::file { @@ -13,197 +16,94 @@ struct ExtPointer { uint32_t length; }; -void CheckHeader(const glcr::ByteBuffer& bytes) { - // TODO: Check ident. - // TODO: Parse core size. - // TODO: Parse extension size. - // TODO: Check CRC32 - // TODO: Parse options. -} - -void WriteHeader(glcr::ByteBuffer& bytes, uint64_t offset, uint32_t core_size, uint32_t extension_size) { - bytes.WriteAt(offset + 0, 0xDEADBEEF); // TODO: Chose a more unique ident sequence. - bytes.WriteAt(offset + 4, core_size); - bytes.WriteAt(offset + 8, extension_size); - bytes.WriteAt(offset + 12, 0); // TODO: Calculate CRC32. - bytes.WriteAt(offset + 16, 0); // TODO: Add options. -} - } // namespace -void OpenFileRequest::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) { - ParseFromBytesInternal(bytes, offset); +glcr::Status OpenFileRequest::ParseFromBytes(const yunq::MessageView& message) { + RETURN_ERROR(ParseFromBytesInternal(message)); + return glcr::Status::Ok(); } -void OpenFileRequest::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) { - ParseFromBytesInternal(bytes, offset); +glcr::Status OpenFileRequest::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) { + RETURN_ERROR(ParseFromBytesInternal(message)); + return glcr::Status::Ok(); } -void OpenFileRequest::ParseFromBytesInternal(const glcr::ByteBuffer& bytes, uint64_t offset) { - CheckHeader(bytes); +glcr::Status OpenFileRequest::ParseFromBytesInternal(const yunq::MessageView& message) { + RETURN_ERROR(message.CheckHeader()); // Parse path. - auto path_pointer = bytes.At(offset + header_size + (8 * 0)); - - set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); + ASSIGN_OR_RETURN(path_, message.ReadField(0)); // Parse options. - auto options_pointer = bytes.At(offset + header_size + (8 * 1)); - - options_.Resize(options_pointer.length / sizeof(uint64_t)); - for (uint64_t i = offset + options_pointer.offset; - i < offset + options_pointer.offset + options_pointer.length; - i += sizeof(uint64_t)) { - options_.PushBack(bytes.At(i)); - } + ASSIGN_OR_RETURN(options_, message.ReadRepeated(1)); + return glcr::Status::Ok(); } uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const { - uint32_t next_extension = header_size + 8 * 2; - const uint32_t core_size = next_extension; - // Write path. - ExtPointer path_ptr{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t)path().length(), - }; - - bytes.WriteStringAt(offset + next_extension, path()); - next_extension += path_ptr.length; - - bytes.WriteAt(offset + header_size + (8 * 0), path_ptr); - // Write options. - ExtPointer options_ptr{ - .offset = next_extension, - .length = (uint32_t)(options().size() * sizeof(uint64_t)), - }; - - next_extension += options_ptr.length; - bytes.WriteAt(offset + header_size + (8 * 1), options_ptr); - - for (uint64_t i = 0; i < options().size(); i++) { - uint32_t ext_offset = offset + options_ptr.offset + (i * sizeof(uint64_t)); - bytes.WriteAt(ext_offset, options().at(i)); - } - - // The next extension pointer is the length of the message. - WriteHeader(bytes, offset, core_size, next_extension); - - return next_extension; + yunq::Serializer serializer(bytes, offset, 2); + return SerializeInternal(serializer); } uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const { - uint32_t next_extension = header_size + 8 * 2; - const uint32_t core_size = next_extension; - uint64_t next_cap = 0; + yunq::Serializer serializer(bytes, offset, 2, caps); + return SerializeInternal(serializer); +} + +uint64_t OpenFileRequest::SerializeInternal(yunq::Serializer& serializer) const { // Write path. - ExtPointer path_ptr{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t)path().length(), - }; - - bytes.WriteStringAt(offset + next_extension, path()); - next_extension += path_ptr.length; - - bytes.WriteAt(offset + header_size + (8 * 0), path_ptr); + serializer.WriteField(0, path_); // Write options. - ExtPointer options_ptr{ - .offset = next_extension, - .length = (uint32_t)(options().size() * sizeof(uint64_t)), - }; + serializer.WriteRepeated(1, options_); - next_extension += options_ptr.length; - bytes.WriteAt(offset + header_size + (8 * 1), options_ptr); + serializer.WriteHeader(); - for (uint64_t i = 0; i < options().size(); i++) { - uint32_t ext_offset = offset + options_ptr.offset + (i * sizeof(uint64_t)); - bytes.WriteAt(ext_offset, options().at(i)); - } - - // The next extension pointer is the length of the message. - WriteHeader(bytes, offset, core_size, next_extension); - - return next_extension; + return serializer.size(); } -void File::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) { - ParseFromBytesInternal(bytes, offset); +glcr::Status File::ParseFromBytes(const yunq::MessageView& message) { + RETURN_ERROR(ParseFromBytesInternal(message)); // Parse mem_cap. - // FIXME: Implement in-buffer capabilities for inprocess serialization. - set_mem_cap(0); + ASSIGN_OR_RETURN(mem_cap_, message.ReadCapability(2)); + return glcr::Status::Ok(); } -void File::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) { - ParseFromBytesInternal(bytes, offset); +glcr::Status File::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) { + RETURN_ERROR(ParseFromBytesInternal(message)); // Parse mem_cap. - uint64_t mem_cap_ptr = bytes.At(offset + header_size + (8 * 2)); - - set_mem_cap(caps.At(mem_cap_ptr)); + ASSIGN_OR_RETURN(mem_cap_, message.ReadCapability(2, caps)); + return glcr::Status::Ok(); } -void File::ParseFromBytesInternal(const glcr::ByteBuffer& bytes, uint64_t offset) { - CheckHeader(bytes); +glcr::Status File::ParseFromBytesInternal(const yunq::MessageView& message) { + RETURN_ERROR(message.CheckHeader()); // Parse path. - auto path_pointer = bytes.At(offset + header_size + (8 * 0)); - - set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); + ASSIGN_OR_RETURN(path_, message.ReadField(0)); // Parse attrs. - set_attrs(bytes.At(offset + header_size + (8 * 1))); + ASSIGN_OR_RETURN(attrs_, message.ReadField(1)); // Parse mem_cap. - // Skip Cap. + return glcr::Status::Ok(); } uint64_t File::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const { - uint32_t next_extension = header_size + 8 * 3; - const uint32_t core_size = next_extension; - // Write path. - ExtPointer path_ptr{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t)path().length(), - }; - - bytes.WriteStringAt(offset + next_extension, path()); - next_extension += path_ptr.length; - - bytes.WriteAt(offset + header_size + (8 * 0), path_ptr); - // Write attrs. - bytes.WriteAt(offset + header_size + (8 * 1), attrs()); - // Write mem_cap. - // FIXME: Implement inbuffer capabilities. - bytes.WriteAt(offset + header_size + (8 * 2), 0); - - // The next extension pointer is the length of the message. - WriteHeader(bytes, offset, core_size, next_extension); - - return next_extension; + yunq::Serializer serializer(bytes, offset, 3); + return SerializeInternal(serializer); } uint64_t File::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const { - uint32_t next_extension = header_size + 8 * 3; - const uint32_t core_size = next_extension; - uint64_t next_cap = 0; + yunq::Serializer serializer(bytes, offset, 3, caps); + return SerializeInternal(serializer); +} + +uint64_t File::SerializeInternal(yunq::Serializer& serializer) const { // Write path. - ExtPointer path_ptr{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t)path().length(), - }; - - bytes.WriteStringAt(offset + next_extension, path()); - next_extension += path_ptr.length; - - bytes.WriteAt(offset + header_size + (8 * 0), path_ptr); + serializer.WriteField(0, path_); // Write attrs. - bytes.WriteAt(offset + header_size + (8 * 1), attrs()); + serializer.WriteField(1, attrs_); // Write mem_cap. - caps.WriteAt(next_cap, mem_cap()); - bytes.WriteAt(offset + header_size + (8 * 2), next_cap++); + serializer.WriteCapability(2, mem_cap_); - // The next extension pointer is the length of the message. - WriteHeader(bytes, offset, core_size, next_extension); + serializer.WriteHeader(); - return next_extension; + return serializer.size(); } diff --git a/yunq/example/example.yunq.h b/yunq/example/example.yunq.h index 1b9176e..112ddab 100644 --- a/yunq/example/example.yunq.h +++ b/yunq/example/example.yunq.h @@ -3,8 +3,11 @@ #include #include +#include #include #include +#include +#include #include @@ -17,8 +20,8 @@ class OpenFileRequest { OpenFileRequest(const OpenFileRequest&) = delete; OpenFileRequest(OpenFileRequest&&) = delete; - void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); - void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); + [[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message); + [[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&); uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const; uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const; const glcr::String& path() const { return path_; } @@ -31,7 +34,9 @@ class OpenFileRequest { glcr::Vector options_; // Parses everything except for caps. - void ParseFromBytesInternal(const glcr::ByteBuffer&, uint64_t offset); + glcr::Status ParseFromBytesInternal(const yunq::MessageView& message); + + uint64_t SerializeInternal(yunq::Serializer& serializer) const; }; class File { public: @@ -40,8 +45,8 @@ class File { File(const File&) = delete; File(File&&) = delete; - void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); - void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); + [[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message); + [[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&); uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const; uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const; const glcr::String& path() const { return path_; } @@ -57,7 +62,9 @@ class File { z_cap_t mem_cap_; // Parses everything except for caps. - void ParseFromBytesInternal(const glcr::ByteBuffer&, uint64_t offset); + glcr::Status ParseFromBytesInternal(const yunq::MessageView& message); + + uint64_t SerializeInternal(yunq::Serializer& serializer) const; }; diff --git a/yunq/example/example.yunq.server.cpp b/yunq/example/example.yunq.server.cpp index 555c8d7..5c3b84c 100644 --- a/yunq/example/example.yunq.server.cpp +++ b/yunq/example/example.yunq.server.cpp @@ -75,9 +75,10 @@ void VFSServerBase::ServerThread() { glcr::ErrorCode reply_err = glcr::OK; resp_cap.Reset(); - glcr::ErrorCode err = HandleRequest(recv_buffer, recv_cap, resp_buffer, resp_length, resp_cap); - if (err != glcr::OK) { - WriteError(resp_buffer, err); + glcr::Status err = HandleRequest(recv_buffer, recv_cap, resp_buffer, resp_length, resp_cap); + if (!err) { + WriteError(resp_buffer, err.code()); + dbgln("Responding Error {}", err.message()); reply_err = static_cast(ZReplyPortSend(reply_port_cap, kHeaderSize, resp_buffer.RawPtr(), 0, nullptr)); } else { WriteHeader(resp_buffer, resp_length); @@ -90,12 +91,12 @@ void VFSServerBase::ServerThread() { } -glcr::ErrorCode VFSServerBase::HandleRequest(const glcr::ByteBuffer& request, - const glcr::CapBuffer& req_caps, - glcr::ByteBuffer& response, uint64_t& resp_length, - glcr::CapBuffer& resp_caps) { +glcr::Status VFSServerBase::HandleRequest(const glcr::ByteBuffer& request, + const glcr::CapBuffer& req_caps, + glcr::ByteBuffer& response, uint64_t& resp_length, + glcr::CapBuffer& resp_caps) { if (request.At(0) != kSentinel) { - return glcr::INVALID_ARGUMENT; + return glcr::InvalidArgument("Request Not Valid"); } uint64_t method_select = request.At(8); @@ -105,7 +106,8 @@ glcr::ErrorCode VFSServerBase::HandleRequest(const glcr::ByteBuffer& request, OpenFileRequest yunq_request; - yunq_request.ParseFromBytes(request, kHeaderSize, req_caps); + yunq::MessageView request_view(request, kHeaderSize); + RETURN_ERROR(yunq_request.ParseFromBytes(request_view, req_caps)); @@ -113,7 +115,7 @@ glcr::ErrorCode VFSServerBase::HandleRequest(const glcr::ByteBuffer& request, - RET_ERR(Handleopen(yunq_request, yunq_response)); + RETURN_ERROR(Handleopen(yunq_request, yunq_response)); @@ -122,10 +124,10 @@ glcr::ErrorCode VFSServerBase::HandleRequest(const glcr::ByteBuffer& request, break; } default: { - return glcr::UNIMPLEMENTED; + return glcr::Unimplemented("Method unimplemented by server."); } } - return glcr::OK; + return glcr::Status::Ok(); } diff --git a/yunq/example/example.yunq.server.h b/yunq/example/example.yunq.server.h index e1cb556..646e669 100644 --- a/yunq/example/example.yunq.server.h +++ b/yunq/example/example.yunq.server.h @@ -2,6 +2,7 @@ #pragma once #include +#include #include #include @@ -28,7 +29,7 @@ class VFSServerBase { - [[nodiscard]] virtual glcr::ErrorCode Handleopen(const OpenFileRequest&, File&) = 0; + [[nodiscard]] virtual glcr::Status Handleopen(const OpenFileRequest&, File&) = 0; @@ -38,9 +39,9 @@ class VFSServerBase { friend void VFSServerBaseThreadBootstrap(void*); void ServerThread(); - [[nodiscard]] glcr::ErrorCode HandleRequest(const glcr::ByteBuffer& request, const glcr::CapBuffer& req_caps, - glcr::ByteBuffer& response, uint64_t& resp_length, - glcr::CapBuffer& resp_caps); + [[nodiscard]] glcr::Status HandleRequest(const glcr::ByteBuffer& request, const glcr::CapBuffer& req_caps, + glcr::ByteBuffer& response, uint64_t& resp_length, + glcr::CapBuffer& resp_caps); }; diff --git a/yunq/message.cpp.jinja b/yunq/message.cpp.jinja index 4a3e599..cf96c8c 100644 --- a/yunq/message.cpp.jinja +++ b/yunq/message.cpp.jinja @@ -58,7 +58,15 @@ glcr::Status {{message.name}}::ParseFromBytesInternal(const yunq::MessageView& m {%- for field in message.fields %} // Parse {{field.name}}. -{%- if field.type != Type.CAPABILITY %} +{%- if field.type == Type.MESSAGE %} + +{%- if not field.repeated %} + message.ReadMessage<{{field.cpp_type()}}>({{field.number}}, {{field.name}}_); +{%- else %} + message.ReadMessageRepeated<{{field.cpp_type()}}>({{field.number}}, {{field.name}}_); +{% endif %} + +{%- elif field.type != Type.CAPABILITY %} {%- if not field.repeated %} ASSIGN_OR_RETURN({{field.name}}_, message.ReadField<{{field.cpp_type()}}>({{field.number}})); @@ -87,10 +95,12 @@ uint64_t {{message.name}}::SerializeInternal(yunq::Serializer& serializer) const // Write {{field.name}}. {%- if not field.repeated %} -{%- if field.type != Type.CAPABILITY %} - serializer.WriteField<{{field.cpp_type()}}>({{field.number}}, {{field.name}}_); -{%- else %} +{%- if field.type == Type.MESSAGE %} + serializer.WriteMessage<{{field.cpp_type()}}>({{field.number}}, {{field.name}}_); +{%- elif field.type == Type.CAPABILITY %} serializer.WriteCapability({{field.number}}, {{field.name}}_); +{%- else %} + serializer.WriteField<{{field.cpp_type()}}>({{field.number}}, {{field.name}}_); {%- endif %} {%- else %} diff --git a/yunq/message.h.jinja b/yunq/message.h.jinja index 814ce81..5274771 100644 --- a/yunq/message.h.jinja +++ b/yunq/message.h.jinja @@ -28,6 +28,12 @@ class {{message.name}} { uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const; {%- for field in message.fields %} + {%- if field.type == Type.MESSAGE %} + const {{field.cpp_type()}}& {{field.name}}() const { return {{field.name}}_; } + {{field.cpp_type()}}& mutable_{{field.name}}() { return {{field.name}}_; } + + {%- else %} + {%- if not field.repeated %} const {{field.cpp_type()}}& {{field.name}}() const { return {{field.name}}_; } void set_{{field.name}}(const {{field.cpp_type()}}& value) { {{field.name}}_ = value; } @@ -35,6 +41,8 @@ class {{message.name}} { const glcr::Vector<{{field.cpp_type()}}>& {{field.name}}() const { return {{field.name}}_; } void add_{{field.name}}(const {{field.cpp_type()}}& value) { {{field.name}}_.PushBack(value); } {%- endif %} + + {%- endif %} {%- endfor %} private: diff --git a/yunq/parser.py b/yunq/parser.py index 403f27b..c3ec971 100644 --- a/yunq/parser.py +++ b/yunq/parser.py @@ -106,6 +106,7 @@ class Type(Enum): STRING = 3 BYTES = 4 CAPABILITY = 5 + MESSAGE = 6 type_str_dict = { "u64": Type.U64, @@ -124,12 +125,18 @@ type_to_cppstr = { } class Field(): - def __init__(self, fieldtype: Type, name: str, repeated = False): - self.type = fieldtype + def __init__(self, field_type_str: str, name: str, repeated = False): + if field_type_str in type_str_dict.keys(): + self.type = type_str_dict[field_type_str] + else: + self.type = Type.MESSAGE + self.type_str = field_type_str self.name = name self.repeated = repeated def cpp_type(self): + if self.type == Type.MESSAGE: + return self.type_str return type_to_cppstr[self.type] class Message(): @@ -293,14 +300,10 @@ class Parser(): if field_type_str == "repeated": repeated = True field_type_str = self.consume_identifier() - - if field_type_str not in type_str_dict.keys(): - sys.exit("Expected type got '%s'" % field_type_str) - field_type = type_str_dict[field_type_str] name = self.consume_identifier() self.consume_check(LexemeType.SEMICOLON) - return Field(field_type, name, repeated) + return Field(field_type_str, name, repeated) def type_check(decls: list[Decl]): if sum(1 for decl in decls if type(decl) is Package) > 1: @@ -320,6 +323,12 @@ def type_check(decls: list[Decl]): sys.exit("Response type '%s' for '%s.%s' does not exist" % (method.response, decl.name, method.name)) if type(name_dict[method.response]) is not Message: sys.exit("Response type '%s' for '%s.%s' should be a message" % (method.response, decl.name, method.name)) + elif type(decl) is Message: + for field in decl.fields: + if field.type == Type.MESSAGE: + if field.type_str not in name_dict.keys(): + sys.exit("Field type '%s' for field '%s' in message '%s' not found." % + (field.type_str, field.name, decl.name)) def print_ast(decls: list[Decl]): for decl in decls: diff --git a/yunq/yunq.py b/yunq/yunq.py index c217e19..743f08c 100755 --- a/yunq/yunq.py +++ b/yunq/yunq.py @@ -34,6 +34,7 @@ def main(): jinja_env = Environment(loader=FileSystemLoader(pathlib.Path(__file__).parent.resolve())) message_header_tmpl = jinja_env.get_template("message.h.jinja") + message_header_tmpl.globals['Type'] = Type with open(filename + '.h', mode='w') as f: message_header = message_header_tmpl.render(messages=messages, package=package) f.write(message_header)