{% for docstring in docstrings.iter_strings() %}
/// {{ docstring }}
{%- endfor %}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd,
{% if info.should_do_eq %}Eq, Ord, Hash,{% endif %}
{% if info.should_do_default %}Default, {% endif %}
::serde::Serialize, ::serde::Deserialize
)]
pub struct {{ info.owned_name }} {
{% for field in fields -%}
{% for docstring in field.name_and_docs.docstrings.iter_strings() %}
/// {{ docstring }}
{%- endfor %}
pub {{ field.info.name }}: {{ field.info.owned_type }},
{% endfor %}
}
/// # Safety
/// The Planus compiler correctly calculates `ALIGNMENT` and `SIZE`.
unsafe impl ::planus::Primitive for {{ info.owned_name }} {
const ALIGNMENT: usize = {{ alignment }};
const SIZE: usize = {{ size }};
}
#[allow(clippy::identity_op)]
impl ::planus::WriteAsPrimitive<{{ info.owned_name }}> for {{ info.owned_name }} {
#[inline]
fn write<const N: usize>(&self, cursor: ::planus::Cursor<'_, N>, buffer_position: u32) {
{% for field in fields -%}
let (cur, cursor) = cursor.split::<{{ field.size }} , {{ size - field.offset - field.size }}>();
self.{{ field.info.name }}.write(cur, buffer_position - {{ field.offset }});
{%- if field.padding_after_field != 0 -%}
let cursor = cursor.write::<{{ field.padding_after_field }}, {{ size - field.offset - field.size - field.padding_after_field }}>([0; {{ field.padding_after_field }}]);
{%- endif -%}
{% endfor %}
cursor.finish([]);
}
}
impl ::planus::WriteAsOffset<{{ info.owned_name }}> for {{ info.owned_name }} {
#[inline]
fn prepare(&self, builder: &mut ::planus::Builder) -> ::planus::Offset<{{info.owned_name}}> {
unsafe {
builder.write_with(
{{ size }},
{{ alignment - 1 }},
|buffer_position, bytes| {
let bytes = bytes.as_mut_ptr();
::planus::WriteAsPrimitive::write(
self,
::planus::Cursor::new(&mut *(bytes as *mut [::core::mem::MaybeUninit<u8>; {{ size }}])),
buffer_position,
);
}
);
}
builder.current_offset()
}
}
impl ::planus::WriteAs<{{ info.owned_name }}> for {{ info.owned_name }} {
type Prepared = Self;
#[inline]
fn prepare(&self, _builder: &mut ::planus::Builder) -> Self {
*self
}
}
impl ::planus::WriteAsOptional<{{ info.owned_name }}> for {{ info.owned_name }} {
type Prepared = Self;
#[inline]
fn prepare(&self, _builder: &mut ::planus::Builder) -> ::core::option::Option<Self> {
::core::option::Option::Some(*self)
}
}
/// Reference to a deserialized [{{info.owned_name}}].
#[derive(Copy, Clone)]
pub struct {{ info.ref_name }}<'a>(::planus::ArrayWithStartOffset<'a, {{ size }}>);
impl<'a> {{ info.ref_name }}<'a> {
{% for field in fields %}
/// Getter for the [`{{field.name_and_docs.original_name}}` field]({{info.owned_name}}#structfield.{{field.info.name}}).
pub fn {{ field.info.name }}(&self) -> {{ field.info.getter_return_type }} {
let buffer = self.0.advance_as_array::<{{field.size}}>({{field.offset}}).unwrap();
{% if field.info.getter_return_type.starts_with("planus::Result<") %}
{{ field.info.getter_code }}.map_err(|error_kind| error_kind.with_error_location(
"{{info.ref_name}}",
"{{field.info.name}}",
self.0.offset_from_start,
))
{% else %}
{{ field.info.getter_code }}
{% endif %}
}
{% endfor %}
}
impl<'a> ::core::fmt::Debug for {{ info.ref_name }}<'a> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
let mut f = f.debug_struct("{{info.ref_name}}");
{% for field in fields -%}
{%- if field.info.getter_return_type.starts_with("planus::Result<") -%}
if let ::core::option::Option::Some(field_{{field.info.name}}) = self.{{field.info.name}}().transpose() {
f.field("{{field.info.name}}", &field_{{field.info.name}});
}
{%- else -%}
f.field("{{field.info.name}}", &self.{{field.info.name}}());
{%- endif -%}
{%- endfor %}
f.finish()
}
}
impl<'a> ::core::convert::From<::planus::ArrayWithStartOffset<'a, {{ size }}>> for {{ info.ref_name }}<'a> {
fn from(array: ::planus::ArrayWithStartOffset<'a, {{ size }}>) -> Self {
Self(array)
}
}
{% if info.should_do_infallible_conversion -%}
impl<'a> ::core::convert::From<{{ info.ref_name }}<'a>> for {{ info.owned_name}} {
#[allow(unreachable_code)]
fn from(value: {{info.ref_name}}<'a>) -> Self {
Self {
{% for field in fields -%}
{{ field.info.name }}:
{% if field.info.getter_return_type.ends_with("<'a>") -%}
::core::convert::From::from(value.{{field.info.name}}()),
{% else -%}
value.{{field.info.name}}(),
{% endif %}
{%- endfor %}
}
}
}
impl<'a, 'b> ::core::cmp::PartialEq<{{ info.ref_name }}<'a>> for {{ info.ref_name }}<'b> {
fn eq(&self, other: &{{info.ref_name}}<'_>) -> bool {
{% for field in fields -%}
{% if !loop.first %} && {% endif %}
self.{{field.info.name}}() == other.{{field.info.name}}()
{%- endfor %}
}
}
{% if info.should_do_eq %}
impl<'a> ::core::cmp::Eq for {{ info.ref_name}}<'a> {}
impl<'a, 'b> ::core::cmp::PartialOrd<{{ info.ref_name }}<'a>> for {{ info.ref_name }}<'b> {
fn partial_cmp(&self, other: &{{info.ref_name}}<'_>) -> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}
impl<'a> ::core::cmp::Ord for {{ info.ref_name }}<'a> {
fn cmp(&self, other: &{{info.ref_name}}<'_>) -> ::core::cmp::Ordering {
{% for field in fields -%}
{% if loop.first %}
self.{{field.info.name}}().cmp(&other.{{field.info.name}}())
{% else %}
.then_with(|| self.{{field.info.name}}().cmp(&other.{{field.info.name}}()))
{% endif %}
{%- endfor %}
}
}
impl<'a> ::core::hash::Hash for {{ info.ref_name }}<'a> {
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
{% for field in fields -%}
self.{{field.info.name}}().hash(state);
{%- endfor %}
}
}
{% else %}
impl<'a, 'b> ::core::cmp::PartialOrd<{{ info.ref_name }}<'a>> for {{ info.ref_name }}<'b> {
fn partial_cmp(&self, other: &{{info.ref_name}}<'_>) -> ::core::option::Option<::core::cmp::Ordering> {
{% for field in fields -%}
{% if loop.last %}
self.{{field.info.name}}().partial_cmp(&other.{{field.info.name}}())
{% else %}
match self.{{field.info.name}}().partial_cmp(&other.{{field.info.name}}()) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) => (),
o => return o,
}
{% endif %}
{%- endfor %}
}
}
{% endif %}
{%- else -%}
impl<'a> ::core::convert::TryFrom<{{ info.ref_name }}<'a>> for {{ info.owned_name}} {
type Error = ::planus::Error;
#[allow(unreachable_code)]
fn try_from(value: {{info.ref_name}}<'a>) -> ::planus::Result<Self> {
::core::result::Result::Ok(Self {
{% for field in fields -%}
{{ field.info.name }}:
{% if field.info.getter_return_type.starts_with("::core::result::Result<") -%}
{%- if field.info.can_do_infallible_conversion -%}
value.{{field.info.name}}()?,
{%- else -%}
::core::convert::TryInto::try_into(value.{{field.info.name}}()?)?,
{%- endif -%}
{% else if field.info.getter_return_type.ends_with("<'a>") -%}
{%- if field.info.can_do_infallible_conversion -%}
::core::convert::Into::into(value.{{field.info.name}}()),
{%- else -%}
::core::convert::TryInto::try_into(value.{{field.info.name}}())?,
{%- endif -%}
{% else -%}
value.{{field.info.name}}(),
{% endif -%}
{%- endfor %}
})
}
}
{%- endif %}
impl<'a> ::planus::TableRead<'a> for {{ info.ref_name }}<'a> {
#[inline]
fn from_buffer(buffer: ::planus::SliceWithStartOffset<'a>, offset: usize) -> ::core::result::Result<Self, ::planus::errors::ErrorKind> {
let buffer = buffer.advance_as_array::<{{size}}>(offset)?;
::core::result::Result::Ok(Self(buffer))
}
}
impl<'a> ::planus::VectorRead<'a> for {{ info.ref_name }}<'a> {
const STRIDE: usize = {{ size }};
#[inline]
unsafe fn from_buffer(buffer: ::planus::SliceWithStartOffset<'a>, offset: usize) -> Self {
Self(unsafe { buffer.unchecked_advance_as_array(offset) })
}
}
/// # Safety
/// The planus compiler generates implementations that initialize
/// the bytes in `write_values`.
unsafe impl ::planus::VectorWrite<{{ info.owned_name }}> for {{ info.owned_name }} {
const STRIDE: usize = {{ size }};
type Value = {{ info.owned_name }};
#[inline]
fn prepare(&self, _builder: &mut ::planus::Builder) -> Self::Value {
*self
}
#[inline]
unsafe fn write_values(
values: &[{{info.owned_name}}],
bytes: *mut ::core::mem::MaybeUninit<u8>,
buffer_position: u32,
) {
let bytes = bytes as *mut [::core::mem::MaybeUninit<u8>; {{ size }}];
for (i, v) in ::core::iter::Iterator::enumerate(values.iter()) {
::planus::WriteAsPrimitive::write(
v,
::planus::Cursor::new(unsafe { &mut *bytes.add(i) }),
{% if size == 1 %}
buffer_position - i as u32,
{% else %}
buffer_position - ({{ size }} * i) as u32,
{% endif %}
);
}
}
}