[Yunq] Add support for empty requests and responses.

This commit is contained in:
Drew Galbraith 2023-11-27 08:03:12 -08:00
parent 6d108f6965
commit cc4b5bd811
11 changed files with 91 additions and 22 deletions

View File

@ -8,7 +8,13 @@
{% for interface in interfaces %}
{% for method in interface.methods %}
{% if method.request == None %}
glcr::ErrorCode {{interface.name}}Client::{{method.name}}({{method.response}}& response) {
{% elif method.response == None %}
glcr::ErrorCode {{interface.name}}Client::{{method.name}}(const {{method.request}}& request) {
{% else %}
glcr::ErrorCode {{interface.name}}Client::{{method.name}}(const {{method.request}}& request, {{method.response}}& response) {
{% endif %}
uint64_t buffer_size = kBufferSize;
uint64_t cap_size = kCapBufferSize;
@ -17,7 +23,12 @@ glcr::ErrorCode {{interface.name}}Client::{{method.name}}(const {{method.request
buffer_.WriteAt<uint64_t>(8, {{loop.index0}});
cap_buffer_.Reset();
{% if method.request == None %}
uint64_t length = 0;
{% else %}
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
{% endif %}
buffer_.WriteAt<uint32_t>(4, 16 + length);
z_cap_t reply_port_cap;
@ -33,7 +44,9 @@ glcr::ErrorCode {{interface.name}}Client::{{method.name}}(const {{method.request
// Check Response Code.
RET_ERR(buffer_.At<uint64_t>(8));
{% if method.response != None %}
response.ParseFromBytes(buffer_, 16, cap_buffer_);
{% endif %}
return glcr::OK;
}

View File

@ -18,7 +18,13 @@ class {{interface.name}}Client {
z_cap_t Capability() { return endpoint_; }
{% for method in interface.methods %}
{% if method.request == None %}
[[nodiscard]] glcr::ErrorCode {{method.name}}({{method.response}}& response);
{% elif method.response == None %}
[[nodiscard]] glcr::ErrorCode {{method.name}}(const {{method.request}}& request);
{% else %}
[[nodiscard]] glcr::ErrorCode {{method.name}}(const {{method.request}}& request, {{method.response}}& response);
{% endif %}
{% endfor %}
private:
z_cap_t endpoint_;

View File

@ -8,7 +8,9 @@
glcr::ErrorCode VFSClient::open(const OpenFileRequest& request, File& response) {
uint64_t buffer_size = kBufferSize;
uint64_t cap_size = kCapBufferSize;
@ -17,7 +19,10 @@ glcr::ErrorCode VFSClient::open(const OpenFileRequest& request, File& response)
buffer_.WriteAt<uint64_t>(8, 0);
cap_buffer_.Reset();
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
buffer_.WriteAt<uint32_t>(4, 16 + length);
z_cap_t reply_port_cap;
@ -33,8 +38,10 @@ glcr::ErrorCode VFSClient::open(const OpenFileRequest& request, File& response)
// Check Response Code.
RET_ERR(buffer_.At<uint64_t>(8));
response.ParseFromBytes(buffer_, 16, cap_buffer_);
return glcr::OK;
}

View File

@ -17,7 +17,9 @@ class VFSClient {
z_cap_t Capability() { return endpoint_; }
[[nodiscard]] glcr::ErrorCode open(const OpenFileRequest& request, File& response);
private:
z_cap_t endpoint_;

View File

@ -44,9 +44,9 @@ void OpenFileRequest::ParseFromBytesInternal(const glcr::ByteBuffer& bytes, uint
// Parse options.
auto options_pointer = bytes.At<ExtPointer>(offset + header_size + (8 * 1));
options_.Resize(options_pointer.length);
options_.Resize(options_pointer.length / sizeof(uint64_t));
for (uint64_t i = offset + options_pointer.offset;
i < offset + options_pointer.offset + (sizeof(uint64_t) * options_pointer.length);
i < offset + options_pointer.offset + options_pointer.length;
i += sizeof(uint64_t)) {
options_.PushBack(bytes.At<uint64_t>(i));
}

View File

@ -17,7 +17,7 @@ class OpenFileRequest {
void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&);
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
glcr::String path() const { return path_; }
const glcr::String& path() const { return path_; }
void set_path(const glcr::String& value) { path_ = value; }
const glcr::Vector<uint64_t>& options() const { return options_; }
void add_options(const uint64_t& value) { options_.PushBack(value); }
@ -40,11 +40,11 @@ class File {
void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&);
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
glcr::String path() const { return path_; }
const glcr::String& path() const { return path_; }
void set_path(const glcr::String& value) { path_ = value; }
uint64_t attrs() const { return attrs_; }
const uint64_t& attrs() const { return attrs_; }
void set_attrs(const uint64_t& value) { attrs_ = value; }
z_cap_t mem_cap() const { return mem_cap_; }
const z_cap_t& mem_cap() const { return mem_cap_; }
void set_mem_cap(const z_cap_t& value) { mem_cap_ = value; }
private:

View File

@ -1,7 +1,7 @@
// Generated file -- DO NOT MODIFY.
#include "example.yunq.server.h"
#include <mammoth/debug.h>
#include <mammoth/util/debug.h>
#include <zcall.h>
namespace {
@ -87,12 +87,19 @@ glcr::ErrorCode VFSServerBase::HandleRequest(const glcr::ByteBuffer& request,
switch(method_select) {
case 0: {
OpenFileRequest yunq_request;
File yunq_response;
yunq_request.ParseFromBytes(request, kHeaderSize, req_caps);
File yunq_response;
RET_ERR(Handleopen(yunq_request, yunq_response));
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
break;

View File

@ -2,7 +2,7 @@
#pragma once
#include <glacier/status/error_or.h>
#include <mammoth/thread.h>
#include <mammoth/proc/thread.h>
#include <ztypes.h>
#include "example.yunq.h"
@ -21,9 +21,11 @@ class VFSServerBase {
[[nodiscard]] Thread RunServer();
[[nodiscard]] virtual glcr::ErrorCode Handleopen(const OpenFileRequest&, File&) = 0;
private:
z_cap_t endpoint_;

View File

@ -211,13 +211,20 @@ class Parser():
self.consume_check(LexemeType.LEFT_PAREN)
request = self.consume_identifier()
request = None
# FIXME: Fix error handling here (and for response). We want to show
# "expected rparen or identifier" if type is wrong rather than just
# "expected rparen".
if self.peektype() == LexemeType.NAME:
request = self.consume_identifier()
self.consume_check(LexemeType.RIGHT_PAREN)
self.consume_check(LexemeType.ARROW)
self.consume_check(LexemeType.LEFT_PAREN)
response = self.consume_identifier()
response = None
if self.peektype() == LexemeType.NAME:
response = self.consume_identifier()
self.consume_check(LexemeType.RIGHT_PAREN)
self.consume_check(LexemeType.SEMICOLON)
@ -269,14 +276,18 @@ def type_check(decls: list[Decl]):
for decl in decls:
if type(decl) is Interface:
for method in decl.methods:
if method.request not in name_dict.keys():
sys.exit("Request type '%s' for '%s.%s' does not exist" % (method.request, decl.name, method.name))
if type(name_dict[method.request]) is not Message:
sys.exit("Request type '%s' for '%s.%s' should be a message" % (method.request, decl.name, method.name))
if method.response not in name_dict.keys():
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))
if method.request is None and method.response is None:
sys.exit("Method '%s.%s' cannot have empty request and response" % (decl.name, method.name))
if method.request is not None:
if method.request not in name_dict.keys():
sys.exit("Request type '%s' for '%s.%s' does not exist" % (method.request, decl.name, method.name))
if type(name_dict[method.request]) is not Message:
sys.exit("Request type '%s' for '%s.%s' should be a message" % (method.request, decl.name, method.name))
if method.response is not None:
if method.response not in name_dict.keys():
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))
def print_ast(decls: list[Decl]):
for decl in decls:

View File

@ -88,14 +88,29 @@ glcr::ErrorCode {{interface.name}}ServerBase::HandleRequest(const glcr::ByteBuff
switch(method_select) {
{%- for method in interface.methods %}
case {{loop.index0}}: {
{% if method.request != None %}
{{method.request}} yunq_request;
{{method.response}} yunq_response;
yunq_request.ParseFromBytes(request, kHeaderSize, req_caps);
{% endif %}
{% if method.response != None %}
{{method.response}} yunq_response;
{% endif %}
{% if method.request == None %}
RET_ERR(Handle{{method.name}}(yunq_response));
{% elif method.response == None %}
RET_ERR(Handle{{method.name}}(yunq_request));
{% else %}
RET_ERR(Handle{{method.name}}(yunq_request, yunq_response));
{% endif %}
{% if method.response != None %}
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
{% else %}
resp_length = 0;
{% endif %}
break;
}
{%- endfor %}

View File

@ -21,7 +21,13 @@ class {{interface.name}}ServerBase {
[[nodiscard]] Thread RunServer();
{% for method in interface.methods %}
{% if method.request == None %}
[[nodiscard]] virtual glcr::ErrorCode Handle{{method.name}}({{method.response}}&) = 0;
{% elif method.response == None %}
[[nodiscard]] virtual glcr::ErrorCode Handle{{method.name}}(const {{method.request}}&) = 0;
{% else %}
[[nodiscard]] virtual glcr::ErrorCode Handle{{method.name}}(const {{method.request}}&, {{method.response}}&) = 0;
{% endif %}
{% endfor %}
private: