// Copyright 2019 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <limits>
#include <memory>
#include <span>
#include <utility>

#include "dawn/wire/WireCmd_autogen.h"
#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/wire/BufferConsumer.h"
#include "src/dawn/wire/WireResult.h"
#include "src/dawn/wire/server/Server.h"
#include "src/utils/assert.h"

namespace dawn::wire::server {

WireResult Server::PreHandleDeviceCreateErrorBuffer(const DeviceCreateErrorBufferCmd& cmd) {
    // mappedAtCreation isn't implemented in CreateErrorBuffer.
    // The client blocks this, so we can treat it as a fatal wire error (for fuzzers).
    if (cmd.descriptor->mappedAtCreation) {
        return WireResult::FatalError;
    }

    return WireResult::Success;
}

WireResult Server::PreHandleBufferUnmap(const BufferUnmapCmd& cmd) {
    Known<WGPUBuffer> buffer;
    WIRE_TRY(Get(cmd.selfId, &buffer));

    buffer->mapState.Use([&](auto mapState) {
        if (buffer->mappedAtCreation &&
            !(buffer->usage & (WGPUBufferUsage_MapWrite | WGPUBufferUsage_MapRead))) {
            // This indicates the memoryHandle is for mappedAtCreation only. Destroy on unmap
            // memoryHandle could have possibly been deleted if buffer is already destroyed so we
            // don't assert it's non-null
            mapState->memoryHandle = nullptr;
        }
    });

    return WireResult::Success;
}

WireResult Server::PreHandleBufferDestroy(const BufferDestroyCmd& cmd) {
    // Destroying a buffer does an implicit unmapping.
    Known<WGPUBuffer> buffer;
    WIRE_TRY(Get(cmd.selfId, &buffer));

    // The buffer was destroyed. Clear the MemoryHandle.
    buffer->mapState.Use([](auto mapState) { mapState->memoryHandle = nullptr; });

    return WireResult::Success;
}

WireResult Server::DoBufferMapAsync(Known<WGPUBuffer> buffer,
                                    Known<WGPUInstance> instance,
                                    Future future,
                                    wgpu::MapMode mode,
                                    size_t offset,
                                    size_t size) {
    // These requests are just forwarded to the buffer, with userdata containing what the
    // client will require in the return command.
    std::unique_ptr<MapUserdata> userdata = MakeUserdata<MapUserdata>();
    userdata->buffer = buffer.AsHandle();
    userdata->instanceId = instance.id;
    userdata->future = future;
    userdata->mode = mode;

    // Make sure that the size is not WGPU_WHOLE_MAP_SIZE because we want the client to give us an
    // explicit size (so we don't have to handle the defaulting here). The client needs to track
    // the size of the buffer and can do the default size computation.
    if (size >= WGPU_WHOLE_MAP_SIZE) {
        return WireResult::FatalError;
    }

    userdata->offset = offset;
    userdata->size = size;

    mProcs->bufferMapAsync(
        buffer->handle, ToAPI(mode), offset, size,
        MakeCallbackInfo<WGPUBufferMapCallbackInfo, &Server::OnBufferMapAsyncCallback>(
            userdata.release()));

    return WireResult::Success;
}

WireResult Server::DoDeviceCreateBuffer(Known<WGPUDevice> device,
                                        const BufferDescriptor* descriptor,
                                        ObjectHandle bufferHandle,
                                        Span<const std::byte> memoryHandleCreateInfo) {
    // Create and register the buffer object.
    Reserved<WGPUBuffer> buffer;
    WIRE_TRY(Allocate(&buffer, bufferHandle));
    buffer->usage = ToAPI(descriptor->usage);
    buffer->mappedAtCreation = descriptor->mappedAtCreation;

    bool isMappable =
        descriptor->mappedAtCreation != 0u ||
        ((descriptor->usage & (wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite)) !=
         wgpu::BufferUsage::None);

    // If the buffer is not mappable, create it normally without shared memory.
    if (!isMappable) {
        buffer->handle = mProcs->deviceCreateBuffer(device->handle, ToAPI(descriptor));
        return WireResult::Success;
    }

    // Return `FatalError` if we fail to deserialize the memory handle.
    std::unique_ptr<MemoryTransferService::MemoryHandle> memoryHandle =
        mMemoryTransferService->DeserializeMemoryHandle(memoryHandleCreateInfo);
    if (memoryHandle == nullptr) {
        buffer->handle = mProcs->deviceCreateBuffer(device->handle, ToAPI(descriptor));
        return WireResult::FatalError;
    }

    // Try to wrap the shared memory into a buffer. Note that:
    // - `TryWrapInBuffer()` may return a valid buffer, an error buffer or nullptr to align with the
    //   behavior of `DeviceBase::APICreateBuffer()`.
    // - When a valid buffer is returned, `beginAccess()` must have been called on it.
    // - Index/indirect buffers are not supported to prevent the TOCTOU issue with races between
    //   GPU-side validation and the client modifying the buffer.
    if (!(descriptor->usage & (wgpu::BufferUsage::Indirect | wgpu::BufferUsage::Index))) {
        buffer->handle =
            memoryHandle->TryWrapInBuffer(mProcs.get(), device->handle, ToAPI(descriptor));
    }
    if (buffer->handle != nullptr) {
        buffer->backedWithSharedMemory = true;
        return buffer->mapState.Use([&](auto mapState) {
            mapState->memoryHandle = std::move(memoryHandle);
            return WireResult::Success;
        });
    } else {
        // Returning `nullptr` from `TryWrapInBuffer()` indicates that we failed to wrap the shared
        // memory into a buffer. Try to create it normally without shared memory.
        buffer->handle = mProcs->deviceCreateBuffer(device->handle, ToAPI(descriptor));
    }

    // A null buffer indicates that mapping-at-creation failed inside createBuffer. Unmark the
    // buffer as allocated so we will skip freeing it.
    if (buffer->handle == nullptr) {
        DAWN_ASSERT(descriptor->mappedAtCreation);
        buffer->state = AllocationState::Reserved;
        return WireResult::Success;
    }

    return buffer->mapState.Use([&](auto mapState) {
        mapState->memoryHandle = std::move(memoryHandle);
        return WireResult::Success;
    });
}

WireResult Server::DoBufferUpdateMappedData(Known<WGPUBuffer> buffer,
                                            Span<const std::byte> writeDataUpdateInfo,
                                            size_t offset,
                                            size_t size) {
    if (size == WGPU_WHOLE_MAP_SIZE) {
        return WireResult::FatalError;
    }

    // Buffers backed with shared memory are directly shared with client; no deserialization needed.
    if (buffer->backedWithSharedMemory) {
        return WireResult::Success;
    }

    return buffer->mapState.Use([&](auto mapState) {
        std::byte* mappedData =
            static_cast<std::byte*>(mProcs->bufferGetMappedRange(buffer->handle, offset, size));

        // There are a few valid reasons why getting the mapped range would fail here:
        //  - The buffer was implicitly unmapped because of a device.Destroy() call.
        //  - The buffer was an error buffer created just to replace an OOM mappedAtCreation buffer.
        // Unfortunately validating exactly that the failure is due to a valid reason and not
        // another is difficult, so we return WireResult::Success even for misuses of the wire
        // protocol (like a size being larger than the buffer's size, etc).
        if (mappedData == nullptr) {
            return WireResult::Success;
        }

        // SAFETY: If GetMappedRange returns non-null, it points to at least `size` valid bytes.
        Span<std::byte> DAWN_UNSAFE_BUFFERS(mappedRange{mappedData, size});

        // However it is easy to check for misuses of the wire protocol to UpdateMappedData without
        // a MemoryHandle.
        if (!mapState->memoryHandle) {
            return WireResult::FatalError;
        }

        // Deserialize the flush info and flush updated data from the handle into mappedRange.
        if (!mapState->memoryHandle->DeserializeDataUpdate(writeDataUpdateInfo, offset, size,
                                                           mappedRange)) {
            return WireResult::FatalError;
        }
        return WireResult::Success;
    });
}

void Server::OnBufferMapAsyncCallback(MapUserdata* data,
                                      wgpu::MapAsyncStatus status,
                                      StringView message) {
    // Skip sending the callback if the buffer has already been destroyed.
    Known<WGPUBuffer> buffer;
    if (Get(data->buffer.id, &buffer) != WireResult::Success ||
        buffer->generation != data->buffer.generation) {
        return;
    }

    bool isSuccess = status == wgpu::MapAsyncStatus::Success;

    ReturnBufferMapAsyncCallbackCmd cmd = {};
    cmd.instanceId = data->instanceId;
    cmd.future = data->future;
    cmd.status = status;
    cmd.message = message;

    if (!isSuccess) {
        SerializeCommand(std::move(cmd));
        return;
    }

    switch (data->mode) {
        case wgpu::MapMode::Read: {
            DAWN_ASSERT(data->size != WGPU_WHOLE_MAP_SIZE);  // Validated in DoBufferMapAsync.

            // Buffers backed with shared memory are directly shared with client; no deserialization
            // needed.
            if (buffer->backedWithSharedMemory) {
                SerializeCommand(std::move(cmd));
                break;
            }

            buffer->mapState.Use([&](auto mapState) {
                const std::byte* mappedData = static_cast<const std::byte*>(
                    mProcs->bufferGetConstMappedRange(buffer->handle, data->offset, data->size));

                // SAFETY: If GetConstMappedRange with size != WGPU_WHOLE_MAP_SIZE returns non-null,
                // it points to at least `size` valid bytes.
                Span<const std::byte> DAWN_UNSAFE_BUFFERS(mappedRange{mappedData, data->size});

                auto* memoryHandle = mapState->memoryHandle.get();
                if (!memoryHandle) {
                    cmd.status = wgpu::MapAsyncStatus::Aborted;
                    SerializeCommand(std::move(cmd));
                    return;
                }

                size_t dataUpdateInfoLength =
                    memoryHandle->GetSerializeDataUpdateSize(data->offset, data->size);
                SerializeCommand(
                    std::move(cmd),
                    // Extensions to replace fields skipped by skip_serialize.
                    CommandExtension<&ReturnBufferMapAsyncCallbackCmd::readDataUpdateInfo>{
                        dataUpdateInfoLength, [memoryHandle, data, mappedRange](
                                                  Span<volatile std::byte> serializeBuffer) {
                            // The in-flight map request returned successfully.
                            memoryHandle->SerializeDataUpdate(serializeBuffer, data->offset,
                                                              data->size, mappedRange);
                        }});
            });
            break;
        }
        case wgpu::MapMode::Write: {
            SerializeCommand(std::move(cmd));
            break;
        }
        default:
            // If we are not one of the two possible modes, we should never succeed.
            DAWN_UNREACHABLE();
            break;
    }
}

}  // namespace dawn::wire::server
