diff --git a/yunq/codegen_message.py b/yunq/codegen_message.py deleted file mode 100644 index 1458486..0000000 --- a/yunq/codegen_message.py +++ /dev/null @@ -1,267 +0,0 @@ - -from parser import * - -HEADER_PRELUDE = """ -// Generated file - DO NOT MODIFY -#pragma once - -#include -#include -#include -#include - -""" - -MESSAGE_CLASS_PREFIX = """ -class {name} {{ - public: - {name}() {{}} - // Delete copy and move until implemented. - {name}(const {name}&) = delete; - {name}({name}&&) = delete; - - void ParseFromBytes(const glcr::ByteBuffer&); - void ParseFromBytes(const glcr::ByteBuffer&, const glcr::CapBuffer&); - void SerializeToBytes(glcr::ByteBuffer&); - void SerializeToBytes(glcr::ByteBuffer&, glcr::CapBuffer&); -""" - -MESSAGE_CLASS_SET_GET = """ - {type} {name}() {{ return {name}_; }} - void set_{name}({type} value) {{ - {name}_ = value; - }} -""" - -MESSAGE_CLASS_PRIVATE = """ - private: -""" - -MESSAGE_CLASS_FIELD = """ - {type} {name}_; -""" - -MESSAGE_CLASS_SUFFIX = """ -}; -""" - -type_to_str = { - Type.U64: "uint64_t", - Type.I64: "int64_t", - Type.STRING: "glcr::String", - Type.CAPABILITY: "z_cap_t", - Type.BYTES: "glcr::Vector" - } - -def _type_str(field_type: Type) -> str: - return type_to_str[field_type] - - -def _generate_message_class(message: Message) -> str: - class_decl = MESSAGE_CLASS_PREFIX.format(name = message.name) - - for field in message.fields: - class_decl += MESSAGE_CLASS_SET_GET.format(name = field.name, type = _type_str(field.type)) - - class_decl += MESSAGE_CLASS_PRIVATE - - for field in message.fields: - class_decl += MESSAGE_CLASS_FIELD.format(name = field.name, type = _type_str(field.type)) - - class_decl += MESSAGE_CLASS_SUFFIX - return class_decl - - -def generate_message_header(ast: list[Decl]) -> str: - header = HEADER_PRELUDE - - for decl in ast: - if type(decl) != Message: - continue - header += _generate_message_class(decl) - - return header - -IMPL_PRELUDE = """ -#include "{file}.h" - -namespace {{ - -const uint64_t header_size = 24; // 4x uint32, 1x uint64 - -struct ExtPointer {{ - uint32_t offset; - 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, uint32_t core_size, uint32_t extension_size) {{ - bytes.WriteAt(0, 0xDEADBEEF); // TODO: Chose a more unique ident sequence. - bytes.WriteAt(4, core_size); - bytes.WriteAt(8, extension_size); - bytes.WriteAt(12, 0); // TODO: Calculate CRC32. - bytes.WriteAt(16, 0); // TODO: Add options. -}} - -}} // namespace -""" - -IMPL_PARSE_DEF = """ -void {name}::ParseFromBytes(const glcr::ByteBuffer& bytes) {{ - CheckHeader(bytes); -""" - -IMPL_PARSE_DEF_CAP = """ -void {name}::ParseFromBytes(const glcr::ByteBuffer& bytes, const glcr::CapBuffer& caps) {{ - CheckHeader(bytes); -""" - -IMPL_PARSE_U64 = """ - set_{name}(bytes.At(header_size + (8 * {offset}))); -""" - -IMPL_PARSE_I64 = """ - set_{name}(bytes.At(header_size + (8 * {offset}))); -""" - -IMPL_PARSE_STRING = """ - auto {name}_pointer = bytes.At(header_size + (8 * {offset})); - - set_{name}(bytes.StringAt({name}_pointer.offset, {name}_pointer.length)); -""" - -IMPL_SET_CAP_EMPTY = """ - set_{name}(0); -""" - -IMPL_PARSE_CAP = """ - uint64_t {name}_ptr = bytes.At(header_size + (8 * {offset})); - - set_{name}(caps.At({name}_ptr)); -""" - -IMPL_PARSE_DEF_END = """ -} -""" - -def _generate_message_parse_impl(message: Message) -> str: - impl = "" - - for with_cap in (False, True): - impl += IMPL_PARSE_DEF.format(name=message.name) if not with_cap else IMPL_PARSE_DEF_CAP.format(name=message.name) - for offset, field in enumerate(message.fields): - if field.type == Type.U64: - impl += IMPL_PARSE_U64.format(name = field.name, offset = offset) - elif field.type == Type.I64: - impl += IMPL_PARSE_I64.format(name = field.name, offset = offset) - elif field.type == Type.STRING: - impl += IMPL_PARSE_STRING.format(name = field.name, offset = offset); - elif field.type == Type.CAPABILITY: - if with_cap: - impl += IMPL_PARSE_CAP.format(name = field.name, offset = offset) - else: - impl += IMPL_SET_CAP_EMPTY.format(name = field.name) - else: - impl += "\n{} unimplemented\n".format(field.type.name) - - impl += IMPL_PARSE_DEF_END - - return impl - -IMPL_SER_DEF = """ -void {name}::SerializeToBytes(glcr::ByteBuffer& bytes) {{ - - uint32_t next_extension = header_size + 8 * {num_fields}; - const uint32_t core_size = next_extension; -""" - -IMPL_SER_CAP_DEF = """ -void {name}::SerializeToBytes(glcr::ByteBuffer& bytes, glcr::CapBuffer& caps) {{ - - uint32_t next_extension = header_size + 8 * {num_fields}; - const uint32_t core_size = next_extension; - uint64_t next_cap = 0; -""" - -IMPL_SER_U64 = """ - bytes.WriteAt(header_size + (8 * {offset}), {name}()); -""" - -IMPL_SER_I64 = """ - bytes.WriteAt(header_size + (8 * {offset}), {name}()); -""" - -IMPL_SER_STRING = """ - ExtPointer {name}_ptr{{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t){name}().length(), - }}; - - bytes.WriteStringAt(next_extension, {name}()); - next_extension += {name}_ptr.length; - - bytes.WriteAt(header_size + (8 * {offset}), {name}_ptr); -""" - -IMPL_SER_CAP_EMPTY = """ - // FIXME: Warn or error on serialization -""" - -IMPL_SER_CAP = """ - caps.WriteAt(next_cap, {name}()); - bytes.WriteAt(header_size + (8 * {offset}), next_cap++); -""" - -IMPL_SER_DEF_END = """ - // The next extension pointer is the length of the message. - WriteHeader(bytes, core_size, next_extension); -} -""" -def _generate_message_serialize_impl(message: Message) -> str: - impl = "" - - for with_cap in (False, True): - if with_cap: - impl += IMPL_SER_CAP_DEF.format(name = message.name, num_fields = len(message.fields)) - else: - impl += IMPL_SER_DEF.format(name = message.name, num_fields = len(message.fields)) - - for offset, field in enumerate(message.fields): - if field.type == Type.U64: - impl += IMPL_SER_U64.format(name = field.name, offset = offset) - elif field.type == Type.I64: - impl += IMPL_SER_I64.format(name = field.name, offset = offset) - elif field.type == Type.STRING: - impl += IMPL_SER_STRING.format(name = field.name, offset = offset) - elif field.type == Type.CAPABILITY: - if with_cap: - impl += IMPL_SER_CAP.format(name = field.name, offset = offset) - else: - impl += IMPL_SER_CAP_EMPTY - else: - impl += "\n{} unimplemented\n".format(field.type.name) - impl += IMPL_SER_DEF_END - - return impl - -def _generate_message_class_impl(message: Message) -> str: - return _generate_message_parse_impl(message) + _generate_message_serialize_impl(message) - - -def generate_message_impl(file: str, ast: list[Decl]) -> str: - impl = IMPL_PRELUDE.format(file=file) - - for decl in ast: - if type(decl) != Message: - continue - impl += _generate_message_class_impl(decl) - - return impl diff --git a/yunq/example.yunq.cpp b/yunq/example.yunq.cpp index f782b1c..afcacc2 100644 --- a/yunq/example.yunq.cpp +++ b/yunq/example.yunq.cpp @@ -1,4 +1,3 @@ - #include "example.yunq.h" namespace { @@ -18,157 +17,95 @@ void CheckHeader(const glcr::ByteBuffer& bytes) { // TODO: Parse options. } -void WriteHeader(glcr::ByteBuffer& bytes, uint32_t core_size, uint32_t extension_size) { - bytes.WriteAt(0, 0xDEADBEEF); // TODO: Chose a more unique ident sequence. - bytes.WriteAt(4, core_size); - bytes.WriteAt(8, extension_size); - bytes.WriteAt(12, 0); // TODO: Calculate CRC32. - bytes.WriteAt(16, 0); // TODO: Add 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) { + + + +void OpenFileRequest::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) { CheckHeader(bytes); - auto path_pointer = bytes.At(header_size + (8 * 0)); - set_path(bytes.StringAt(path_pointer.offset, path_pointer.length)); - set_options(bytes.At(header_size + (8 * 1))); + auto {field.name}_pointer = bytes.At(offset + header_size + (8 * {loop.index})); + + set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); + + + + set_options(bytes.At(offset + header_size + (8 * 2))); + } -void OpenFileRequest::ParseFromBytes(const glcr::ByteBuffer& bytes, const glcr::CapBuffer& caps) { +void {message.name}::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) { CheckHeader(bytes); - auto path_pointer = bytes.At(header_size + (8 * 0)); - set_path(bytes.StringAt(path_pointer.offset, path_pointer.length)); - set_options(bytes.At(header_size + (8 * 1))); + auto {field.name}_pointer = bytes.At(offset + header_size + (8 * {loop.index})); + + set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); + + + + set_options(bytes.At(offset + header_size + (8 * 2))); + } -void OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes) { - uint32_t next_extension = header_size + 8 * 2; - const uint32_t core_size = next_extension; - ExtPointer path_ptr{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t)path().length(), - }; - bytes.WriteStringAt(next_extension, path()); - next_extension += path_ptr.length; - - bytes.WriteAt(header_size + (8 * 0), path_ptr); - - bytes.WriteAt(header_size + (8 * 1), options()); - - // The next extension pointer is the length of the message. - WriteHeader(bytes, core_size, next_extension); -} - -void OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, glcr::CapBuffer& caps) { - - uint32_t next_extension = header_size + 8 * 2; - const uint32_t core_size = next_extension; - uint64_t next_cap = 0; - - ExtPointer path_ptr{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t)path().length(), - }; - - bytes.WriteStringAt(next_extension, path()); - next_extension += path_ptr.length; - - bytes.WriteAt(header_size + (8 * 0), path_ptr); - - bytes.WriteAt(header_size + (8 * 1), options()); - - // The next extension pointer is the length of the message. - WriteHeader(bytes, core_size, next_extension); -} - -void File::ParseFromBytes(const glcr::ByteBuffer& bytes) { +void File::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) { CheckHeader(bytes); - auto path_pointer = bytes.At(header_size + (8 * 0)); - set_path(bytes.StringAt(path_pointer.offset, path_pointer.length)); - set_attrs(bytes.At(header_size + (8 * 1))); + auto {field.name}_pointer = bytes.At(offset + header_size + (8 * {loop.index})); + set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); + + + + set_attrs(bytes.At(offset + header_size + (8 * 2))); + + + + // FIXME: Implement in-buffer capabilities for inprocess serialization. set_mem_cap(0); + } -void File::ParseFromBytes(const glcr::ByteBuffer& bytes, const glcr::CapBuffer& caps) { +void {message.name}::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) { CheckHeader(bytes); - auto path_pointer = bytes.At(header_size + (8 * 0)); - set_path(bytes.StringAt(path_pointer.offset, path_pointer.length)); - set_attrs(bytes.At(header_size + (8 * 1))); + auto {field.name}_pointer = bytes.At(offset + header_size + (8 * {loop.index})); - uint64_t mem_cap_ptr = bytes.At(header_size + (8 * 2)); + set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); + + + + set_attrs(bytes.At(offset + header_size + (8 * 2))); + + + + uint64_t mem_cap_ptr = bytes.At(offset + header_size + (8 * {offset})); set_mem_cap(caps.At(mem_cap_ptr)); + } -void File::SerializeToBytes(glcr::ByteBuffer& bytes) { - uint32_t next_extension = header_size + 8 * 3; - const uint32_t core_size = next_extension; - - ExtPointer path_ptr{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t)path().length(), - }; - - bytes.WriteStringAt(next_extension, path()); - next_extension += path_ptr.length; - - bytes.WriteAt(header_size + (8 * 0), path_ptr); - - bytes.WriteAt(header_size + (8 * 1), attrs()); - - // FIXME: Warn or error on serialization - - // The next extension pointer is the length of the message. - WriteHeader(bytes, core_size, next_extension); -} - -void File::SerializeToBytes(glcr::ByteBuffer& bytes, glcr::CapBuffer& caps) { - - uint32_t next_extension = header_size + 8 * 3; - const uint32_t core_size = next_extension; - uint64_t next_cap = 0; - - ExtPointer path_ptr{ - .offset = next_extension, - // FIXME: Check downcast of str length. - .length = (uint32_t)path().length(), - }; - - bytes.WriteStringAt(next_extension, path()); - next_extension += path_ptr.length; - - bytes.WriteAt(header_size + (8 * 0), path_ptr); - - bytes.WriteAt(header_size + (8 * 1), attrs()); - - caps.WriteAt(next_cap, mem_cap()); - bytes.WriteAt(header_size + (8 * 2), next_cap++); - - // The next extension pointer is the length of the message. - WriteHeader(bytes, core_size, next_extension); -} diff --git a/yunq/example.yunq.h b/yunq/example.yunq.h index 86b6358..73e264b 100644 --- a/yunq/example.yunq.h +++ b/yunq/example.yunq.h @@ -1,4 +1,3 @@ - // Generated file - DO NOT MODIFY #pragma once @@ -8,6 +7,7 @@ #include + class OpenFileRequest { public: OpenFileRequest() {} @@ -15,20 +15,18 @@ class OpenFileRequest { OpenFileRequest(const OpenFileRequest&) = delete; OpenFileRequest(OpenFileRequest&&) = delete; - void ParseFromBytes(const glcr::ByteBuffer&); - void ParseFromBytes(const glcr::ByteBuffer&, const glcr::CapBuffer&); - void SerializeToBytes(glcr::ByteBuffer&); - void SerializeToBytes(glcr::ByteBuffer&, glcr::CapBuffer&); + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&); + glcr::String path() { return path_; } - void set_path(glcr::String value) { - path_ = value; - } + void set_path(const glcr::String& value) { path_ = value; } uint64_t options() { return options_; } - void set_options(uint64_t value) { - options_ = value; - } + void set_options(const uint64_t& value) { options_ = value; } + private: @@ -36,7 +34,8 @@ class OpenFileRequest { uint64_t options_; -}; + +} class File { public: @@ -45,25 +44,21 @@ class File { File(const File&) = delete; File(File&&) = delete; - void ParseFromBytes(const glcr::ByteBuffer&); - void ParseFromBytes(const glcr::ByteBuffer&, const glcr::CapBuffer&); - void SerializeToBytes(glcr::ByteBuffer&); - void SerializeToBytes(glcr::ByteBuffer&, glcr::CapBuffer&); + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&); + glcr::String path() { return path_; } - void set_path(glcr::String value) { - path_ = value; - } + void set_path(const glcr::String& value) { path_ = value; } uint64_t attrs() { return attrs_; } - void set_attrs(uint64_t value) { - attrs_ = value; - } + void set_attrs(const uint64_t& value) { attrs_ = value; } z_cap_t mem_cap() { return mem_cap_; } - void set_mem_cap(z_cap_t value) { - mem_cap_ = value; - } + void set_mem_cap(const z_cap_t& value) { mem_cap_ = value; } + private: @@ -73,4 +68,5 @@ class File { z_cap_t mem_cap_; -}; + +} diff --git a/yunq/message.cpp.jinja b/yunq/message.cpp.jinja new file mode 100644 index 0000000..4293708 --- /dev/null +++ b/yunq/message.cpp.jinja @@ -0,0 +1,147 @@ +// Generated file -- DO NOT MODIFY. +#include "{{file}}.h" + +namespace { + +const uint64_t header_size = 24; // 4x uint32, 1x uint64 + +struct ExtPointer { + uint32_t offset; + 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 + +{%- for message in messages %} +void {{message.name}}::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) { + CheckHeader(bytes); + +{%- for field in message.fields %} + // Parse {{field.name}}. +{%- if field.type == Type.U64 %} + set_{{field.name}}(bytes.At(offset + header_size + (8 * {{loop.index0}}))); +{%- elif field.type == Type.I64 %} + set_{{field.name}}(bytes.At(offset + header_size + (8 * {{loop.index0}}))); +{%- elif field.type == Type.STRING %} + auto {{field.name}}_pointer = bytes.At(offset + header_size + (8 * {{loop.index0}})); + + set_{{field.name}}(bytes.StringAt(offset + {{field.name}}_pointer.offset, {{field.name}}_pointer.length)); +{%- elif field.type == Type.CAPABILITY %} + // FIXME: Implement in-buffer capabilities for inprocess serialization. + set_{{field.name}}(0); +{%- else %} + // TODO: Unimplemented parsing {{field.type}} +{%- endif %} +{%- endfor %} +} + +void {{message.name}}::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) { + CheckHeader(bytes); + +{%- for field in message.fields %} + // Parse {{field.name}}. +{%- if field.type == Type.U64 %} + set_{{field.name}}(bytes.At(offset + header_size + (8 * {{loop.index0}}))); +{%- elif field.type == Type.I64 %} + set_{{field.name}}(bytes.At(offset + header_size + (8 * {{loop.index0}}))); +{%- elif field.type == Type.STRING %} + auto {{field.name}}_pointer = bytes.At(offset + header_size + (8 * {{loop.index0}})); + + set_{{field.name}}(bytes.StringAt(offset + {{field.name}}_pointer.offset, {{field.name}}_pointer.length)); +{%- elif field.type == Type.CAPABILITY %} + uint64_t {{field.name}}_ptr = bytes.At(offset + header_size + (8 * {{loop.index0}})); + + set_{{field.name}}(caps.At({{field.name}}_ptr)); +{%- else %} + // TODO: Unimplemented parsing {{field.type}} +{%- endif %} +{%- endfor %} +} + +uint64_t {{message.name}}::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) { + uint32_t next_extension = header_size + 8 * {{ message.fields | length }}; + const uint32_t core_size = next_extension; + +{%- for field in message.fields %} + // Write {{field.name}}. +{%- if field.type == Type.U64 %} + bytes.WriteAt(offset + header_size + (8 * {{loop.index0}}), {{field.name}}()); +{%- elif field.type == Type.I64 %} + bytes.WriteAt(offset + header_size + (8 * {{loop.index0}}), {{field.name}}()); +{%- elif field.type == Type.STRING %} + ExtPointer {{field.name}}_ptr{ + .offset = next_extension, + // FIXME: Check downcast of str length. + .length = (uint32_t){{field.name}}().length(), + }; + + bytes.WriteStringAt(offset + next_extension, {{field.name}}()); + next_extension += {{field.name}}_ptr.length; + + bytes.WriteAt(offset + header_size + (8 * {{loop.index0}}), {{field.name}}_ptr); +{%- elif field.type == Type.CAPABILITY %} + // FIXME: Implement inbuffer capabilities. + bytes.WriteAt(offset + header_size + (8 * {{loop.index0}}), 0); +{%- else %} + // TODO: Unimplemented serialization {{field.type}} +{%- endif %} +{%- endfor %} + + // The next extension pointer is the length of the message. + WriteHeader(bytes, offset, core_size, next_extension); + + return next_extension; +} + +uint64_t {{message.name}}::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) { + uint32_t next_extension = header_size + 8 * {{ message.fields | length}}; + const uint32_t core_size = next_extension; + uint64_t next_cap = 0; + +{%- for field in message.fields %} + // Write {{field.name}}. +{%- if field.type == Type.U64 %} + bytes.WriteAt(offset + header_size + (8 * {{loop.index0}}), {{field.name}}()); +{%- elif field.type == Type.I64 %} + bytes.WriteAt(offset + header_size + (8 * {{loop.index0}}), {{field.name}}()); +{%- elif field.type == Type.STRING %} + ExtPointer {{field.name}}_ptr{ + .offset = next_extension, + // FIXME: Check downcast of str length. + .length = (uint32_t){{field.name}}().length(), + }; + + bytes.WriteStringAt(offset + next_extension, {{field.name}}()); + next_extension += {{field.name}}_ptr.length; + + bytes.WriteAt(offset + header_size + (8 * {{loop.index0}}), {{field.name}}_ptr); +{%- elif field.type == Type.CAPABILITY %} + caps.WriteAt(next_cap, {{field.name}}()); + bytes.WriteAt(offset + header_size + (8 * {{loop.index0}}), next_cap++); +{%- else %} + // TODO: Unimplemented serialization {{field.type}} +{%- endif %} +{%- endfor %} + + // The next extension pointer is the length of the message. + WriteHeader(bytes, offset, core_size, next_extension); + + return next_extension; +} +{%- endfor %} diff --git a/yunq/message.h.jinja b/yunq/message.h.jinja new file mode 100644 index 0000000..bf684be --- /dev/null +++ b/yunq/message.h.jinja @@ -0,0 +1,34 @@ +// Generated file - DO NOT MODIFY +#pragma once + +#include +#include +#include +#include + + +{%- for message in messages %} +class {{message.name}} { + public: + {{message.name}}() {} + // Delete copy and move until implemented. + {{message.name}}(const {{message.name}}&) = delete; + {{message.name}}({{message.name}}&&) = delete; + + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&); + +{%- for field in message.fields %} + {{field.cpp_type()}} {{field.name}}() { return {{field.name}}_; } + void set_{{field.name}}(const {{field.cpp_type()}}& value) { {{field.name}}_ = value; } +{%- endfor %} + + private: +{%- for field in message.fields %} + {{field.cpp_type()}} {{field.name}}_; +{%- endfor %} + +}; +{%- endfor %} diff --git a/yunq/parser.py b/yunq/parser.py index 8d90af2..9e9e64d 100644 --- a/yunq/parser.py +++ b/yunq/parser.py @@ -102,11 +102,22 @@ type_str_dict = { "capability": Type.CAPABILITY, } +type_to_cppstr = { + Type.U64: "uint64_t", + Type.I64: "int64_t", + Type.STRING: "glcr::String", + Type.CAPABILITY: "z_cap_t", + Type.BYTES: "glcr::Vector" + } + class Field(): def __init__(self, fieldtype: Type, name: str): self.type = fieldtype self.name = name + def cpp_type(self): + return type_to_cppstr[self.type] + class Message(): def __init__(self, name: str, fields: list[Field]): self.name = name diff --git a/yunq/requirements.txt b/yunq/requirements.txt new file mode 100644 index 0000000..e6bb872 --- /dev/null +++ b/yunq/requirements.txt @@ -0,0 +1 @@ +jinja2==3.1 diff --git a/yunq/yunq.py b/yunq/yunq.py index a74f2e7..de09d55 100755 --- a/yunq/yunq.py +++ b/yunq/yunq.py @@ -1,8 +1,10 @@ -#! /usr/bin/python +#! python3 import os +import pathlib import sys -from codegen_message import * +from jinja2 import Environment, FileSystemLoader + from parser import * def main(): @@ -20,11 +22,22 @@ def main(): ast = parser.parse() type_check(ast) + messages = [m for m in ast if type(m) is Message] + interfaces = [i for i in ast if type(i) is Interface] + jinja_env = Environment(loader=FileSystemLoader(pathlib.Path(__file__).parent.resolve())) + + message_header_tmpl = jinja_env.get_template("message.h.jinja") with open(filename + '.h', mode='w') as f: - f.write(generate_message_header(ast)) + message_header = message_header_tmpl.render(messages=messages) + f.write(message_header) + + message_impl_tmpl = jinja_env.get_template("message.cpp.jinja") + message_impl_tmpl.globals['Type'] = Type with open(filename + '.cpp', mode='w') as f: - f.write(generate_message_impl(filename, ast)) + message_impl = message_impl_tmpl.render(file=filename, messages=messages) + f.write(message_impl) + if __name__ == "__main__": main()