/* This file was generated by generate-wire.py */
/* Do not modify this file! Modify the _csv file it was generated from. */
/* Original template can be found at tools/gen/header_template */

#ifndef LIGHTNING_${idem}
#define LIGHTNING_${idem}
#include <ccan/tal/tal.h>
#include <wire/tlvstream.h>
#include <wire/wire.h>
% for i in includes:
${i}
% endfor

## Enum sets for wire messages & tlvs
% for enum_set in enum_sets:
enum ${enum_set['name']} {
    % for msg in enum_set['set']:
        % for comment in msg.msg_comments:
        /* ${comment} */
        % endfor
        ${msg.enum_name()} = ${msg.number},
    % endfor
};

%endfor
## The 'name' functions for the enums
% for enum_set in enum_sets:
const char *${enum_set['name']}_name(int e);

/**
 * Determine whether a given message type is defined as a message.
 *
 * Returns true if the message type is part of the message definitions we have
 * generated parsers for, false if it is a custom message that cannot be
 * handled internally.
 */
bool ${enum_set['name']}_is_defined(u16 type);
% endfor

## Structs for subtypes + tlv messages
% for struct in structs:
struct ${struct.struct_name()} {
        % for f in struct.fields.values():
            % for c in f.field_comments:
        /* ${c} */
            % endfor
        % if bool(f.len_field_of):
<% continue %>
        % endif
            % if f.is_varlen() and f.type_obj.is_varsize():
        ${f.type_obj.type_name()} **${f.name};
            % elif f.is_varlen() or f.type_obj.is_varsize():
        ${f.type_obj.type_name()} *${f.name};
            % elif f.is_array():
        ${f.type_obj.type_name()} ${f.name}[${f.count}];
            % else:
        ${f.type_obj.type_name()} ${f.name};
            % endif
        % endfor
};
% endfor
## Structs for TLVs
% for tlv in tlvs.values():
struct ${tlv.struct_name()} {
        /* Raw fields including unknown ones. */
        struct tlv_field *fields;

	/* TODO The following explicit fields could just point into the
	 * tlv_field entries above to save on memory. */
    % for msg in tlv.messages.values():
        % if msg.singleton():
	## Array of variable-length elems needs ptr-to-ptr!
            % if msg.singleton().is_varlen() and msg.singleton().type_obj.is_varsize():
	${msg.singleton().type_obj.type_name()} **${msg.name};
	    % else:
	${msg.singleton().type_obj.type_name()} *${msg.name};
	    % endif
	% else:
        struct ${msg.struct_name()} *${msg.name};
	% endif
    % endfor
};
% endfor

% for tlv in tlvs.values():
struct ${tlv.struct_name()} *${tlv.struct_name()}_new(const tal_t *ctx);

/**
 * Deserialize a TLV stream for the ${tlv.name} namespace.
 *
 * This function will parse any TLV stream, as long as the type, length and
 * value fields are formatted correctly. Fields that are not known in the
 * current namespace are stored in the `fields` member. Validity can be
 * checked using ${tlv.name}_is_valid.
 */
bool fromwire_${tlv.name}(const u8 **cursor, size_t *max,
			  struct ${tlv.struct_name()} * record);

/**
 * Serialize a TLV stream for the ${tlv.name} namespace.
 *
 * This function only considers known fields from the ${tlv.name} namespace,
 * and will ignore any fields that may be stored in the `fields` member. This
 * ensures that the resulting stream is valid according to
 * `${tlv.name}_is_valid`.
 */
void towire_${tlv.name}(u8 **pptr, const struct ${tlv.struct_name()} *record);

/**
 * Check that the TLV stream is valid.
 *
 * Enforces the followin validity rules:
 * - Types must be in monotonic non-repeating order
 * - We must understand all even types
 *
 * Returns false if an error was detected, otherwise returns true. If err_index
 * is non-null and we detect an error it is set to the index of the first error
 * detected.
 */
bool ${tlv.name}_is_valid(const struct ${tlv.struct_name()} *record,
			  size_t *err_index);

% if tlv.name in options.expose_tlv_type:
#define TLVS_ARRAY_SIZE_${tlv.name} ${len(tlv.messages)}
extern const struct tlv_record_type tlvs_${tlv.name}[];

<%!
    def upper(text):
        return text.upper()
%>

/* Define an enum with the constants */
enum ${tlv.name}_types {
% for msg in tlv.ordered_msgs():
	${msg.struct_name()|upper} = ${msg.number},
% endfor
};

% endif
% endfor
% if options.expose_subtypes and bool(subtypes):
% for subtype in subtypes:
/* SUBTYPE: ${subtype.name.upper()} */
    % for c in subtype.type_comments:
/* ${c} */
    % endfor
void towire_${subtype.name}(u8 **p, const ${subtype.type_name()} *${subtype.name});
% if subtype.is_varsize():
${subtype.type_name()} *fromwire_${subtype.name}(const tal_t *ctx, const u8 **cursor, size_t *plen);
% else:
void fromwire_${subtype.name}(const u8 **cursor, size_t *plen, ${subtype.type_name()} *${subtype.name});
% endif

% endfor
% endif
% for msg in messages:
    % if msg.if_token:
#if ${msg.if_token}
    % endif
/* WIRE: ${msg.name.upper()} */
    % for c in msg.msg_comments:
/* ${c} */
    % endfor
u8 *towire_${msg.name}(const tal_t *ctx${''.join([f.arg_desc_to() for f in msg.fields.values()])});
bool fromwire_${msg.name}(${'const tal_t *ctx, ' if msg.needs_context() else ''}const void *p${''.join([f.arg_desc_from() for f in msg.fields.values()])});
    % if msg.if_token:
#endif /* ${msg.if_token} */
    % endif

% endfor

#endif /* LIGHTNING_${idem} */
