---
title: llarp/layers/flow/flow_addr.hpp

---

# llarp/layers/flow/flow_addr.hpp



## Namespaces

| Name           |
| -------------- |
| **[llarp](Namespaces/namespacellarp.md)** <br>[crypto.hpp] |
| **[llarp::layers](Namespaces/namespacellarp_1_1layers.md)**  |
| **[llarp::layers::flow](Namespaces/namespacellarp_1_1layers_1_1flow.md)**  |
| **[std](Namespaces/namespacestd.md)** <br>STL namespace.  |

## Classes

|                | Name           |
| -------------- | -------------- |
| class | **[llarp::layers::flow::FlowAddr](Classes/classllarp_1_1layers_1_1flow_1_1FlowAddr.md)** <br>a long form .snode or .loki address  |
| struct | **[std::hash< llarp::layers::flow::FlowAddr >](Classes/structstd_1_1hash_3_01llarp_1_1layers_1_1flow_1_1FlowAddr_01_4.md)**  |




## Source code

```cpp
#pragma once

#include <array>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <llarp/util/aligned.hpp>
#include <numeric>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>

#include <algorithm>

#include <oxenc/variant.h>

#include <llarp/service/address.hpp>
#include <variant>
#include "llarp/router_id.hpp"
#include "llarp/util/types.hpp"

namespace llarp::layers::flow
{

  class FlowAddr
  {
   public:
    static constexpr std::size_t size = 32;
    using backing_array_t = AlignedBuffer<size>;

    enum class Kind : uint8_t
    {
      empty,
      snapp,
      snode,
    };

    FlowAddr() : FlowAddr{Kind::empty} {};

    explicit FlowAddr(std::string str);

    explicit FlowAddr(Kind k);

    FlowAddr(Kind k, const backing_array_t& data);

    FlowAddr(const FlowAddr&) = default;

    FlowAddr(FlowAddr&& other);

    FlowAddr&
    operator=(const FlowAddr& other) = default;

    FlowAddr&
    operator=(FlowAddr&& other) &;

    std::string
    ToString() const;

    constexpr bool
    operator==(const FlowAddr& other) const
    {
      return _kind == other._kind and _data == other._data;
    }

    constexpr auto
    kind() const
    {
      return _kind;
    }

    explicit constexpr
    operator backing_array_t&() &
    {
      return _data;
    }

    explicit constexpr operator const backing_array_t&() const&
    {
      return _data;
    }

    constexpr std::array<byte_t, size>&
    as_array()
    {
      return _data.as_array();
    }
    constexpr const std::array<byte_t, size>&
    as_array() const
    {
      return _data.as_array();
    }

    constexpr operator bool() const
    {
      return _kind != Kind::empty;
    }

   private:
    static Kind
    get_kind(std::string_view str);

    Kind _kind;
    backing_array_t _data;
  };

  template <typename T>
  static FlowAddr
  to_flow_addr(const T& addr)
  {
    if constexpr (std::is_same_v<T, RouterID>)
      return FlowAddr{FlowAddr::Kind::snode, addr};
    else if constexpr (std::is_same_v<T, service::Address>)
      return FlowAddr{FlowAddr::Kind::snapp, addr};
    else if constexpr (std::is_same_v<T, std::variant<RouterID, service::Address>>)
      return var::visit([](auto&& addr) { return to_flow_addr(addr); }, addr);
    else
      return FlowAddr{FlowAddr::Kind::empty};
  }

}  // namespace llarp::layers::flow

namespace llarp
{
  template <>
  inline constexpr bool IsToStringFormattable<llarp::layers::flow::FlowAddr> = true;

}

namespace std
{

  template <>
  struct hash<llarp::layers::flow::FlowAddr>
  {
    size_t
    operator()(const llarp::layers::flow::FlowAddr& addr) const noexcept
    {
      using backing_t = std::decay_t<decltype(addr)>::backing_array_t;
      return std::hash<backing_t>{}(reinterpret_cast<const backing_t&>(addr))
          ^ (std::hash<uint8_t>{}(static_cast<uint8_t>(addr.kind())) << 3);
    }
  };
}  // namespace std
```


-------------------------------

Updated on 2023-04-27 at 04:17:17 +0000
