def adapt_transforms(
    transforms_list, ffcv_decoder_list, device: Optional[torch.device] = None
):
    """
    Adapt the list of torchvision transformations to FFCV.

    This will use hard-coded transformations that will usually
    make sense for the vast majority of situations. However,
    in some cases it makes sense to pass an explicit `decoder_def`
    to the :func:`enable_ffcv` function.

    :param transforms_list: The list of transformations. May include
        multi-param transformations. Avalanche will usually obtain this
        list from the AvalancheDatasets.
    :param ffcv_decoder_list: The list of FFCV decoders.
    :param device: If passed, the FFCV `ToDevice` operation will be added.
    :return: The transformations adapted for FFCV.
    """
    result = []
    for field_idx, pipeline_head in enumerate(ffcv_decoder_list):
        transforms = flat_transforms_recursive(transforms_list, field_idx)
        transforms = pipeline_head + transforms
        transforms = _apply_transforms_pre_optimization(transforms, device=device)

        field_transforms: List[Operation] = []
        for t in transforms:
            if isinstance(t, Operation):
                # Already an FFCV transform
                field_transforms.append(t)
            elif isinstance(t, PILToTensorTV):
                field_transforms.append(ToTensorFFCV())
                field_transforms.append(ToTorchImageFFCV())
            elif isinstance(t, ToTensorTV):
                field_transforms.append(ToTensorFFCV())
                field_transforms.append(ToTorchImageFFCV())
                field_transforms.append(ModuleWrapper(ScaleFrom_0_255_To_0_1()))
            elif isinstance(t, ConvertTV):
                field_transforms.append(ConvertFFCV(t.dtype))
            elif isinstance(t, RandomResizedCropTV):
                field_transforms.append(RandomResizedCropFFCV(t.scale, t.ratio, t.size))
            elif isinstance(t, RandomHorizontalFlipTV):
                field_transforms.append(RandomHorizontalFlipFFCV(t.p))
            elif isinstance(t, RandomCropTV):
                field_transforms.append(
                    SmartModuleWrapper(
                        t, expected_out_type="as_previous", expected_shape=t.size
                    )
                )
            elif isinstance(t, torch.nn.Module):
                field_transforms.append(SmartModuleWrapper(t))
            else:
                # Last hope...
                field_transforms.append(SmartModuleWrapper(CallableAdapter(t)))
        field_transforms = _add_to_device_operation(field_transforms, device=device)
        result.append(field_transforms)
    return result

    Adapt the list of torchvision transformations to FFCV.

    This will use hard-coded transformations that will usually
    make sense for the vast majority of situations. However,
    in some cases it makes sense to pass an explicit `decoder_def`
    to the :func:`enable_ffcv` function.

    :param transforms_list: The list of transformations. May include
        multi-param transformations. Avalanche will usually obtain this
        list from the AvalancheDatasets.
    :param ffcv_decoder_list: The list of FFCV decoders.
    :param device: If passed, the FFCV `ToDevice` operation will be added.
    :return: The transformations adapted for FFCV.
    
avalanche/benchmarks/utils/ffcv_support/ffcv_transform_utils.py