// SPDX-License-Identifier: CDDL-1.0
/*
 * CDDL HEADER START
 *
 * This file and its contents are supplied under the terms of the Common
 * Development and Distribution License ("CDDL"), version 1.0. You may only use
 * this file in accordance with the terms of version 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this source. A
 * copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2026 by Garth Snyder. All rights reserved.
 */

#ifndef _ZSTREAM_FLETCHER4_H
#define	_ZSTREAM_FLETCHER4_H

#ifdef __cplusplus
extern "C" {
#endif

#include "zstream_io.h"

/*
 * zstream_chain module for calculating, validating, and inscribing
 * Fletcher4 checksums.
 *
 * serial_validate_fletcher4() validates record checksums against the
 * running stream checksum and fails loudly on any mismatch.
 *
 * serial_add_fletcher4() inscribes record checksums from the running
 * stream checksum, in theory replacing whatever was there before. But
 * see note in zstream_fletcher4.c regarding zero checksums generated
 * by send_conclusion_record(), which are preserved.
 */

/*
 * DRR_END records normally do have end-record checksums. However, records
 * emitted by send_conclusion_record() in libzfs_sendrecv.c have the
 * checksum set to zero. zfs receive ignores those checksums. DRR_END
 * records also have an internal checksum that applies to the stream-to-date
 * since the most recent DRR_BEGIN.
 *
 * Ideally, null zstream transformations should be idempotent. E.g., a
 * zstream redup that does not redup anything should yield a stream that is
 * identical to the original stream. So, it's helpful to emulate zfs send's
 * checksumming practices just to minimize spurious differences between
 * input and output streams.
 *
 * The IS_CONCLUSION macro recognizes the records generated by
 * send_conclusion_record() so that they can be treated specially.
 */
#define	IS_CONCLUSION(drr, type)					       \
	    ((type) == DRR_END &&					       \
	    (drr)->drr_u.drr_end.drr_toguid == 0 &&			       \
	    ZIO_CHECKSUM_IS_ZERO(&(drr)->drr_u.drr_checksum.drr_checksum))

/*
 * Maximum number of checksum operations in one chain
 */
#define	MAX_FLETCHER_4 8

chain_step_t
serial_validate_fletcher4(void);

chain_step_t
serial_add_fletcher4(void);

#ifdef __cplusplus
}
#endif

#endif  /* _ZSTREAM_FLETCHER4_H */
