// Copyright 2026 Noverberrain.
// SPDX-License-Identifier: Apache-2.0
///|
/// A MySQL 8.0 ROTATE_EVENT (4), independent of the common header's next_position.
/// The target identifier is retained verbatim, without charset/path interpretation.
pub struct RotateEvent {
header : EventHeader
position : UInt64
next_binlog : Bytes
} derive(Debug, Eq)
///|
pub extend RotateEvent with Eq::{equal, not_equal}
///|
pub extend RotateEvent with @debug.Debug::{to_repr}
///|
/// Validate one full event using its current FDE. Requires an eight-byte
/// little-endian position and a nonempty identifier byte sequence. No NUL is
/// appended or stripped from the identifier.
/// Unknown filename encodings and all UInt64 positions (including zero) are
/// preserved. Trailing input outside the declared event is not consumed.
/// No next file is opened and no cross-file/transaction state is advanced.
/// For a framed event from BinlogFileReader, pass event.format, event.raw and
/// file_offset=event.header.file_offset; position is the target file's offset.
pub fn RotateEvent::parse(
format : FormatDescription,
data : BytesView,
file_offset~ : UInt64,
max_event_size~ : UInt32 = 16_777_216,
) -> RotateEvent raise DecodeError {
let header = EventHeader::parse(data, file_offset~, max_event_size~)
guard header.event_type == 4 else {
raise UnexpectedEventType(
file_offset~,
expected=4,
actual=header.event_type,
)
}
let body = format.payload(data, file_offset~, max_event_size~)
guard format.post_header_lengths.get(3) is Some(8) else {
raise InvalidRotateEvent(
file_offset~,
reason="ROTATE requires an eight-byte post-header",
)
}
guard body.length() > 8 else {
raise InvalidRotateEvent(
file_offset~,
reason="ROTATE requires a complete position and nonempty filename",
)
}
let mut position = 0UL
for i in 0..<8 {
position = position | (body[i].to_uint().to_uint64() << (8 * i))
}
{ header, position, next_binlog: body[8:].to_owned(), }
}