Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement serialize #137

Open
wants to merge 4 commits into
base: pz-write-tags
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions ext/liquid_c/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,16 @@ static VALUE block_body_disassemble(VALUE self)
document_body_get_constants_ptr(entry), (const VALUE *)body->tags.data);
}

static VALUE block_body_dump(VALUE self)
{
block_body_t *body;
BlockBody_Get_Struct(self, body);
ensure_body_compiled(body);

return document_body_dump(body->as.compiled.document_body_entry.body,
(uint32_t)body->as.compiled.document_body_entry.buffer_offset);
}


static VALUE block_body_add_evaluate_expression(VALUE self, VALUE expression)
{
Expand Down Expand Up @@ -604,6 +614,7 @@ void liquid_define_block_body()
rb_define_method(cLiquidCBlockBody, "blank?", block_body_blank_p, 0);
rb_define_method(cLiquidCBlockBody, "nodelist", block_body_nodelist, 0);
rb_define_method(cLiquidCBlockBody, "disassemble", block_body_disassemble, 0);
rb_define_method(cLiquidCBlockBody, "dump", block_body_dump, 0);

rb_define_method(cLiquidCBlockBody, "add_evaluate_expression", block_body_add_evaluate_expression, 1);
rb_define_method(cLiquidCBlockBody, "add_find_variable", block_body_add_find_variable, 1);
Expand Down
29 changes: 29 additions & 0 deletions ext/liquid_c/document_body.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,35 @@ void document_body_write_block_body(VALUE self, bool blank, uint32_t render_scor
}
}


VALUE document_body_dump(document_body_t *body, uint32_t entrypoint_block_offset)
{
assert(BUILTIN_TYPE(body->constants) == T_ARRAY);

uint32_t buffer_len = (uint32_t)c_buffer_size(&body->buffer);

VALUE constants = rb_marshal_dump(body->constants, Qnil);
uint32_t constants_len = (uint32_t)RSTRING_LEN(constants);

VALUE str = rb_str_buf_new(sizeof(document_body_header_t) + buffer_len + constants_len);

document_body_header_t header = {
.version = DOCUMENT_BODY_CURRENT_VERSION,
.entrypoint_block_offset = entrypoint_block_offset,
.buffer_offset = sizeof(document_body_header_t),
.buffer_len = buffer_len,
.constants_offset = sizeof(document_body_header_t) + buffer_len,
.constants_len = constants_len
};

rb_str_cat(str, (const char *)&header, sizeof(document_body_header_t));
rb_str_cat(str, (const char *)body->buffer.data, buffer_len);
rb_str_append(str, constants);

return str;
}


void liquid_define_document_body()
{
cLiquidCDocumentBody = rb_define_class_under(mLiquidC, "DocumentBody", rb_cObject);
Expand Down
14 changes: 14 additions & 0 deletions ext/liquid_c/document_body.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ typedef struct document_body {
c_buffer_t buffer;
} document_body_t;

/* Bump this version every time a backwards incompatible change has been made in the serialization headers.
*/
#define DOCUMENT_BODY_CURRENT_VERSION 0

typedef struct document_body_header {
uint32_t version;
uint32_t entrypoint_block_offset;
uint32_t buffer_offset;
uint32_t buffer_len;
uint32_t constants_offset;
uint32_t constants_len;
} document_body_header_t;

typedef struct document_body_entry {
document_body_t *body;
size_t buffer_offset;
Expand All @@ -34,6 +47,7 @@ typedef struct document_body_entry {
void liquid_define_document_body();
VALUE document_body_new_instance();
void document_body_write_block_body(VALUE self, bool blank, uint32_t render_score, vm_assembler_t *code, document_body_entry_t *entry);
VALUE document_body_dump(document_body_t *body, uint32_t entrypoint_block_offset);

static inline void document_body_entry_mark(document_body_entry_t *entry)
{
Expand Down
6 changes: 6 additions & 0 deletions ext/liquid_c/extconf.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# frozen_string_literal: true
require 'mkmf'

# if system endianness == network endianness (big endian)
if [1].pack('I') == [1].pack('N')
raise 'System incompatible with liquid-c, only little endian systems supported'
end

$CFLAGS << ' -std=c11 -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers'
append_cflags('-fvisibility=hidden')
# In Ruby 2.6 and earlier, the Ruby headers did not have struct timespec defined
Expand Down
12 changes: 12 additions & 0 deletions lib/liquid/c.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ def parse(tokenizer, parse_context)
end
end

Liquid::Template.class_eval do
def dump
@root.dump
end
end

Liquid::Document.class_eval do
def dump
@body.dump
end
end

Liquid::Variable.class_eval do
class << self
# @api private
Expand Down