[Yunq] Add support for nested fields in messages.
This commit is contained in:
		
							parent
							
								
									9e12531651
								
							
						
					
					
						commit
						a48d63a664
					
				|  | @ -28,6 +28,9 @@ class MessageView { | |||
|   glcr::ErrorOr<uint64_t> ReadCapability(uint64_t field_index, | ||||
|                                          const glcr::CapBuffer& caps) const; | ||||
| 
 | ||||
|   template <typename T> | ||||
|   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<glcr::Vector<uint64_t>> MessageView::ReadRepeated<uint64_t>( | ||||
|     uint64_t field_index) const; | ||||
| 
 | ||||
| template <typename T> | ||||
| glcr::Status MessageView::ReadMessage(uint64_t field_index, T& message) const { | ||||
|   ExtensionPointer ptr = | ||||
|       buffer_.At<ExtensionPointer>(field_offset(field_index)); | ||||
| 
 | ||||
|   MessageView subview(buffer_, offset_ + ptr.offset); | ||||
|   return message.ParseFromBytes(subview); | ||||
| } | ||||
| 
 | ||||
| }  // namespace yunq
 | ||||
|  |  | |||
|  | @ -38,6 +38,9 @@ class Serializer { | |||
|   void WriteRepeatedCapability(uint64_t field_index, | ||||
|                                const glcr::Vector<uint64_t>& value); | ||||
| 
 | ||||
|   template <typename T> | ||||
|   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>(uint64_t field_index, | ||||
|                                          const glcr::Vector<uint64_t>& value); | ||||
| 
 | ||||
| template <typename T> | ||||
| 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<ExtensionPointer>(field_offset(field_index), ptr); | ||||
| } | ||||
| 
 | ||||
| }  // namespace yunq
 | ||||
|  |  | |||
|  | @ -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(); | ||||
| } | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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<uint64_t>(0)); | ||||
|   // Parse size.
 | ||||
