// Copyright 2017 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.

#ifndef SRC_LIB_STORAGE_VFS_CPP_PSEUDO_FILE_H_
#define SRC_LIB_STORAGE_VFS_CPP_PSEUDO_FILE_H_

#include <lib/fit/function.h>
#include <zircon/types.h>

#include <cstddef>
#include <string_view>

#include <fbl/macros.h>
#include <fbl/ref_ptr.h>
#include <fbl/string.h>

#include "vnode.h"

namespace fs {

// A pseudo-file is a file-like object whose content is generated and modified dynamically
// on-the-fly by invoking handler functions rather than being directly persisted as a sequence of
// bytes.
//
// This class is designed to allow programs to publish read-only, write-only, or read-write
// properties such as configuration options, debug flags, and dumps of internal state which may
// change dynamically.
//
// A pseudo-file is readable when it has a non-null |ReadHandler|.  Typically the read handler will
// output a UTF-8 representation of some element of the program's state, or return an error if the
// requested information is not available.  The read handler is not expected to have side-effects
// (but it can).
//
// A pseudo-file is writable when it has a non-null |WriteHandler|.  Typically the write handler
// will parse the input in a UTF-8 representation and update the program's state in response, or
// return an error if the input is invalid.
//
// Although pseudo-files usually contain text, they can also be used for binary data.
//
// There is no guarantee that data written to the pseudo-file can be read back from the pseudo-file
// in the same form; it's not a real file after all.
//
// This is an abstract class.  The concrete implementations are |BufferedPseudoFile| and
// |UnbufferedPseudoFile|.
class PseudoFile : public Vnode {
 public:
  // Handler called to read from the pseudo-file.
  using ReadHandler = fit::function<zx_status_t(fbl::String* output)>;

  // Handler called to write into the pseudo-file.
  using WriteHandler = fit::function<zx_status_t(std::string_view input)>;

  ~PseudoFile() override;

  // |Vnode| implementation:
  VnodeProtocolSet GetProtocols() const final;
  bool ValidateRights(Rights rights) const override;
  zx_status_t GetAttributes(fs::VnodeAttributes* a) final;

  zx_status_t GetNodeInfoForProtocol(VnodeProtocol protocol, Rights rights,
                                     VnodeRepresentation* info) final;

 protected:
  PseudoFile(ReadHandler read_handler, WriteHandler write_handler);

  ReadHandler const read_handler_;
  WriteHandler const write_handler_;

  DISALLOW_COPY_ASSIGN_AND_MOVE(PseudoFile);
};

// Buffered pseudo-file.
//
// This variant is optimized for incrementally reading and writing properties which are larger than
// can typically be read or written by the client in a single I/O transaction.
//
// In read mode, the pseudo-file invokes its read handler when the file is opened and retains the
// content in an output buffer which the client incrementally reads from and can seek within.
//
// In write mode, the client incrementally writes into and seeks within an input buffer which the
// pseudo-file delivers as a whole to the write handler when the file is closed.  Truncation is also
// supported.
//
// Each client has its own separate output and input buffers.  Writing into the output buffer does
// not affect the contents of the client's input buffer or that of any other client.  Changes to the
// underlying state of the pseudo-file are not observed by the client until it closes and re-opens
// the file.
//
// This class is thread-safe.
class BufferedPseudoFile : public PseudoFile {
 public:
  // Construct with fbl::MakeRefCounted.

 private:
  friend fbl::internal::MakeRefCountedHelper<BufferedPseudoFile>;
  friend fbl::RefPtr<BufferedPseudoFile>;

  class Content final : public Vnode {
   public:
    // |Vnode| implementation:
    VnodeProtocolSet GetProtocols() const final;
    zx_status_t GetAttributes(fs::VnodeAttributes* a) final;
    zx_status_t Read(void* data, size_t length, size_t offset, size_t* out_actual) final;
    zx_status_t Write(const void* data, size_t length, size_t offset, size_t* out_actual) final;
    zx_status_t Append(const void* data, size_t length, size_t* out_end, size_t* out_actual) final;
    zx_status_t Truncate(size_t length) final;
    zx_status_t GetNodeInfoForProtocol(VnodeProtocol protocol, Rights rights,
                                       VnodeRepresentation* info) final;

   private:
    friend fbl::internal::MakeRefCountedHelper<Content>;
    friend fbl::RefPtr<Content>;

    Content(fbl::RefPtr<BufferedPseudoFile> file, VnodeConnectionOptions options,
            fbl::String output);
    ~Content() override;

    // Vnode protected implementation:
    zx_status_t CloseNode() final;

    void SetInputLength(size_t length);

    fbl::RefPtr<BufferedPseudoFile> const file_;
    const VnodeConnectionOptions options_;
    fbl::String const output_;

    char* input_data_ = nullptr;
    size_t input_length_ = 0u;
  };

