{% if emit_crate_header and backend_mode == "no_std" -%}
#![no_std]

{% endif -%}
{% if function_index == 0 -%}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GradgenError {
    WorkspaceTooSmall(&'static str),
    InputTooSmall(&'static str),
    OutputTooSmall(&'static str),
}

{% endif -%}
{% if function_index == 0 and shared_helper_lines -%}
{% for line in shared_helper_lines -%}
{{ line }}
{% endfor -%}

{% endif -%}
{% if emit_metadata_helpers -%}
{% if emit_docs -%}
{% if function_index == 0 -%}
/// Metadata describing a generated Rust function.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FunctionMetadata {
    /// Generated Rust function name.
    pub function_name: &'static str,
    /// Minimum required length of the mutable workspace slice.
    pub workspace_size: usize,
    /// Declared input names.
    pub input_names: &'static [&'static str],
    /// Declared input slice lengths.
    pub input_sizes: &'static [usize],
    /// Declared output names.
    pub output_names: &'static [&'static str],
    /// Declared output slice lengths.
    pub output_sizes: &'static [usize],
}

{% endif -%}
/// Return metadata describing [`{{ function_name }}`].
{% endif -%}
pub fn {{ function_name }}_meta() -> FunctionMetadata {
    FunctionMetadata {
        function_name: {{ function_label }},
        workspace_size: {{ workspace_size }},
        input_names: &[
{% for spec in input_specs %}
            {{ spec.rust_label }},
{% endfor %}
        ],
        input_sizes: &[
{% for spec in input_specs %}
            {{ spec.size }},
{% endfor %}
        ],
        output_names: &[
{% for spec in output_specs %}
            {{ spec.rust_label }},
{% endfor %}
        ],
        output_sizes: &[
{% for spec in output_specs %}
            {{ spec.size }},
{% endfor %}
        ],
    }
}

{% endif -%}
{% if emit_docs -%}
/// Evaluate the generated symbolic function `{{ function_name }}`.
///
/// All numeric slices use the `{{ scalar_type }}` scalar type.
///
/// Arguments:
{% for spec in input_specs -%}
/// - `{{ spec.rust_name }}`:
///   {{ spec.doc_description|wordwrap(68, false, "\n///   ") }}
///   Expected length: {{ spec.size }}.
{% endfor -%}
{% for spec in output_specs -%}
/// - `{{ spec.rust_name }}`:
///   {{ spec.doc_description|wordwrap(68, false, "\n///   ") }}
///   Expected length: {{ spec.size }}.
{% endfor -%}
/// - `work`: mutable workspace slice used to store intermediate values
///   while evaluating this kernel. Expected length: at least {{ workspace_size }}.
{% endif -%}
{% if function_parameter_count > 7 -%}
#[allow(clippy::too_many_arguments)]
{% endif -%}
{{ function_keyword }} {{ function_name }}({{ parameters }}){% if function_keyword.startswith('pub') %} -> Result<(), GradgenError>{% endif %} {
{% if function_keyword.startswith('pub') %}
    {% if workspace_return_line %}
    {{ workspace_return_line }}
    {% endif %}
{% elif workspace_assert_line %}
    {{ workspace_assert_line }}
{% endif %}
{% for line in input_assert_lines %}
    {% if function_keyword.startswith('pub') %}
    {{ input_return_lines[loop.index0] }}
    {% endif %}
{% endfor %}
{% for line in output_assert_lines %}
    {% if function_keyword.startswith('pub') %}
    {{ output_return_lines[loop.index0] }}
    {% endif %}
{% endfor %}
{% for line in computation_lines %}
    {{ line }}
{% endfor %}
{% for line in output_write_lines %}
    {{ line }}
{% endfor %}
{% if function_keyword.startswith('pub') %}
    Ok(())
{% endif %}
}
