
{#-#############################################}
{#-################ Struct body ################}
{#-#############################################}
pub struct {{ m.bumpalo_ident }}<'bump> {
    _bump: &'bump ::puroro::bumpalo::Bump,
    _bitfield: ::puroro::bitvec::array::BitArray<
        ::puroro::bitvec::order::Lsb0,
        [u32; ({{ m.bitfield_len }} + 31) / 32],
    >,

    {%- for f in m.fields %}
    {%- if !f.is_explicit_oneof_field %}
    {#- [optional] int32 => Bare<i32> #}
    {#- [optional] String => Bare<NoAllocBumpString> #}
    {#- [optional] MyMessage => Option<NoAllocBumpBox<MyMessageBumpalo<'bump>>> #}
    {#- repeated int32 => NoAllocBumpVec<i32> #}
    {#- repeated String => NoAllocBumpVec<NoAllocBumpString> #}
    {#- repeated MyMessage => NoAllocBumpVec<MyMessageBumpalo<'bump>> #}
    {{ f.ident }}: {{ f.bumpalo_field_type }},
    {%- endif %}
    {%- endfor %}

    {%- for oneof in m.oneofs %}
    {{ oneof.field_ident }}: 
        super::_puroro_nested::{{ m.submodule_ident }}::_puroro_private_oneofs::{{ oneof.bumpalo_enum_ident }}<'bump>,
    {%- endfor %} {#- for f in m.fields #}
}

pub type {{ m.bumpalo_owned_ident }} = ::puroro::BumpaloOwned<{{ m.bumpalo_ident }}<'static>>;


{#-################################################}
{#-################ Struct methods ################}
{#-################################################}
impl<'bump> {{ m.bumpalo_ident }}<'bump> {

    {#- ######## new_in ######## #}
    pub fn new_in(bump: &'bump ::puroro::bumpalo::Bump) -> Self {
        {#- We need to make this `bump_ref` to cut off the borrow from the param `bump`
         #  so that we can move the `bump` into our struct.
         #}
        #[allow(unused)]
        let bump_ref: &::puroro::bumpalo::Bump = unsafe {
            ::std::mem::transmute(
                ::std::ops::Deref::deref(&bump)
            )
        };

        Self {
            _bump: bump,
            _bitfield: ::std::default::Default::default(),

            {%- for f in m.fields %}
            {%- if !f.is_explicit_oneof_field %}
            {{ f.ident }}: ::std::default::Default::default(),
            {%- endif %} {#- if !f.is_explicit_oneof_field #}
            {%- endfor %} {#- for f in m.fields #}

            {%- for oneof in m.oneofs %}
            {{ oneof.field_ident }}: ::std::default::Default::default(),
            {%- endfor %}
        }
    }

    {#- ######## getters ######## #}
    {%- for f in m.fields %}
    {%- if !f.is_explicit_oneof_field %}
    {%- if f.is_repeated %}
    
    {#- ######## repeated getter ######## #}

    {#- repeated int32 => &'this [i32] #}
    {#- repeated String => &'this [impl Deref<Target=str>] #}
    {#- repeated MyMessage => &'this [MyMessageBumpalo<'this>] #}
    pub fn {{ f.ident }}<'this>(&'this self) -> {{ f.bumpalo_getter_type }} {
        {%- if f.is_message %}
        unsafe { self.{{ f.ident }}.cast_item_unchecked() }
        {%- else %} {#- if f.is_message #}
        &self.{{ f.ident }}
        {%- endif %} {#- if f.is_message #}
    }

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

    {#- ######## non-repeated getters ######## #}

    {#- [optional] int32 => Option<i32> #}
    {#- [optional] String => Option<&'this str> #}
    {#- [optional] MyMessage => Option<&'this MyMessageBumpalo<'this>> #}
    pub fn {{ f.ident_unesc }}_opt<'this>(&'this self) -> {{ f.bumpalo_getter_opt_type }} {
        {%- if f.is_message %}
        {#- Non-repeated message f. Field type is always `Option<NoAllocBox<T>>`.#}
        {#- Need to cast the lifetime. #}
        self.{{ f.ident }}.as_ref().map(|x| unsafe { ::std::mem::transmute(::std::ops::Deref::deref(x)) })

        {%- else %} {#- if f.is_message #}
        {%- if f.has_optional_bit %}
        {#- Non-repeated, non-message, optional f. Optional bit is stored in the bitfield. #}
        if self._bitfield.get({{ f.bitfield_index }}).map_or(false, |v| *v) {
            ::std::option::Option::Some(
                {%- if f.is_length_delimited %}
                &self.{{ f.ident }}
                {%- else %} {#- if f.is_length_delimited #}
                self.{{ f.ident }}.inner()
                {%- endif %} {#- if f.is_length_delimited #}
            )
        } else {
            ::std::option::Option::None
        }
        {%- else %} {#- if f.has_optional_bit #}
        {#- Non-repeated, non-message, unlabeled f. Treat as unexisting when it's default value. #}
        if !::puroro::internal::IsDefault::is_default(&*self.{{ f.ident }}) {
            ::std::option::Option::Some(
                {%- if f.is_length_delimited %}
                &self.{{ f.ident }}
                {%- else %} {#- if f.is_length_delimited #}
                self.{{ f.ident }}.inner()
                {%- endif %} {#- if f.is_length_delimited #}
            )
        } else {
            ::std::option::Option::None
        }
        {%- endif %} {#- if f.has_optional_bit #}
        {%- endif %} {#- if f.is_message #}
    }

    {#- [optional] int32 => i32 #}
    {#- [optional] String => &'this str #}
    {#- [optional] MyMessage => Option<&'this MyMessageBumpalo<'this>> #}
    pub fn {{ f.ident }}<'this>(&'this self) -> {{ f.bumpalo_getter_type }} {
        {%- if f.is_message %}
        {#- For message, we return `Option` value even in normal getter method. #}
        self.{{ f.ident_unesc }}_opt()
        {%- else %} {#- if f.is_message #}
        match self.{{ f.ident_unesc }}_opt() {
            ::std::option::Option::Some(x) => x,
            _ => {
                {%- if f.has_default_value %}
                {{ f.default_value }}
                {%- else %} {#- if f.has_default_value #}
                ::std::default::Default::default()
                {%- endif %} {#- if f.has_default_value #}
            }
        }
        {%- endif %} {#- if f.is_message #}
    }

    pub fn has_{{ f.ident_unesc }}(&self) -> bool {
        self.{{ f.ident_unesc }}_opt().is_some()
    }

    {%- endif %} {#- if f.is_repeated #}
    {%- endif %} {#- if !f.is_explicit_oneof_field #}
    {%- endfor %} {#- for f in m.fields #}

    {#- ######## mut getter ######## #}

    {%- for f in m.fields %}
    {%- if !f.is_explicit_oneof_field %}

    {%- if f.is_repeated %}

    {#- mut get repeated field #}
    
    {#- repeated int32 => RefMutBumpVec<'bump, 'this, i32> #}
    {#- repeated String => AddBumpVecView<'bump, 'this, NoAllocBumpString> #}
    {#- repeated MyMessage => RefMutBumpVec<'bump, 'this, MyMessageBumpalo<'bump>> #}
    pub fn {{ f.ident_unesc }}_mut<'this>(&'this mut self) -> {{ f.bumpalo_getter_mut_type }} {
        {%- if f.is_message %}
        unsafe { self.{{ f.ident }}.as_mut_vec_in(self._bump) }
        {%- endif %} {#- if f.is_message #}
        {%- if f.is_string || f.is_bytes %}
        unsafe { self.{{ f.ident }}.as_add_bump_vec_view_in(self._bump) }
        {%- endif %} {#- if f.is_string || f.is_bytes #}
        {%- if f.is_numerical %}
        unsafe { self.{{ f.ident }}.as_mut_vec_in(self._bump) }
        {%- endif %} {#- if f.is_numerical #}
    }

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

    {#- clear scalar field #}
    pub fn clear_{{ f.ident_unesc }}(&mut self) {
        {%- if f.has_optional_bit %}
        self._bitfield.set({{ f.bitfield_index }}, false);
        {#- Skip dropping the f. No need to do that unless it's a message field, #}
        {#- and the message field will never have optional bitfield. #}
        {%- else %} {#- if f.has_optional_bit #}
        self.{{ f.ident }} = ::std::default::Default::default();
        {%- endif %} {#- if f.has_optional_bit #}
    }

    {#- mut get scalar field #}
    {#- always returns an option-unwrapped mut reference. The field is initialized if it's not present. #}
    {#- [optional] int32 => &'this mut i32 #}
    {#- [optional] String => RefMutBumpString<'bump, 'this> #}
    {#- [optional] MyMessage => &'this mut MyMessageBumpalo<'bump> #}
    pub fn {{ f.ident_unesc }}_mut<'this>(&'this mut self) -> {{ f.bumpalo_getter_mut_type }} {
        if !self.has_{{ f.ident_unesc }}() {
            {#- field is not set so we need to initialize it. #}
            self.{{ f.ident }} = ::std::default::Default::default();

            {%- if f.has_optional_bit %}
            self._bitfield.set({{ f.bitfield_index }}, true);
            {%- endif %} {#- if f.has_optional_bit #}
        }

        {%- if f.is_message %}
        {#- Non-repeated message f. Field type is always `Optional<NoAllocBox<T>>`.#}
        let bump = self._bump;
        self.{{ f.ident }}.get_or_insert_with(|| ::puroro::internal::NoAllocBumpBox::new_in(
            ::puroro::internal::BumpDefault::default_in(bump),
            bump,
        ))
        {%- endif %} {#- if f.is_message #}
        {%- if f.is_string %}
        unsafe { self.{{ f.ident }}.as_mut_string_in(self._bump) } 
        {%- endif %} {#- if f.is_string #}
        {%- if f.is_bytes %}
        unsafe { self.{{ f.ident }}.as_mut_vec_in(self._bump) }
        {%- endif %} {#- if f.is_bytes #}
        {%- if f.is_numerical %}
        &mut self.{{ f.ident }}
        {%- endif %} {#- if f.is_numerical #}
    }

    {%- endif %} {#- if f.is_repeated #}
    {%- endif %} {#- if !f.is_explicit_oneof_field #}
    {%- endfor %} {#- for f in m.fields #}
}


{#-####################################################}
{#-################ puroro trait impls ################}
{#-####################################################}
impl<'bump> ::puroro::Message<super::_puroro_simple_impl::{{ m.simple_ident }}> for {{ m.bumpalo_ident }}<'bump> {}

impl<'bump> ::puroro::BumpaloMessage<'bump> for {{ m.bumpalo_ident }}<'bump> {
    fn new_in(bump: &'bump ::puroro::bumpalo::Bump) -> Self {
        Self::new_in(bump)
    }
}

impl<'bump> ::puroro::internal::BumpDefault<'bump> for {{ m.bumpalo_ident }}<'bump> {
    fn default_in(bump: &'bump ::puroro::bumpalo::Bump) -> Self {
        Self::new_in(bump)
    }
}

impl<'bump> super::_puroro_traits::{{ m.trait_ident }} for {{ m.bumpalo_ident }}<'bump> {
    {%- for f in m.fields %}
    {%- call bumpalo_trait_impl_field(f) %}
    {%- endfor %}

    {%- for oneof in m.oneofs %}
    fn {{ oneof.field_ident }}(&self) ->
        Option<
            super::_puroro_nested::{{ m.submodule_ident }}::_puroro_oneofs::
                {{ oneof.enum_ident }}{{ oneof.enum_maybe_gp_self }}
        >
    {
        use super::_puroro_nested::{{ m.submodule_ident }}::_puroro_private_oneofs::{{ oneof.bumpalo_enum_ident }} as E;
        use super::_puroro_nested::{{ m.submodule_ident }}::_puroro_oneofs::{{ oneof.enum_ident }} as F;
        match &self.{{ oneof.field_ident }} {
            E::_None(_) => ::std::option::Option::None,
            {%- for f in oneof.fields %}
            E::{{ f.ident }}(val) => ::std::option::Option::Some(
                {%- if f.is_message %}
                {#- message field need to be cast the lifetime param #}
                F::{{ f.ident }}(unsafe { ::std::mem::transmute(val.as_ref()) })
                {%- endif %} {#- if f.is_message #}
                {%- if f.is_string || f.is_bytes %}
                F::{{ f.ident }}(val.as_ref())
                {%- endif %} {#- if f.is_string || f.is_bytes #}
                {%- if f.is_numerical %}
                F::{{ f.ident }}(val.inner().clone())
                {%- endif %} {#- if f.is_numerical #}
            ),
            {%- endfor %}
        }
    }
    {%- endfor %}
}

impl<'bump> ::puroro::internal::de::DeserMessageFromBytesIter for {{ m.bumpalo_ident }}<'bump> {
    fn deser_field<'this, I>(
        &'this mut self,
        field_number: i32,
        data: ::puroro::internal::types::FieldData<&mut ::puroro::internal::de::from_iter::ScopedIter<I>>,
    ) -> ::puroro::Result<()>
    where
        I: ::std::iter::Iterator<Item = ::std::io::Result<u8>>
    {
        use ::puroro::internal::impls::bumpalo::de::DeserFieldFromBytesIter;
        match field_number {
            {%- for f in m.fields %}
            {%- if !f.is_explicit_oneof_field %}
            {{ f.number }} => {
                {%- if f.has_optional_bit %}
                self._bitfield.set({{ f.bitfield_index }}, true);
                {%- endif %}
                DeserFieldFromBytesIter::<
                    {{ f.bumpalo_label_and_type_tags }}
                >::deser_field(&mut self.{{ f.ident }}, data, self._bump)
            }
            {%- endif %}
            {%- endfor %}

            {%- for oneof in m.oneofs %}
            {%- for f in oneof.fields %}
            {{ f.number }} => {
                use super::_puroro_nested::{{ m.submodule_ident }}::_puroro_private_oneofs::{{ oneof.bumpalo_enum_ident }} as E;
                if !matches!(
                    &self.{{ oneof.field_ident }},
                    E::{{ f.ident }}(_))
                {
                    self.{{ oneof.field_ident }} = E::{{ f.ident }}(
                        {%- if f.is_message %}
                        ::puroro::internal::Bare::new(::puroro::BumpaloMessage::new_in(self._bump))
                        {%- else %} {#- if f.is_message #}
                        ::puroro::internal::BumpDefault::default_in(self._bump)
                        {%- endif %} {#- if f.is_message #}
                    );
                }
                let field_value_mut_ref = match &mut self.{{ oneof.field_ident }} {
                    E::{{ f.ident }}(v) => v,
                    _ => unreachable!(),
                };
                DeserFieldFromBytesIter::<
                    ::puroro::tags::OneofField, {{ f.bumpalo_field_type_tag }},
                >::deser_field(field_value_mut_ref, data, self._bump)
            }
            {%- endfor %}
            {%- endfor %}

            _ => unimplemented!("TODO: This case should be handled properly..."),
        }
    }
}

impl<'bump> ::puroro::internal::se::SerMessageToIoWrite for {{ m.bumpalo_ident }}<'bump>
where
    Self: super::_puroro_traits::{{ m.ident }}Trait,
{%- for f in m.fields %}
{%- if f.is_message %}
    for<'a> <Self as super::_puroro_traits::{{ m.trait_ident }}>::{{ f.ident_camel_unesc }}MessageType<'a> :
        ::puroro::internal::se::SerMessageToIoWrite,
{%- endif %}
{%- endfor %}
{
    fn ser<W>(&self, out: &mut W) -> ::puroro::Result<()>
    where
        W: ::std::io::Write,
    {
        {%- for f in m.fields %}
        ::puroro::internal::se::SerFieldToIoWrite::<
            {{ f.trait_label_and_type_tags }}
        >::ser_field(
            {%- if f.is_repeated %}
            <Self as super::_puroro_traits::{{ m.ident }}Trait>::{{ f.ident }}(self),
            {%- else %}
            <Self as super::_puroro_traits::{{ m.ident }}Trait>::{{ f.ident_unesc }}_opt(self),
            {%- endif %}
            {{ f.number }},
            out
        )?;
        {%- endfor %} {#- for f in m.fields #}
        ::std::result::Result::Ok(())
    }
}
