// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

library RotationPacking {
    struct RotationState {
        uint8 parity;
        uint64 session;
    }

    function pack(uint8 parity, uint64 session) internal pure returns (uint256 packed) {
        // forge-lint: disable-next-line(unsafe-typecast)
        return (uint256(session) << 8) | uint256(parity);
    }

    function pack(RotationState calldata state) internal pure returns (uint256 packed) {
        return pack(state.parity, state.session);
    }

    function unpack(uint256 packed) internal pure returns (RotationState memory state) {
        // forge-lint: disable-next-line(unsafe-typecast)
        state.parity = uint8(packed & 0xFF);
        state.session = uint64((packed >> 8) & 0xFFFFFFFFFFFFFFFF);
        return state;
    }
}

library RequestPacking {
    struct RequestPayload {
        uint32 commission;
        uint64 chainId;
        address receiver;
    }

    function pack(uint32 commission, uint64 chainId, address receiver) internal pure returns (uint256 packed) {
        packed = uint256(uint160(receiver)) << 96;
        packed |= uint256(chainId) << 32;
        packed |= uint256(commission);
        return packed;
    }

    function pack(RequestPayload calldata data) internal pure returns (uint256 packed) {
        return pack(data.commission, data.chainId, data.receiver);
    }

    function unpack(uint256 packed) internal pure returns (RequestPayload memory data) {
        // forge-lint: disable-next-line(unsafe-typecast)
        data.commission = uint32(packed & 0xFFFFFFFF);
        // forge-lint: disable-next-line(unsafe-typecast)
        data.chainId = uint64((packed >> 32) & 0xFFFFFFFFFFFFFFFF);
        // forge-lint: disable-next-line(unsafe-typecast)
        data.receiver = address(uint160(packed >> 96));
        return data;
    }
}
