{#--- Begin #} function {{struct.name}}(values) { this.initDefaults_(); this.initFields_(values); } {#--- Enums #} {%- from "enum_definition.tmpl" import enum_def %} {% for enum in struct.enums %} {{enum_def("%s.%s"|format(struct.name, enum.name), enum)}} {%- endfor %} {#--- Constants #} {% for constant in struct.constants %} {{struct.name}}.{{constant.name}} = {{constant.value|expression_to_text}}; {%- endfor %} {#--- initDefaults() #} {{struct.name}}.prototype.initDefaults_ = function() { {%- for packed_field in struct.packed.packed_fields %} this.{{packed_field.field.name}} = {{packed_field.field|default_value}}; {%- endfor %} }; {#--- initFields() #} {{struct.name}}.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; {#--- Fuzzing #} {%- if generate_fuzzing %} {%- from "fuzzing.tmpl" import generate_or_mutate %} {{struct.name}}.generate = function(generator_) { var generated = new {{struct.name}}; {%- for field in struct.fields %} generated.{{field.name}} = {{generate_or_mutate('generator_', 'generate', field.kind)|indent(4)}}; {%- endfor %} return generated; }; {{struct.name}}.prototype.mutate = function(mutator_) { {%- for field in struct.fields %} if (mutator_.chooseMutateField()) { this.{{field.name}} = {{generate_or_mutate('mutator_', 'mutate', field.kind, 'this.' ~ field.name)|indent(6)}}; } {%- endfor %} return this; }; {%- from "fuzzing.tmpl" import get_handle_deps %} {{struct.name}}.prototype.getHandleDeps = function() { var handles = []; {%- for field in struct.fields %} {%- if field.kind|contains_handles_or_interfaces %} if (this.{{field.name}} !== null) { Array.prototype.push.apply(handles, {{get_handle_deps(field.kind, 'this.' ~ field.name)|indent(6)}}); } {%- endif %} {%- endfor %} return handles; }; {{struct.name}}.prototype.setHandles = function() { this.setHandlesInternal_(arguments, 0); }; {%- from "fuzzing.tmpl" import set_handles %} {{struct.name}}.prototype.setHandlesInternal_ = function(handles, idx) { {%- for field in struct.fields %} {%- if field.kind|contains_handles_or_interfaces %} {{set_handles(field.kind, 'this.' ~ field.name)|indent(4)}}; {%- endif %} {%- endfor %} return idx; }; {%- endif %} {#--- Validation #} {{struct.name}}.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {%- for version in struct.versions %} {version: {{version.version}}, numBytes: {{version.num_bytes}}}{% if not loop.last %}, {%- endif -%} {% endfor %} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; {#- Before validating fields introduced at a certain version, we need to add a version check, which makes sure we skip further validation if |object| is from an earlier version. |last_checked_version| records the last version that we have added such version check. #} {%- from "validation_macros.tmpl" import validate_struct_field %} {%- set last_checked_version = 0 %} {%- for packed_field in struct.packed.packed_fields_in_ordinal_order %} {%- set offset = packed_field|field_offset %} {%- set field = packed_field.field %} {%- set name = struct.name ~ '.' ~ field.name %} {% if field.kind|is_object_kind or field.kind|is_any_handle_or_interface_kind or field.kind|is_enum_kind %} {% if packed_field.min_version > last_checked_version %} {% set last_checked_version = packed_field.min_version %} // version check {{name}} if (!messageValidator.isFieldInStructVersion(offset, {{packed_field.min_version}})) return validator.validationError.NONE; {%- endif -%} {{validate_struct_field(field, offset, name)|indent(4)}} {%- endif %} {%- endfor %} return validator.validationError.NONE; }; {#--- Encoding and decoding #} {{struct.name}}.encodedSize = codec.kStructHeaderSize + {{struct.packed|payload_size}}; {{struct.name}}.decode = function(decoder) { var packed; var val = new {{struct.name}}(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); {%- for byte in struct.bytes %} {%- if byte.packed_fields|length >= 1 and byte.packed_fields[0].field.kind|is_bool_kind %} packed = decoder.readUint8(); {%- for packed_field in byte.packed_fields %} val.{{packed_field.field.name}} = (packed >> {{packed_field.bit}}) & 1 ? true : false; {%- endfor %} {%- else %} {%- for packed_field in byte.packed_fields %} val.{{packed_field.field.name}} = decoder.{{packed_field.field.kind|decode_snippet}}; {%- endfor %} {%- endif %} {%- if byte.is_padding %} decoder.skip(1); {%- endif %} {%- endfor %} return val; }; {{struct.name}}.encode = function(encoder, val) { var packed; encoder.writeUint32({{struct.name}}.encodedSize); encoder.writeUint32({{struct.versions[-1].version}}); {%- for byte in struct.bytes %} {%- if byte.packed_fields|length >= 1 and byte.packed_fields[0].field.kind|is_bool_kind %} packed = 0; {%- for packed_field in byte.packed_fields %} packed |= (val.{{packed_field.field.name}} & 1) << {{packed_field.bit}} {%- endfor %} encoder.writeUint8(packed); {%- else %} {%- for packed_field in byte.packed_fields %} encoder.{{packed_field.field.kind|encode_snippet}}val.{{packed_field.field.name}}); {%- endfor %} {%- endif %} {%- if byte.is_padding %} encoder.skip(1); {%- endif %} {%- endfor %} };