[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