// Copyright 2014 The Crashpad Authors
//
// 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.

#ifndef CRASHPAD_UTIL_MISC_UUID_H_
#define CRASHPAD_UTIL_MISC_UUID_H_

#include <stdint.h>

#include <string>
#include <string_view>

#include "build/build_config.h"

#if BUILDFLAG(IS_WIN)
#include <rpc.h>
#endif

namespace crashpad {

//! \brief A universally unique identifier (%UUID).
//!
//! An alternate term for %UUID is “globally unique identifier” (GUID), used
//! primarily by Microsoft.
//!
//! A %UUID is a unique 128-bit number specified by RFC 4122.
//!
//! This is a POD structure.
struct UUID {
  bool operator==(const UUID& that) const;
  bool operator!=(const UUID& that) const { return !operator==(that); }
  bool operator<(const UUID& that) const;

  //! \brief Initializes the %UUID to zero.
  void InitializeToZero();

  //! \brief Initializes the %UUID from a sequence of bytes.
  //!
  //! \a bytes is taken as a %UUID laid out in big-endian format in memory. On
  //! little-endian machines, appropriate byte-swapping will be performed to
  //! initialize an object’s data members.
  //!
  //! \param[in] bytes A buffer of exactly 16 bytes that will be assigned to the
  //!     %UUID.
  void InitializeFromBytes(const uint8_t* bytes);

  //! \brief Initializes the %UUID from a RFC 4122 §3 formatted string.
  //!
  //! \param[in] string A string of the form
  //!     `"00112233-4455-6677-8899-aabbccddeeff"`.
  //!
  //! \return `true` if the string was formatted correctly and the object has
  //!     been initialized with the data. `false` if the string could not be
  //!     parsed, with the object state untouched.
  bool InitializeFromString(std::string_view string);
#if BUILDFLAG(IS_WIN) || DOXYGEN
  bool InitializeFromString(std::wstring_view string);
#endif  // BUILDFLAG(IS_WIN)

  //! \brief Initializes the %UUID using a standard system facility to generate
  //!     the value.
  //!
  //! \return `true` if the %UUID was initialized correctly, `false` otherwise
  //!     with a message logged.
  bool InitializeWithNew();

#if BUILDFLAG(IS_WIN) || DOXYGEN
  //! \brief Initializes the %UUID from a system `UUID` or `GUID` structure.
  //!
  //! \param[in] system_uuid A system `UUID` or `GUID` structure.
  void InitializeFromSystemUUID(const ::UUID* system_uuid);
#endif  // BUILDFLAG(IS_WIN)

  //! \brief Checks whether the %UUID is zero (all bytes are 0).
  //!
  //! \return `true` if the %UUID is all zeros, `false` otherwise.
  bool IsZero() const;

  //! \brief Formats the %UUID per RFC 4122 §3.
  //!
  //! \return A string of the form `"00112233-4455-6677-8899-aabbccddeeff"`.
  std::string ToString() const;

#if BUILDFLAG(IS_WIN) || DOXYGEN
  //! \brief The same as ToString, but returned as a wstring.
  std::wstring ToWString() const;
#endif  // BUILDFLAG(IS_WIN)

  // These fields are laid out according to RFC 4122 §4.1.2.
  uint32_t data_1;
  uint16_t data_2;
  uint16_t data_3;
  uint8_t data_4[2];
  uint8_t data_5[6];
};

}  // namespace crashpad

#endif  // CRASHPAD_UTIL_MISC_UUID_H_
