impl<T, U> {{ m.trait_ident }} for ::puroro::Either<T, U>
where
    T: {{ m.trait_ident }},
    U: {{ m.trait_ident }},
{
    {%- for f in m.fields_and_oneof_fields %}

    {%- if f.is_message %}
    type {{ f.ident_camel_unesc }}MessageType<'this> = ::puroro::Either<
        <T as {{ m.trait_ident }}>::{{ f.ident_camel_unesc }}MessageType<'this>,
        <U as {{ m.trait_ident }}>::{{ f.ident_camel_unesc }}MessageType<'this>,
    > where Self: 'this;
    {%- endif %}

    {%- if f.is_repeated %}

    {%- let either_repeated_field_type %}
    {%- if f.is_message %}
    {%- let either_repeated_field_type = "EitherRepeatedMessageField" %}
    {%- else %}
    {%- let either_repeated_field_type = "EitherRepeatedField" %}
    {%- endif %}
    type {{ f.ident_camel_unesc }}RepeatedType<'this>
        = ::puroro::internal::impls::either::{{ either_repeated_field_type }}<
            <T as {{ m.trait_ident }}>::{{ f.ident_camel_unesc }}RepeatedType<'this>,
            <U as {{ m.trait_ident }}>::{{ f.ident_camel_unesc }}RepeatedType<'this>,
        > where Self: 'this;

    fn {{ f.ident }}<'this>(&'this self) -> Self::{{ f.ident_camel_unesc }}RepeatedType<'this>
    {
        ::puroro::internal::impls::either::{{ either_repeated_field_type }}::new(self
            .as_ref()
            .map_left(
                |t| <T as {{ m.trait_ident }}>::{{ f.ident }}(t)
            )
            .map_right(
                |u| <U as {{ m.trait_ident }}>::{{ f.ident }}(u)
            )
        )
    }

    {%- else %} {#- if f.is_repeated #}

    {%- if !f.is_explicit_oneof_field %}
    fn {{ f.ident_unesc }}_opt<'this>(&'this self) -> ::std::option::Option<{{ f.trait_scalar_getter_type }}>
    {
        {%- if f.is_message %}
        self.as_ref().either(
            |t| <T as {{ m.trait_ident }}>::{{ f.ident_unesc }}_opt(t).map(
                |t| ::puroro::Either::Left(t)
            ),
            |u| <U as {{ m.trait_ident }}>::{{ f.ident_unesc }}_opt(u).map(
                |u| ::puroro::Either::Right(u)
            ),
        )
        {%- else %}
        self.as_ref().either(
            |t| <T as {{ m.trait_ident }}>::{{ f.ident_unesc }}_opt(t),
            |u| <U as {{ m.trait_ident }}>::{{ f.ident_unesc }}_opt(u),
        )
        {%- endif %}
    }
    {%- endif %}

    {%- endif %} {#- if f.is_repeated #}

    {%- endfor %} {#- for f in m.fields_and_oneof_fields #}
}