  // Creates a buffered pseudo-file.
  //
  // If the |read_handler| is null, then the pseudo-file is considered not readable. If the
  // |write_handler| is null, then the pseudo-file is considered not writable. The
  // |input_buffer_capacity| determines the maximum number of bytes which can be written to the
  // pseudo-file's input buffer when it it opened for writing.
  explicit BufferedPseudoFile(ReadHandler read_handler = ReadHandler(),
                              WriteHandler write_handler = WriteHandler(),
                              size_t input_buffer_capacity = 1024);

  ~BufferedPseudoFile() override;

  // |Vnode| protected implementation:
  zx_status_t OpenNode(ValidatedOptions options, fbl::RefPtr<Vnode>* out_redirect) final;

  size_t const input_buffer_capacity_;

  DISALLOW_COPY_ASSIGN_AND_MOVE(BufferedPseudoFile);
};

// Unbuffered pseudo-file.
//
// This variant is optimized for atomically reading and writing small properties. Unlike buffered
// pseudo-files, it is not necessary to re-open the pseudo-file to observe side-effects; the client
// can simply seek back to the zero offset and read or write again.
//
// Because reads and writes are not buffered, the maximum size of the property is limited to what
// will fit in a single I/O transaction.  Unbuffered pseudo-files generally work best for properties
// which are likely to be polled or repeatedly modified and which are no larger than the nominal I/O
// buffer size used by the intended clients.
//
// As a conservative guideline, we recommend using |BufferedPseudoFile| instead for content larger
// than the system page size.
//
// In read mode, the pseudo-file invokes its read handler each time |Read()| is called with a seek
// offset of 0, returning at most as many bytes as the client requested and discarding the remainder
// (if any).
//
// Reading with a non-zero seek offset returns empty data, indicating end of file.
//
// In write mode, the pseudo-file invokes its write handler each time |Write()| with a seek offset
// of 0 is called, passing all of the bytes written by the client as the input string.  Likewise,
// |Append()| invokes the write handler each time it is called and returns a new end of file offset
// of 0.
//
// Writing with a non-zero seek offset returns |ZX_ERR_NO_SPACE|, indicating an attempt to write
// data beyond what was accepted by the write handler.
//
// Opening the file in create mode or truncating it to zero length then closing it without an
// intervening write is equivalent to writing 0 bytes.  This adaptation improves compatibility with
// command-line operations which are intended to modify the file in-place such as: `echo "data" >
// pseudo-file`.
//
// Truncating to a non-zero length returns |ZX_ERR_INVALID_ARGS|.
//
// This class is thread-safe.
class UnbufferedPseudoFile : public PseudoFile {
 public:
  // Construct with fbl::MakeRefCounted.

 private:
  friend fbl::internal::MakeRefCountedHelper<UnbufferedPseudoFile>;
  friend fbl::RefPtr<UnbufferedPseudoFile>;

  class Content final : public Vnode {
   public:
    // |Vnode| implementation:
    VnodeProtocolSet GetProtocols() const final;
    zx_status_t GetAttributes(fs::VnodeAttributes* a) final;
    zx_status_t Read(void* data, size_t length, size_t offset, size_t* out_actual) final;
    zx_status_t Write(const void* data, size_t length, size_t offset, size_t* out_actual) final;
    zx_status_t Append(const void* data, size_t length, size_t* out_end, size_t* out_actual) final;
    zx_status_t Truncate(size_t length) final;
    zx_status_t GetNodeInfoForProtocol(VnodeProtocol protocol, Rights rights,
                                       VnodeRepresentation* info) final;

   private:
    friend fbl::internal::MakeRefCountedHelper<Content>;
    friend fbl::RefPtr<Content>;

    Content(fbl::RefPtr<UnbufferedPseudoFile> file, VnodeConnectionOptions options);
    ~Content() override;

    // Vnode protected implementation.
    zx_status_t OpenNode(ValidatedOptions options, fbl::RefPtr<Vnode>* out_redirect) final;
    zx_status_t CloseNode() final;

    fbl::RefPtr<UnbufferedPseudoFile> const file_;
    const VnodeConnectionOptions options_;

    bool truncated_since_last_successful_write_;
  };

  // Creates an unbuffered pseudo-file.
  //
  // If the |read_handler| is null, then the pseudo-file is considered not readable.
  // If the |write_handler| is null, then the pseudo-file is considered not writable.
  explicit UnbufferedPseudoFile(ReadHandler read_handler = ReadHandler(),
                                WriteHandler write_handler = WriteHandler());

  ~UnbufferedPseudoFile() override;

  // |Vnode| protected implementation:
  zx_status_t OpenNode(ValidatedOptions options, fbl::RefPtr<Vnode>* out_redirect) final;

  DISALLOW_COPY_ASSIGN_AND_MOVE(UnbufferedPseudoFile);
};

}  // namespace fs

#endif  // SRC_LIB_STORAGE_VFS_CPP_PSEUDO_FILE_H_
