packages feed

glean-0.2.0.0: glean/rts/id.h

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 */

#pragma once

#include <folly/Format.h>
#include <folly/Hash.h>
#include <folly/container/HeterogeneousAccess.h>

namespace facebook {
namespace glean {
namespace rts {

const uint64_t FIRST_FREE_ID = 1024;
const uint64_t INVALID_ID = 0;

template <typename Tag>
struct WordId {
  // We might use uint32_t for pids in the future
  using word_type = uint64_t;

  // The FFI interface uses signed integers, because we need
  // to send data over Thrift which doesn't have unsigned types
  // and it's easier to convert at the FFI boundary.
  using thrift_word_type = int64_t;

  WordId() : val(0) {}

  static constexpr WordId invalid() {
    return WordId(INVALID_ID);
  }

  static constexpr WordId lowest() {
    return WordId(FIRST_FREE_ID);
  }

  explicit operator bool() const {
    return val != INVALID_ID;
  }

  bool operator==(const WordId& other) const {
    return val == other.val;
  }

  bool operator!=(const WordId& other) const {
    return val != other.val;
  }

  bool operator<=(const WordId& other) const {
    return val <= other.val;
  }

  bool operator<(const WordId& other) const {
    return val < other.val;
  }

  bool operator>=(const WordId& other) const {
    return val >= other.val;
  }

  bool operator>(const WordId& other) const {
    return val > other.val;
  }

  WordId operator+(word_type i) const {
    return WordId(val + i);
  }

  WordId& operator+=(word_type i) {
    val += i;
    return *this;
  }

  WordId& operator++() {
    ++val;
    return *this;
  }

  WordId operator++(int) {
    return WordId(val++);
  }

  WordId operator-(word_type i) const {
    assert(val > i);
    return WordId(val - i);
  }

  WordId& operator-=(word_type i) {
    assert(val > i);
    val -= i;
    return *this;
  }

  word_type operator-(WordId other) const {
    assert(val >= other.val);
    return val - other.val;
  }

  WordId& operator--() {
    assert(val > 1);
    --val;
    return *this;
  }

  WordId operator--(int) {
    assert(val > 1);
    return WordId(val--);
  }

  constexpr word_type toWord() const {
    return val;
  }

  static constexpr WordId fromWord(word_type x) {
    return WordId(x);
  }

  constexpr thrift_word_type toThrift() const {
    return static_cast<thrift_word_type>(val);
  }

  static constexpr WordId fromThrift(thrift_word_type id) {
    return WordId(id);
  }

 private:
  explicit constexpr WordId(word_type x) : val(x) {}

  word_type val = static_cast<word_type>(0);
};

template <typename Tag>
inline typename WordId<Tag>::word_type distance(
    WordId<Tag> from,
    WordId<Tag> to) {
  assert(from <= to);
  return to.toWord() - from.toWord();
}

struct Pid_tag;
struct Fid_tag;

using Pid = WordId<Pid_tag>;
using Id = WordId<Fid_tag>;

} // namespace rts
} // namespace glean
} // namespace facebook

namespace folly {

template <typename T>
class FormatValue<facebook::glean::rts::WordId<T>> {
 public:
  facebook::glean::rts::WordId<T> id;

  explicit FormatValue(facebook::glean::rts::WordId<T> i) : id(i) {}

  template <class Callback>
  void format(FormatArg& arg, Callback& cb) const {
    return FormatValue<typename facebook::glean::rts::WordId<T>::word_type>(
               id.toWord())
        .format(arg, cb);
  }
};

template <typename T>
struct hasher<facebook::glean::rts::WordId<T>> {
  using word_hasher =
      hasher<typename facebook::glean::rts::WordId<T>::word_type>;
  using folly_is_avalanching = typename word_hasher::folly_is_avalanching;

  size_t operator()(facebook::glean::rts::WordId<T> id) const noexcept {
    return Hash()(id.toWord());
  }
};

template <typename T>
struct HeterogeneousAccessHash<facebook::glean::rts::WordId<T>>
    : hasher<facebook::glean::rts::WordId<T>> {
  using is_transparent = void;
};

} // namespace folly