///|
fn CodeGenerator::oneof_shape(
self : CodeGenerator,
message : Message,
oneof : OneOf,
) -> OneofShape raise {
let message_name = message.import_path.path() |> to_camel_case
let fields = []
for field in oneof.field {
let field_shape : OneofFieldShape = {
constructor_name: field.import_path.name() |> to_camel_case,
json_name: field.json_name.unwrap(),
value_type: self.get_moonbit_type(field, parent_path=message.import_path),
value: self.field_codec_value(field, message.import_path),
envelope: self.field_envelope_shape(field),
}
fields.push(field_shape)
}
{
field_name: oneof.import_path.name() |> pascal_to_snake,
enum_name: "\{message_name}_\{to_camel_case(oneof.import_path.name())}",
fields,
}
}
///|
fn CodeGenerator::gen_oneof_codec_read(
_ : CodeGenerator,
shape : OneofShape,
content : StringBuilder,
is_async? : Bool = false,
) -> Unit raise {
for field in shape.fields {
content.write_string(
" (\{field.envelope.field_number}, \{field.envelope.read_wire_pattern(field.value)}) => msg.\{shape.field_name} = \{field.value.read_expr(field.envelope, is_async~)} |> \{shape.enum_name}::\{field.constructor_name}\n",
)
}
}
///|
fn CodeGenerator::gen_oneof_codec_write(
_ : CodeGenerator,
shape : OneofShape,
content : StringBuilder,
is_async? : Bool = false,
) -> Unit raise {
let async_keyword = if is_async { "async" } else { "" }
let async_keyword_to_snake = async_keyword |> pascal_to_snake
content.write_string(" match self.\{shape.field_name} {\n")
for field in shape.fields {
let field_write = field.value.write_expr(field.envelope, "v", is_async~)
content.write_string(
" \{shape.enum_name}::\{field.constructor_name}(v) => {\n",
)
if !field.envelope.writes_own_field_tags() {
content.write_string(
" writer |> @lib.\{async_keyword_to_snake}write_varint(\{field.envelope.tag_value()}UL)\n",
)
}
content.write_string(" \{field_write}\n")
content.write_string(" }\n")
}
content.write_string(
(
$| \{shape.enum_name}::NotSet => ()
$| }
$|
),
)
}
///|
fn CodeGenerator::gen_oneof_codec_size(
_ : CodeGenerator,
shape : OneofShape,
content : StringBuilder,
) -> Unit {
content.write_string(" match self.\{shape.field_name} {\n")
for field in shape.fields {
let (delta_size, need_v) = field.value.field_size_expr(field.envelope, "v")
let value_binding = if need_v { "v" } else { "_" }
content.write_string(
(
$| \{field.constructor_name}(\{value_binding}) => { size += \{delta_size} }
$|
),
)
}
content.write_string(
(
#| NotSet => ()
#| }
#|
),
)
}
///|
fn CodeGenerator::gen_oneof_json_to(
_ : CodeGenerator,
shape : OneofShape,
content : StringBuilder,
) -> Unit {
content.write_string(
(
$| match self.\{shape.field_name} {
$| NotSet => ()
$|
),
)
for field in shape.fields {
content.write_string(
" \{field.constructor_name}(v) => json[\"\{field.json_name}\"] = ToJson::to_json(v)\n",
)
}
content.write_string(" }\n")
}
///|
fn CodeGenerator::gen_oneof_json_from(
_ : CodeGenerator,
shape : OneofShape,
content : StringBuilder,
) -> Unit {
for field in shape.fields {
content.write_string(
" (\"\{field.json_name}\", value) => message.\{shape.field_name} = @json.from_json(value, path~)\n",
)
}
}