// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library zx;

@transport("Syscall")
closed protocol Fifo {
    /// ## Summary
    ///
    /// Create a fifo.
    ///
    /// ## Declaration
    ///
    /// ```c
    /// #include <zircon/syscalls.h>
    ///
    /// zx_status_t zx_fifo_create(size_t elem_count,
    ///                            size_t elem_size,
    ///                            uint32_t options,
    ///                            zx_handle_t* out0,
    ///                            zx_handle_t* out1);
    /// ```
    ///
    /// ## Description
    ///
    /// `zx_fifo_create()` creates a fifo, which is actually a pair of fifos
    /// of *elem_count* entries of *elem_size* bytes.  Two endpoints are
    /// returned.  Writing to one endpoint enqueues an element into the fifo
    /// that the opposing endpoint reads from.
    ///
    /// Fifos are intended to be the control plane for shared memory transports.
    /// Their read and write operations are more efficient than *sockets* or
    /// *channels*, but there are severe restrictions on the size of elements
    /// and buffers.
    ///
    /// The total size of each fifo (`elem_count * elem_size`) may not exceed 4096 bytes.
    ///
    /// The *options* argument must be 0.
    ///
    /// ## Rights
    ///
    /// Caller job policy must allow `ZX_POL_NEW_FIFO`.
    ///
    /// ## Return value
    ///
    /// `zx_fifo_create()` returns `ZX_OK` on success. In the event of
    /// failure, one of the following values is returned.
    ///
    /// ## Errors
    ///
    /// `ZX_ERR_INVALID_ARGS`  *out0* or *out1* is an invalid pointer or NULL or
    /// *options* is any value other than 0.
    ///
    /// `ZX_ERR_OUT_OF_RANGE`  *elem_count* or *elem_size* is zero, or
    /// *elem_count* * *elem_size* is greater than 4096.
    ///
    /// `ZX_ERR_NO_MEMORY`  Failure due to lack of memory.
    /// There is no good way for userspace to handle this (unlikely) error.
    /// In a future build this error will no longer occur.
    ///
    /// ## See also
    ///
    ///  - [`zx_fifo_read()`]
    ///  - [`zx_fifo_write()`]
    ///
    /// [`zx_fifo_read()`]: fifo_read.md
    /// [`zx_fifo_write()`]: fifo_write.md
    strict Create(struct {
        elem_count usize64;
        elem_size usize64;
        options uint32;
    }) -> (resource struct {
        out0 Handle:FIFO;
        out1 Handle:FIFO;
    }) error Status;

    /// ## Summary
    ///
    /// Read data from a fifo.
    ///
    /// ## Declaration
    ///
    /// ```c
    /// #include <zircon/syscalls.h>
    ///
    /// zx_status_t zx_fifo_read(zx_handle_t handle,
    ///                          size_t elem_size,
    ///                          void* data,
    ///                          size_t count,
    ///                          size_t* actual_count);
    /// ```
    ///
    /// ## Description
    ///
    /// `zx_fifo_read()` attempts to read up to *count* elements from the fifo
    /// *handle* into *data*.
    ///
    /// Fewer elements may be read than requested if there are insufficient
    /// elements in the fifo to fulfill the entire request. The number of
    /// elements actually read is returned via *actual_count*.
    ///
    /// The element size specified by *elem_size* must match the element size
    /// that was passed into [`zx_fifo_create()`].
    ///
    /// *data* must have a size of at least `count * elem_size` bytes.
    ///
    /// *actual_count* is allowed to be NULL. This is useful when reading
    /// a single element: if *count* is 1 and `zx_fifo_read()` returns `ZX_OK`,
    /// *actual_count* is guaranteed to be 1 and thus can be safely ignored.
    ///
    /// It is not legal to read zero elements.
    ///
    /// ## Rights
    ///
    /// *handle* must be of type `ZX_OBJ_TYPE_FIFO` and have `ZX_RIGHT_READ`.
    ///
    /// ## Return value
    ///
    /// `zx_fifo_read()` returns `ZX_OK` on success, and returns
    /// the number of elements read (at least one) via *actual_count*.
    ///
    /// ## Errors
    ///
    /// `ZX_ERR_BAD_HANDLE`  *handle* is not a valid handle.
    ///
    /// `ZX_ERR_WRONG_TYPE`  *handle* is not a fifo handle.
    ///
    /// `ZX_ERR_INVALID_ARGS`  *data* is an invalid pointer or *actual_count*
    /// is an invalid pointer.
    ///
    /// `ZX_ERR_OUT_OF_RANGE`  *count* is zero or *elem_size* is not equal
    /// to the element size of the fifo.
    ///
    /// `ZX_ERR_ACCESS_DENIED`  *handle* does not have `ZX_RIGHT_READ`.
    ///
    /// `ZX_ERR_PEER_CLOSED`  The other side of the fifo is closed.
    ///
    /// `ZX_ERR_SHOULD_WAIT`  The fifo is empty.
    ///
    /// ## See also
    ///
    ///  - [`zx_fifo_create()`]
    ///  - [`zx_fifo_write()`]
    ///
    /// [`zx_fifo_create()`]: fifo_create.md
    /// [`zx_fifo_write()`]: fifo_write.md
    strict Read(resource struct {
        handle Handle:FIFO;
        elem_size usize64;
    }) -> (struct {
        @voidptr
        data vector<byte>:MAX;
        actual_count usize64;
    }) error Status;

    /// ## Summary
    ///
    /// Write data to a fifo.
    ///
    /// ## Declaration
    ///
    /// ```c
    /// #include <zircon/syscalls.h>
    ///
    /// zx_status_t zx_fifo_write(zx_handle_t handle,
    ///                           size_t elem_size,
    ///                           const void* data,
    ///                           size_t count,
    ///                           size_t* actual_count);
    /// ```
    ///
    /// ## Description
    ///
    /// `zx_fifo_write()` attempts to write up to *count* elements
    /// (`count * elem_size` bytes) from *data* to the fifo specified by *handle*.
    ///
    /// Fewer elements may be written than requested if there is insufficient
    /// room in the fifo to contain all of them. The number of
    /// elements actually written is returned via *actual_count*.
    ///
    /// The element size specified by *elem_size* must match the element size
    /// that was passed into [`zx_fifo_create()`].
    ///
    /// *actual_count* is allowed to be NULL. This is useful when writing
    /// a single element: if *count* is 1 and `zx_fifo_write()` returns `ZX_OK`,
    /// *actual_count* is guaranteed to be 1 and thus can be safely ignored.
    ///
    /// It is not legal to write zero elements.
    ///
    /// ## Rights
    ///
    /// *handle* must be of type `ZX_OBJ_TYPE_FIFO` and have `ZX_RIGHT_WRITE`.
    ///
    /// ## Return value
    ///
    /// `zx_fifo_write()` returns `ZX_OK` on success, and returns
    /// the number of elements written (at least one) via *actual_count*.
    ///
    /// ## Errors
    ///
    /// `ZX_ERR_BAD_HANDLE`  *handle* is not a valid handle.
    ///
    /// `ZX_ERR_WRONG_TYPE`  *handle* is not a fifo handle.
    ///
    /// `ZX_ERR_INVALID_ARGS`  *data* is an invalid pointer or *actual_count*
    /// is an invalid pointer.
    ///
    /// `ZX_ERR_OUT_OF_RANGE`  *count* is zero or *elem_size* is not equal
    /// to the element size of the fifo.
    ///
    /// `ZX_ERR_ACCESS_DENIED`  *handle* does not have `ZX_RIGHT_WRITE`.
    ///
    /// `ZX_ERR_PEER_CLOSED`  The other side of the fifo is closed.
    ///
    /// `ZX_ERR_SHOULD_WAIT`  The fifo is full.
    ///
    /// ## See also
    ///
    ///  - [`zx_fifo_create()`]
    ///  - [`zx_fifo_read()`]
    ///
    /// [`zx_fifo_create()`]: fifo_create.md
    /// [`zx_fifo_read()`]: fifo_read.md
    strict Write(resource struct {
        handle Handle:FIFO;
        elem_size usize64;
        // TODO(joshuaseaton): vector<byte>
        @voidptr
        data experimental_pointer<byte>;
        count usize64;
    }) -> (struct {
        actual_count usize64;
    }) error Status;
};