|   ASSIGN_OR_RETURN(size_, message.ReadField<uint64_t>(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<uint64_t>(0, lba_); | ||||
|   // Write size.
 | ||||
|   serializer.WriteField<uint64_t>(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<uint64_t>(0)); | ||||
|   // Parse lba.
 | ||||
|   ASSIGN_OR_RETURN(lba_, message.ReadField<uint64_t>(1)); | ||||
|   // Parse size.
 | ||||
|   ASSIGN_OR_RETURN(size_, message.ReadField<uint64_t>(2)); | ||||
|   // Parse block.
 | ||||
|   message.ReadMessage<DiskBlock>(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<uint64_t>(0, device_id_); | ||||
|   // Write lba.
 | ||||
|   serializer.WriteField<uint64_t>(1, lba_); | ||||
|   // Write size.
 | ||||
|   serializer.WriteField<uint64_t>(2, size_); | ||||
|   // Write block.
 | ||||
|   serializer.WriteMessage<DiskBlock>(1, block_); | ||||
| 
 | ||||
|   serializer.WriteHeader(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,31 @@ | |||
| #include <ztypes.h> | ||||
| 
 | ||||
| 
 | ||||
| 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); | ||||
|  |  | |||
|  | @ -9,8 +9,8 @@ glcr::ErrorOr<glcr::SharedPtr<Ext2BlockReader>> 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<mmth::OwnedMemoryRegion> 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()) { | ||||
|  |  | |||
|  | @ -59,8 +59,8 @@ GptReader::GptReader(glcr::UniquePtr<DenaliClient> 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()); | ||||
|  |  | |||
|  | @ -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<uint32_t>(0) != kSentinel) { | ||||
|     return glcr::INVALID_RESPONSE; | ||||
|     return glcr::InvalidResponse("Got an invalid response from server."); | ||||
|   } | ||||
| 
 | ||||
|   // Check Response Code.
 | ||||
|   RET_ERR(buffer_.At<uint64_t>(8)); | ||||
| 
 | ||||
| 
 | ||||
|   response.ParseFromBytes(buffer_, 16, cap_buffer_); | ||||
|   yunq::MessageView resp_view(buffer_, 16); | ||||
|   RETURN_ERROR(response.ParseFromBytes(resp_view, cap_buffer_)); | ||||
| 
 | ||||
| 
 | ||||
|   return glcr::OK; | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| // Generated file -- DO NOT MODIFY.
 | ||||
| #include "example.yunq.h" | ||||
| 
 | ||||
| #include <yunq/message_view.h> | ||||
| #include <yunq/serialize.h> | ||||
| 
 | ||||
| 
 | ||||
| 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<uint32_t>(offset + 0, 0xDEADBEEF);  // TODO: Chose a more unique ident sequence.
 | ||||
|   bytes.WriteAt<uint32_t>(offset + 4, core_size); | ||||
|   bytes.WriteAt<uint32_t>(offset + 8, extension_size); | ||||
|   bytes.WriteAt<uint32_t>(offset + 12, 0); // TODO: Calculate CRC32.
 | ||||
|   bytes.WriteAt<uint64_t>(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<ExtPointer>(offset + header_size + (8 * 0)); | ||||
| 
 | ||||
|   set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); | ||||
|   ASSIGN_OR_RETURN(path_, message.ReadField<glcr::String>(0)); | ||||
|   // Parse options.
 | ||||
|   auto options_pointer = bytes.At<ExtPointer>(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<uint64_t>(i)); | ||||
|   } | ||||
|   ASSIGN_OR_RETURN(options_, message.ReadRepeated<uint64_t>(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<ExtPointer>(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<ExtPointer>(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<uint64_t>(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<ExtPointer>(offset + header_size + (8 * 0), path_ptr); | ||||
|   serializer.WriteField<glcr::String>(0, path_); | ||||
|   // Write options.
 | ||||
|   ExtPointer options_ptr{ | ||||
|     .offset = next_extension, | ||||
|     .length = (uint32_t)(options().size() * sizeof(uint64_t)), | ||||
|   }; | ||||
|   serializer.WriteRepeated<uint64_t>(1, options_); | ||||
| 
 | ||||
|   next_extension += options_ptr.length; | ||||
|   bytes.WriteAt<ExtPointer>(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<uint64_t>(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<uint64_t>(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<ExtPointer>(offset + header_size + (8 * 0)); | ||||
| 
 | ||||
|   set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); | ||||
|   ASSIGN_OR_RETURN(path_, message.ReadField<glcr::String>(0)); | ||||
|   // Parse attrs.
 | ||||
|   set_attrs(bytes.At<uint64_t>(offset + header_size + (8 * 1))); | ||||
|   ASSIGN_OR_RETURN(attrs_, message.ReadField<uint64_t>(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<ExtPointer>(offset + header_size + (8 * 0), path_ptr); | ||||
|   // Write attrs.
 | ||||
|   bytes.WriteAt<uint64_t>(offset + header_size + (8 * 1), attrs()); | ||||
|   // Write mem_cap.
 | ||||
|   // FIXME: Implement inbuffer capabilities.
 | ||||
|   bytes.WriteAt<uint64_t>(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<ExtPointer>(offset + header_size + (8 * 0), path_ptr); | ||||
|   serializer.WriteField<glcr::String>(0, path_); | ||||
|   // Write attrs.
 | ||||
|   bytes.WriteAt<uint64_t>(offset + header_size + (8 * 1), attrs()); | ||||
|   serializer.WriteField<uint64_t>(1, attrs_); | ||||
|   // Write mem_cap.
 | ||||
|   caps.WriteAt(next_cap, mem_cap()); | ||||
|   bytes.WriteAt<uint64_t>(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(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,8 +3,11 @@ | |||
| 
 | ||||
| #include <glacier/buffer/byte_buffer.h> | ||||
| #include <glacier/buffer/cap_buffer.h> | ||||
| #include <glacier/status/status.h> | ||||
| #include <glacier/container/vector.h> | ||||
| #include <glacier/string/string.h> | ||||
| #include <yunq/message_view.h> | ||||
| #include <yunq/serialize.h> | ||||
| #include <ztypes.h> | ||||
| 
 | ||||
| 
 | ||||
|  | @ -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<uint64_t> 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; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<glcr::ErrorCode>(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<uint32_t>(0) != kSentinel) { | ||||
|     return glcr::INVALID_ARGUMENT; | ||||
|     return glcr::InvalidArgument("Request Not Valid"); | ||||
|   }  | ||||
|    | ||||
|   uint64_t method_select = request.At<uint64_t>(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(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <glacier/status/error_or.h> | ||||
| #include <glacier/status/status.h> | ||||
| #include <mammoth/proc/thread.h> | ||||
| #include <ztypes.h> | ||||
| 
 | ||||
|  | @ -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); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 %} | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue