llarp/util/aligned.hpp

Namespaces

Name
llarp
[crypto.hpp]
llarp::service
llarp::routing
fmt
std
STL namespace.

Classes

Name
struct llarp::AssignPtr
Assigns a value from a bare pointer to a fixzed size container.
struct fmt::range_format_kind< T, char, std::enable_if_t< llarp::is_aligned_buffer< T > > >
disable range formatting for aligned buffer.
struct fmt::formatter< T, char, std::enable_if_t< llarp::is_aligned_buffer< T > and not llarp::IsToStringFormattable< T > > >
struct std::hash< array< uint8_t, sz > >

Functions

Name
void randombytes(unsigned char *const ptr, unsigned long long sz)
int sodium_is_zero(const unsigned char * n, const size_t nlen)
bool bencode_write_bytestring(llarp_buffer_t * , const void * , size_t )
bool bencode_read_string(llarp_buffer_t * , llarp_buffer_t * )

Defines

Name
ALIGNED_BUFFER_MEMBERS_NO_OPERS(_Kind_t, _sz)
ALIGNED_BUFFER_MEMBERS_NO_CTOR(_Kind_t, _sz)
ALIGNED_BUFFER_MEMBERS_NO_SERIALIZE(_Kind_t, _sz)
ALIGNED_BUFFER_MEMBERS(_kind_t, _sz)

Functions Documentation

function randombytes

void randombytes(
    unsigned char *const ptr,
    unsigned long long sz
)

function sodium_is_zero

int sodium_is_zero(
    const unsigned char * n,
    const size_t nlen
)

function bencode_write_bytestring

bool bencode_write_bytestring(
    llarp_buffer_t * ,
    const void * ,
    size_t 
)

function bencode_read_string

bool bencode_read_string(
    llarp_buffer_t * ,
    llarp_buffer_t * 
)

Macros Documentation

define ALIGNED_BUFFER_MEMBERS_NO_OPERS

#define ALIGNED_BUFFER_MEMBERS_NO_OPERS(
    _Kind_t,
    _sz
)

define ALIGNED_BUFFER_MEMBERS_NO_CTOR

#define ALIGNED_BUFFER_MEMBERS_NO_CTOR(
    _Kind_t,
    _sz
)
  ALIGNED_BUFFER_MEMBERS_NO_OPERS(_Kind_t, _sz)                                   \
 public:                                                                          \
  constexpr bool operator==(const _Kind_t& other) const noexcept                  \
  {                                                                               \
    return as_array() == other.as_array();                                        \
  }                                                                               \
  constexpr bool operator!=(const _Kind_t& other) const noexcept                  \
  {                                                                               \
    return not(*this == other);                                                   \
  }                                                                               \
  constexpr bool operator<(const _Kind_t& other) const noexcept                   \
  {                                                                               \
    return as_array() < other.as_array();                                         \
  }                                                                               \
  _Kind_t& operator=(const byte_t* ptr) noexcept                                  \
  {                                                                               \
    return AssignPtr{*this} = ptr;                                                \
  }                                                                               \
  template <typename Other_t>                                                     \
    requires llarp::is_aligned_buffer<Other_t>                                    \
  constexpr _Kind_t operator^(const Other_t& other) const noexcept                \
  {                                                                               \
    static_assert(other.size() == size());                                        \
    _Kind_t ret{};                                                                \
    std::transform(begin(), end(), other.begin(), ret.begin(), std::bit_xor<>{}); \
    return ret;                                                                   \
  }

define ALIGNED_BUFFER_MEMBERS_NO_SERIALIZE

#define ALIGNED_BUFFER_MEMBERS_NO_SERIALIZE(
    _Kind_t,
    _sz
)
  ALIGNED_BUFFER_MEMBERS_NO_CTOR(_Kind_t, _sz)            \
 public:                                                  \
  _Kind_t() = default;                                    \
  explicit _Kind_t(const byte_t* buf)                     \
  {                                                       \
    *this = buf;                                          \
  }                                                       \
  template <typename Kind_t>                              \
    requires llarp::is_aligned_buffer<Kind_t>             \
  explicit _Kind_t(const Kind_t& data)                    \
  {                                                       \
    static_assert(data.size() == size());                 \
    std::copy_n(data.begin(), size(), m_data.begin());    \
  }

define ALIGNED_BUFFER_MEMBERS

#define ALIGNED_BUFFER_MEMBERS(
    _kind_t,
    _sz
)
  ALIGNED_BUFFER_MEMBERS_NO_SERIALIZE(_kind_t, _sz)       \
 public:                                                  \
  inline std::string ToHex() const noexcept               \
  {                                                       \
    return oxenc::to_hex(begin(), end());                 \
  }                                                       \
  inline bool BEncode(llarp_buffer_t* buf) const          \
  {                                                       \
    return bencode_write_bytestring(buf, data(), size()); \
  }                                                       \
  inline bool BDecode(llarp_buffer_t* buf)                \
  {                                                       \
    llarp_buffer_t str{};                                 \
    if (not bencode_read_string(buf, &str))               \
      return false;                                       \
    if (str.sz != size())                                 \
      return false;                                       \
    std::copy_n(str.base, size(), begin());               \
    return true;                                          \
  }                                                       \
  inline void Zero()                                      \
  {                                                       \
    llarp::Zero(data(), size());                          \
  }                                                       \
  inline bool IsZero() const                              \
  {                                                       \
    return ::sodium_is_zero(data(), size());              \
  }

Source code

#pragma once
#include "types.hpp"
#include "buffer.hpp"
#include <fmt/ranges.h>
#include <llarp/util/formattable.hpp>

#include <oxenc/hex.h>

#include <array>
#include <cstddef>
#include <memory>
#include <numeric>
#include <type_traits>
#include <compare>

extern "C"
{
  extern void
  randombytes(unsigned char* const ptr, unsigned long long sz);

  extern int
  sodium_is_zero(const unsigned char* n, const size_t nlen);
}

bool
bencode_write_bytestring(llarp_buffer_t*, const void*, size_t);
bool
bencode_read_string(llarp_buffer_t*, llarp_buffer_t*);

namespace llarp::service
{
  struct ConvoTag;
}

namespace llarp
{

  void
  Zero(void*, size_t);

  template <typename Container_t>
  struct AssignPtr
  {
    Container_t& ref;
    Container_t&
    operator=(const byte_t* ptr)
    {
      std::memcpy(ref.data(), ptr, ref.size());
      return ref;
    }
  };

  template <size_t sz>
  using AlignedBuffer = std::array<byte_t, sz>;

  // True if T implements aligned buffer style interface.
  template <typename T>
  constexpr inline bool is_aligned_buffer = false;

  template <typename T>
  constexpr inline bool is_std_array = false;

  template <size_t sz>
  constexpr inline bool is_std_array<std::array<uint8_t, sz>> = true;

  template <typename T>
    requires is_aligned_buffer<T>
  void
  Randomize(T& t)
  {
    ::randombytes(t.data(), t.size());
    if constexpr (std::is_same_v<T, service::ConvoTag>)
      t.data()[0] = 0xfc;
  }

  template <typename T>
    requires is_aligned_buffer<T> or is_std_array<T>
  size_t
  overhead_for(const T& t) noexcept
  {
    if (::sodium_is_zero(t.data(), t.size()))
      return 0;
    // bencode overhead.
    return std::floor(std::log10(t.size())) + 1 + 1 + t.size();
  }

  template <typename Int_t>
    requires std::is_integral_v<Int_t> and std::is_unsigned_v<Int_t>
  size_t
  overhead_for(const Int_t& i) noexcept
  {
    // bencode overhead
    if (i == 0)
      return 1 + 2;
    return std::floor(std::log10(i)) + 1 + 2;
  }

  namespace routing
  {
    struct IMessage;
  }

  template <typename Msg_t>
    requires std::is_base_of_v<routing::IMessage, Msg_t>
  size_t
  overhead_for(const Msg_t& msg) noexcept
  {
    return msg.overhead();
  }

}  // namespace llarp

namespace fmt
{
  template <typename T>
  struct range_format_kind<T, char, std::enable_if_t<llarp::is_aligned_buffer<T>>>
  {
    static constexpr auto value = range_format::disabled;
  };

  // Any aligned buffer like gets hex formatted when output:
  template <typename T>
  struct formatter<
      T,
      char,
      std::enable_if_t<llarp::is_aligned_buffer<T> and not llarp::IsToStringFormattable<T>>>
      : formatter<std::string_view>
  {
    template <typename FormatContext>
    auto
    format(const T& val, FormatContext& ctx) const
    {
      auto it = oxenc::hex_encoder{val.begin(), val.end()};
      return std::copy(it, it.end(), ctx.out());
    }
  };
}  // namespace fmt

namespace std
{
  template <size_t sz>
  struct hash<array<uint8_t, sz>>
  {
    static_assert(sz >= sizeof(size_t));

    std::size_t
    operator()(const array<uint8_t, sz>& buf) const noexcept
    {
      std::size_t h{};
      std::memcpy(&h, buf.data(), sizeof(std::size_t));
      return h;
    }
  };
}  // namespace std

#define ALIGNED_BUFFER_MEMBERS_NO_OPERS(_Kind_t, _sz)                                  \
 public:                                                                               \
  static constexpr size_t SIZE = _sz;                                                  \
  constexpr size_t size() const noexcept                                               \
  {                                                                                    \
    return SIZE;                                                                       \
  }                                                                                    \
  using Data = std::array<byte_t, SIZE>;                                               \
  constexpr byte_t* data() noexcept                                                    \
  {                                                                                    \
    return m_data.data();                                                              \
  }                                                                                    \
  constexpr const byte_t* data() const noexcept                                        \
  {                                                                                    \
    return m_data.data();                                                              \
  }                                                                                    \
  constexpr const std::array<byte_t, SIZE>& as_array() const noexcept                  \
  {                                                                                    \
    return m_data;                                                                     \
  }                                                                                    \
  using iter_t = Data::iterator;                                                       \
  using c_iter_t = Data::const_iterator;                                               \
  constexpr iter_t begin() noexcept                                                    \
  {                                                                                    \
    return m_data.begin();                                                             \
  }                                                                                    \
  constexpr iter_t end() noexcept                                                      \
  {                                                                                    \
    return m_data.end();                                                               \
  }                                                                                    \
  constexpr c_iter_t begin() const noexcept                                            \
  {                                                                                    \
    return m_data.begin();                                                             \
  }                                                                                    \
  constexpr c_iter_t end() const noexcept                                              \
  {                                                                                    \
    return m_data.end();                                                               \
  }                                                                                    \
  std::string_view ToView() const noexcept                                             \
  {                                                                                    \
    return std::string_view{                                                           \
        reinterpret_cast<const char*>(begin()), reinterpret_cast<const char*>(end())}; \
  }                                                                                    \
  void Fill(byte_t ch) noexcept                                                        \
  {                                                                                    \
    m_data.fill(ch);                                                                   \
  }                                                                                    \
                                                                                       \
 private:                                                                              \
  Data m_data{};

#define ALIGNED_BUFFER_MEMBERS_NO_CTOR(_Kind_t, _sz)                              \
  ALIGNED_BUFFER_MEMBERS_NO_OPERS(_Kind_t, _sz)                                   \
 public:                                                                          \
  constexpr bool operator==(const _Kind_t& other) const noexcept                  \
  {                                                                               \
    return as_array() == other.as_array();                                        \
  }                                                                               \
  constexpr bool operator!=(const _Kind_t& other) const noexcept                  \
  {                                                                               \
    return not(*this == other);                                                   \
  }                                                                               \
  constexpr bool operator<(const _Kind_t& other) const noexcept                   \
  {                                                                               \
    return as_array() < other.as_array();                                         \
  }                                                                               \
  _Kind_t& operator=(const byte_t* ptr) noexcept                                  \
  {                                                                               \
    return AssignPtr{*this} = ptr;                                                \
  }                                                                               \
  template <typename Other_t>                                                     \
    requires llarp::is_aligned_buffer<Other_t>                                    \
  constexpr _Kind_t operator^(const Other_t& other) const noexcept                \
  {                                                                               \
    static_assert(other.size() == size());                                        \
    _Kind_t ret{};                                                                \
    std::transform(begin(), end(), other.begin(), ret.begin(), std::bit_xor<>{}); \
    return ret;                                                                   \
  }

#define ALIGNED_BUFFER_MEMBERS_NO_SERIALIZE(_Kind_t, _sz) \
  ALIGNED_BUFFER_MEMBERS_NO_CTOR(_Kind_t, _sz)            \
 public:                                                  \
  _Kind_t() = default;                                    \
  explicit _Kind_t(const byte_t* buf)                     \
  {                                                       \
    *this = buf;                                          \
  }                                                       \
  template <typename Kind_t>                              \
    requires llarp::is_aligned_buffer<Kind_t>             \
  explicit _Kind_t(const Kind_t& data)                    \
  {                                                       \
    static_assert(data.size() == size());                 \
    std::copy_n(data.begin(), size(), m_data.begin());    \
  }

#define ALIGNED_BUFFER_MEMBERS(_kind_t, _sz)              \
  ALIGNED_BUFFER_MEMBERS_NO_SERIALIZE(_kind_t, _sz)       \
 public:                                                  \
  inline std::string ToHex() const noexcept               \
  {                                                       \
    return oxenc::to_hex(begin(), end());                 \
  }                                                       \
  inline bool BEncode(llarp_buffer_t* buf) const          \
  {                                                       \
    return bencode_write_bytestring(buf, data(), size()); \
  }                                                       \
  inline bool BDecode(llarp_buffer_t* buf)                \
  {                                                       \
    llarp_buffer_t str{};                                 \
    if (not bencode_read_string(buf, &str))               \
      return false;                                       \
    if (str.sz != size())                                 \
      return false;                                       \
    std::copy_n(str.base, size(), begin());               \
    return true;                                          \
  }                                                       \
  inline void Zero()                                      \
  {                                                       \
    llarp::Zero(data(), size());                          \
  }                                                       \
  inline bool IsZero() const                              \
  {                                                       \
    return ::sodium_is_zero(data(), size());              \
  }

Updated on 2026-04-01 at 23:35:40 +0000