// bslim_fuzzdataview.h                                               -*-C++-*-
#ifndef INCLUDED_BSLIM_FUZZDATAVIEW
#define INCLUDED_BSLIM_FUZZDATAVIEW

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide a view of a buffer of fuzz data bytes.
//
//@CLASSES:
//  bslim::FuzzDataView: reference-semantic type for fuzz data
//
//@SEE_ALSO: bslim_fuzzutil
//
//@DESCRIPTION: This component defines a reference-semantic class,
// 'bslim::FuzzDataView', providing a view to a non-modifiable buffer of fuzz
// data obtained from a fuzz testing harness (e.g., 'libFuzzer').
//
// See {http://bburl/BDEFuzzTesting} for details on how to build and run with
// fuzz testing enabled.
//
// Typically, this class is intended to be employed by a utility that takes an
// object of this class as an in-out parameter, consumes the bytes (updating
// the view so that the bytes are not used again), and returns objects of the
// type requested.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example 1: Creating a 'bsl::string'
///- - - - - - - - - - - - - - - - - -
// The following example demonstrates how to create a 'bsl::string' object from
// a 'FuzzDataView'.
//
// First, we construct a 'FuzzDataView' object, 'view0', from an array of
// bytes:
//..
//  const bsl::uint8_t data[] = {0x8A, 0x19, 0x0D, 0x44, 0x37, 0x0D,
//                               0x38, 0x5E, 0x9B, 0xAA, 0xF3, 0xDA};
//
//  bslim::FuzzDataView view0(data, sizeof(data));
//
//  assert(12 == view0.length());
//..
// Next, we take the first 3 bytes from 'view0' and store them in a new
// 'FuzzDataView' object, 'view1':
//..
//  bslim::FuzzDataView view1 = view0.removePrefix(3);
//
//  assert(3 == view1.length());
//  assert(9 == view0.length());
//..
// We confirm that 'removePrefix(3)' removed 3 bytes from 'view0' and that
// 'view1' has length 3.
//
// Then, we create a 'bsl::string' object from 'view1':
//..
//  bsl::string s1(view1.begin(), view1.end());
//
//  assert(3 == s1.length());
//..
// Finally, we create another 'bsl::string' with the remaining bytes of
// 'view0':
//..
//  bsl::string s2(view0.begin(), view0.end());
//
//  assert(9 == s2.length());
//..

#include <bslscm_version.h>

#include <bsls_assert.h>

#include <bsl_algorithm.h>  // min
#include <bsl_cstddef.h>    // size_t
#include <bsl_cstdint.h>    // uint8_t

namespace BloombergLP {
namespace bslim {

                             // ==================
                             // class FuzzDataView
                             // ==================

class FuzzDataView {
    // This type represents a view of a buffer of bytes provided by a fuzz
    // testing harness.

  private:
    // DATA
    const bsl::uint8_t *d_data_p;  // pointer to the data
    bsl::size_t         d_length;  // length of the view

  public:
    // CREATORS
    FuzzDataView(const bsl::uint8_t *data, bsl::size_t size);
        // Create a 'FuzzDataView' object from the specified fuzz 'data' and
        // 'size'. The behavior is undefined unless 'data || (0 == size)'.

    // FuzzDataView(const FuzzDataView& original)  = default;
        // Create a 'FuzzDataView' having the value of the specified 'original'
        // 'FuzzDataView'.  Note that this trivial copy constructor is
        // generated by the compiler.

    // ~FuzzDataView() = default;
        // Destroy this 'FuzzDataView' object.  Note that this trivial
        // destructor is generated by the compiler.

    // MANIPULATORS

    // FuzzDataView &operator=(const FuzzDataView& rhs) = default;
        // Assign to this FuzzDataView the value of the specified 'rhs'
        // 'FuzzDataView', and return a reference providing modifiable access
        // to this object.  Note that this trivial assignment operation is
        // generated by the compiler.

    FuzzDataView removePrefix(bsl::size_t numBytes);
        // Remove the specified initial 'numBytes' from this view if
        // 'numBytes <= length()' and remove 'length()' bytes otherwise; return
        // a view to the bytes that were removed.  Note that this method will
        // decrease the length of this view by 'min(numBytes, length())' bytes.

    FuzzDataView removeSuffix(bsl::size_t numBytes);
        // Remove the specified last 'numBytes' from this view if
        // 'numBytes <= length()' and remove 'length()' bytes otherwise; return
        // a view to the bytes that were removed.  Note that this method will
        // decrease the length of this view by 'min(numBytes, length())' bytes.

    // ACCESSORS
    const bsl::uint8_t *begin() const;
        // Return a const pointer to the beginning of the buffer.

    const bsl::uint8_t *end() const;
        // Return a const pointer to the end of the buffer.

    bsl::size_t length() const;
        // Return the length in bytes of the buffer.

    const bsl::uint8_t *data() const;
        // Return a pointer to the beginning of the buffer.
};

// ============================================================================
//                            INLINE DEFINITIONS
// ============================================================================

                            // ------------------
                            // class FuzzDataView
                            // ------------------

// CREATORS
inline
FuzzDataView::FuzzDataView(const bsl::uint8_t *data, bsl::size_t size)
: d_data_p(data)
, d_length(size)
{
    BSLS_ASSERT(data || (0 == size));
}

// MANIPULATORS
inline
FuzzDataView FuzzDataView::removePrefix(bsl::size_t numBytes)
{
    FuzzDataView prefix(d_data_p, bsl::min(numBytes, length()));

    d_data_p += prefix.length();
    d_length -= prefix.length();

    return prefix;
}

inline
FuzzDataView FuzzDataView::removeSuffix(bsl::size_t numBytes)
{
    bsl::size_t num = bsl::min(numBytes, length());

    FuzzDataView suffix(end() - num, num);
    d_length -= num;

    return suffix;
}

// ACCESSORS
inline
const bsl::uint8_t* FuzzDataView::begin() const
{
    return d_data_p;
}

inline
const bsl::uint8_t* FuzzDataView::end() const
{
    return d_data_p + d_length;
}

inline
bsl::size_t FuzzDataView::length() const
{
    return d_length;
}

inline
const bsl::uint8_t *FuzzDataView::data() const
{
    return d_data_p;
}

}  // close package namespace
}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2021 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------