export type {{ident}} = {%- let type_variant = ident.clone() %} {%- for variant in variants -%} {%- match variant -%} {%- when EnumVariantDeclaration::Unit with { ident, value } %} | { tag: '{{ident}}' } {%- when EnumVariantDeclaration::Unnamed with { ident, types } %} {%- if types.len() == 1 %} | { tag: '{{ident}}'; value: {{ variant.first_type().ts_type() }} } {%- else %} | { tag: '{{ident}}'; value: {{type_variant}}_{{ident}} } {%- endif -%} {%- when EnumVariantDeclaration::Named with { ident, types } %} | { tag: '{{ident}}'; value: {{type_variant}}_{{ident}} } {%- endmatch -%} {% endfor -%} ; {%- for variant in variants -%} {%- match variant -%} {%- when EnumVariantDeclaration::Unnamed with { ident, types } -%} {%- if types.len() > 1 %} export interface {{type_variant}}_{{ident}} { {%- for ty in types %} {{ loop.index - 1 }}: {{ ty.ts_type() }}; {%- endfor %} } {% endif -%} {%- when EnumVariantDeclaration::Named with { ident, types } %} export interface {{type_variant}}_{{ident}} { {%- for (id, ty) in types %} {{ id }}: {{ ty.ts_type() }}; {%- endfor %} } {% else %} {%- endmatch -%} {% endfor %} export module {{ident}} { {%- for variant in variants -%} {%- match variant -%} {%- when EnumVariantDeclaration::Unit with { ident, value } %} export const {{ident}}: {{type_variant}} = { tag: '{{ident}}' }; {%- when EnumVariantDeclaration::Unnamed with { ident, types } %} {%- if types.len() == 1 %} export const {{ident}} = (value: {{ variant.first_type().ts_type() }}): {{type_variant}} => ({ tag: '{{ident}}', value }); {%- else %} export const {{ident}} = ( {%- for ty in types -%} p{{loop.index - 1}}: {{ ty.ts_type() }}, {%- endfor -%} ): {{type_variant}} => ({ tag: '{{ident}}', value: [ {%- for ty in types -%} p{{loop.index - 1}}, {%- endfor -%} ] }); {%- endif -%} {%- when EnumVariantDeclaration::Named with { ident, types } %} export const {{ident}} = (value: {{type_variant}}_{{ident}}): {{type_variant}} => ({ tag: '{{ident}}', value }); {%- endmatch -%} {% endfor %} } export function write{{ident}}(value: {{ident}}, sinkOrBuf?: SinkOrBuf): Sink { const sink = Sink.create(sinkOrBuf); switch(value.tag) { {%- for variant in variants %} {%- let i = loop.index %} case '{{variant.ident()}}': writeU32({{loop.index - 1}}, sink); {%- match variant -%} {%- when EnumVariantDeclaration::Unit with { ident, value } %} {%- when EnumVariantDeclaration::Unnamed with { ident, types } %} {%- if types.len() == 1 %} const val{{i}} = value as { value: {{ variant.first_type().ts_type() }} }; {{ variant.first_type().writer() }}(val{{i}}.value, sink); {%- else %} const val{{i}} = value as { value: {{type_variant}}_{{ident}} }; {%- for ty in types %} {{ ty.writer() }}(val{{i}}.value[{{loop.index -1}}], sink); {%- endfor %} {%- endif -%} {%- when EnumVariantDeclaration::Named with { ident, types } %} const val{{i}} = value as { value: {{type_variant}}_{{ident}} }; {%- for (id, ty) in types %} {{ ty.writer() }}(val{{i}}.value.{{id}}, sink); {%- endfor -%} {%- endmatch %} break; {%- endfor %} default: throw new Error(`'${(value as any).tag}' is invalid tag for enum '{{ident}}'`); } return sink; } export function read{{ident}}(sinkOrBuf: SinkOrBuf): {{ident}} { const sink = Sink.create(sinkOrBuf); const value = readU32(sink); switch (value) { {%- for variant in variants %} case {{loop.index - 1}}: {%- match variant -%} {%- when EnumVariantDeclaration::Unit with { ident, value } %} return {{type_variant}}.{{ident}}; {%- when EnumVariantDeclaration::Unnamed with { ident, types } %} return {{type_variant}}.{{ident}}( {%- for ty in types %} {{ ty.reader() }}(sink), {%- endfor %} ); {%- when EnumVariantDeclaration::Named with { ident, types } %} return {{type_variant}}.{{ident}}({ {%- for (id, ty) in types %} {{ id }}: {{ ty.reader() }}(sink), {%- endfor %} }); {%- endmatch -%} {%- endfor %} default: throw new Error(`'${value}' is invalid value for enum '{{ident}}'`); } }