9#ifndef BOTAN_STRONG_TYPE_H_
10#define BOTAN_STRONG_TYPE_H_
12#include <botan/concepts.h>
19template <
typename T,
typename Tag,
typename... Capabilities>
25template <
typename... Ts>
29template <
typename... Ts>
32template <
typename... Ts>
38concept streamable =
requires(std::ostream& os, T a) { os << a; };
52template <
typename T,
typename Capability>
68template <
typename CapabilityT,
typename... Tags>
109 constexpr T&
get() & {
return m_value; }
113 constexpr const T&
get() const& {
return m_value; }
117 constexpr T&&
get() && {
return std::move(m_value); }
121 constexpr const T&&
get() const&& {
return std::move(m_value); }
136template <std::
integral T>
145template <concepts::container T>
172 template <
typename InputIt>
178 decltype(
auto)
begin() noexcept(noexcept(this->
get().
begin())) {
return this->
get().begin(); }
182 decltype(
auto)
begin()
const noexcept(
noexcept(this->
get().begin())) {
return this->
get().begin(); }
186 decltype(
auto)
end()
noexcept(
noexcept(this->
get().end())) {
return this->
get().end(); }
190 decltype(
auto)
end()
const noexcept(
noexcept(this->
get().end())) {
return this->
get().end(); }
194 decltype(
auto)
cbegin()
noexcept(
noexcept(this->
get().cbegin())) {
return this->
get().cbegin(); }
198 decltype(
auto)
cbegin()
const noexcept(
noexcept(this->
get().cbegin())) {
return this->
get().cbegin(); }
202 decltype(
auto)
cend()
noexcept(
noexcept(this->
get().cend())) {
return this->
get().cend(); }
206 decltype(
auto)
cend()
const noexcept(
noexcept(this->
get().cend())) {
return this->
get().cend(); }
217 return this->
get().empty();
239 template <
typename U>
240 decltype(
auto)
operator[](U&& i)
const noexcept(
noexcept(this->
get().operator[](i))) {
241 return this->
get()[std::forward<U>(i)];
247 template <
typename U>
248 decltype(
auto)
operator[](U&& i)
noexcept(
noexcept(this->
get().operator[](i))) {
249 return this->
get()[std::forward<U>(i)];
253template <concepts::container T>
254class Strong_Adapter<T> :
public Container_Strong_Adapter_Base<T> {
256 using Container_Strong_Adapter_Base<T>::Container_Strong_Adapter_Base;
259template <concepts::contiguous_container T>
260class Strong_Adapter<T> :
public Container_Strong_Adapter_Base<T> {
275 requires(std::same_as<T, std::string>)
279 decltype(
auto)
data() noexcept(noexcept(this->
get().
data())) {
return this->
get().data(); }
281 decltype(
auto)
data()
const noexcept(
noexcept(this->
get().data())) {
return this->
get().data(); }
297template <
typename T,
typename TagTypeT,
typename... Capabilities>
306 template <
typename CapabilityT>
308 return (std::is_same_v<CapabilityT, Capabilities> || ...);
312 using Tag = TagTypeT;
331 return std::forward<T>(t);
334 return std::forward<T>(t).get();
350template <
typename T,
typename ParamT>
351 requires std::constructible_from<T, ParamT> ||
352 (concepts::strong_type<T> && std::constructible_from<typename T::wrapped_type, ParamT>)
354 if constexpr(std::same_as<std::remove_cvref_t<ParamT>, T>) {
356 return std::forward<ParamT>(t);
357 }
else if constexpr(std::constructible_from<T, ParamT>) {
359 return T{std::forward<ParamT>(t)};
364 return T{
typename T::wrapped_type{std::forward<ParamT>(t)}};
381template <concepts::strong_type T>
384 using type =
typename T::wrapped_type;
407template <
typename T,
typename... Tags>
410 return os << v.
get();
419template <
typename T,
typename... Tags>
420 requires(std::equality_comparable<T>)
422 return lhs.
get() == rhs.
get();
431template <
typename T,
typename... Tags>
432 requires(std::three_way_comparable<T>)
434 return lhs.
get() <=> rhs.
get();
443template <std::integral T1, std::integral T2,
typename... Tags>
445 return a <=> b.
get();
454template <std::integral T1, std::integral T2,
typename... Tags>
456 return a.
get() <=> b;
465template <std::integral T1, std::integral T2,
typename... Tags>
476template <std::integral T1, std::integral T2,
typename... Tags>
487template <std::integral T1, std::integral T2,
typename... Tags>
499template <std::integral T1, std::integral T2,
typename... Tags>
511template <std::integral T,
typename... Tags>
522template <std::integral T1, std::integral T2,
typename... Tags>
534template <std::integral T1, std::integral T2,
typename... Tags>
546template <std::integral T,
typename... Tags>
557template <std::integral T1, std::integral T2,
typename... Tags>
569template <std::integral T1, std::integral T2,
typename... Tags>
581template <std::integral T,
typename... Tags>
592template <std::integral T1, std::integral T2,
typename... Tags>
604template <std::integral T1, std::integral T2,
typename... Tags>
616template <std::integral T,
typename... Tags>
627template <std::integral T1, std::integral T2,
typename... Tags>
639template <std::integral T1, std::integral T2,
typename... Tags>
651template <std::integral T,
typename... Tags>
662template <std::integral T1, std::integral T2,
typename... Tags>
674template <std::integral T1, std::integral T2,
typename... Tags>
686template <std::integral T,
typename... Tags>
697template <std::integral T1, std::integral T2,
typename... Tags>
709template <std::integral T1, std::integral T2,
typename... Tags>
721template <std::integral T,
typename... Tags>
732template <std::integral T1, std::integral T2,
typename... Tags>
735 return Strong<T2, Tags...>(a >> b.
get());
744template <std::integral T1, std::integral T2,
typename... Tags>
747 return Strong<T1, Tags...>(a.
get() >> b);
756template <std::integral T,
typename... Tags>
767template <std::integral T1, std::integral T2,
typename... Tags>
770 return Strong<T2, Tags...>(a << b.
get());
779template <std::integral T1, std::integral T2,
typename... Tags>
782 return Strong<T1, Tags...>(a.
get() << b);
791template <std::integral T,
typename... Tags>
802template <std::integral T1, std::integral T2,
typename... Tags>
815template <std::integral T,
typename... Tags>
827template <std::integral T1, std::integral T2,
typename... Tags>
840template <std::integral T,
typename... Tags>
852template <std::integral T1, std::integral T2,
typename... Tags>
865template <std::integral T,
typename... Tags>
877template <std::integral T1, std::integral T2,
typename... Tags>
890template <std::integral T,
typename... Tags>
902template <std::integral T1, std::integral T2,
typename... Tags>
915template <std::integral T,
typename... Tags>
927template <std::integral T1, std::integral T2,
typename... Tags>
940template <std::integral T,
typename... Tags>
952template <std::integral T1, std::integral T2,
typename... Tags>
965template <std::integral T,
typename... Tags>
977template <std::integral T1, std::integral T2,
typename... Tags>
990template <std::integral T,
typename... Tags>
1002template <std::integral T1, std::integral T2,
typename... Tags>
1015template <std::integral T,
typename... Tags>
1026template <std::integral T,
typename... Tags>
1038template <std::integral T,
typename... Tags>
1049template <std::integral T,
typename... Tags>
1061template <std::integral T,
typename... Tags>
1082template <concepts::contiguous_strong_type T>
1084 using underlying_span = std::
1085 conditional_t<std::is_const_v<T>, std::span<const typename T::value_type>, std::span<typename T::value_type>>;
1098 using pointer =
typename underlying_span::pointer;
1127 template <concepts::contiguous_strong_type T2>
1130 requires(std::is_same_v<T2, std::remove_const_t<T>>)
1131 : m_span(other.
get()) {}
1157 underlying_span
get()
const {
return m_span; }
1163 underlying_span
get() {
return m_span; }
1167 decltype(
auto)
data()
noexcept(
noexcept(this->m_span.data())) {
return this->m_span.data(); }
1171 decltype(
auto)
data()
const noexcept(
noexcept(this->m_span.data())) {
return this->m_span.data(); }
1175 decltype(
auto)
size()
const noexcept(
noexcept(this->m_span.size())) {
return this->m_span.size(); }
1179 bool empty() const noexcept(noexcept(this->m_span.
empty())) {
return this->m_span.empty(); }
1183 decltype(
auto)
begin() noexcept(noexcept(this->m_span.
begin())) {
return this->m_span.begin(); }
1187 decltype(
auto)
begin() const noexcept(noexcept(this->m_span.
begin())) {
return this->m_span.begin(); }
1191 decltype(
auto)
end() noexcept(noexcept(this->m_span.
end())) {
return this->m_span.end(); }
1195 decltype(
auto)
end() const noexcept(noexcept(this->m_span.
end())) {
return this->m_span.end(); }
1200 decltype(
auto)
operator[](
typename underlying_span::size_type i)
const noexcept {
return this->m_span[i]; }
1203 underlying_span m_span;
1213template <
typename T>
1216template <
typename T>
typename underlying_span::size_type size_type
The size type of the underlying span.
decltype(auto) begin() noexcept(noexcept(this->m_span.begin()))
StrongSpan()=default
Default constructor, creates an empty span.
decltype(auto) data() noexcept(noexcept(this->m_span.data()))
underlying_span get() const
typename underlying_span::value_type value_type
The element type of the underlying span.
decltype(auto) begin() const noexcept(noexcept(this->m_span.begin()))
StrongSpan(const StrongSpan &other)=default
StrongSpan(const StrongSpan< T2 > &other)
decltype(auto) end() noexcept(noexcept(this->m_span.end()))
StrongSpan & operator=(StrongSpan &&other)=default
StrongSpan(underlying_span span)
typename underlying_span::const_pointer const_pointer
The const pointer type of the underlying span.
bool empty() const noexcept(noexcept(this->m_span.empty()))
decltype(auto) operator[](typename underlying_span::size_type i) const noexcept
typename underlying_span::pointer pointer
The pointer type of the underlying span.
decltype(auto) data() const noexcept(noexcept(this->m_span.data()))
decltype(auto) end() const noexcept(noexcept(this->m_span.end()))
StrongSpan & operator=(const StrongSpan &other)=default
typename underlying_span::iterator iterator
The iterator type of the underlying span.
StrongSpan(StrongSpan &&other)=default
decltype(auto) size() const noexcept(noexcept(this->m_span.size()))
static constexpr bool has_capability()
typename T::iterator iterator
The iterator type of the wrapped container.
typename T::value_type value_type
The element type of the wrapped container.
decltype(auto) cbegin() const noexcept(noexcept(this->get().cbegin()))
decltype(auto) begin() noexcept(noexcept(this->get().begin()))
Container_Strong_Adapter_Base(InputIt begin, InputIt end)
decltype(auto) cend() noexcept(noexcept(this->get().cend()))
typename T::size_type size_type
The size type of the wrapped container.
decltype(auto) cend() const noexcept(noexcept(this->get().cend()))
decltype(auto) end() const noexcept(noexcept(this->get().end()))
void reserve(size_type size) noexcept(noexcept(this->get().reserve(size)))
size_type size() const noexcept(noexcept(this->get().size()))
decltype(auto) end() noexcept(noexcept(this->get().end()))
bool empty() const noexcept(noexcept(this->get().empty()))
decltype(auto) begin() const noexcept(noexcept(this->get().begin()))
Container_Strong_Adapter_Base(size_t size)
void resize(size_type size) noexcept(noexcept(this->get().resize(size)))
typename T::const_iterator const_iterator
The const iterator type of the wrapped container.
decltype(auto) cbegin() noexcept(noexcept(this->get().cbegin()))
Strong_Adapter(const char *str)
decltype(auto) data() const noexcept(noexcept(this->get().data()))
decltype(auto) data() noexcept(noexcept(this->get().data()))
typename T::const_pointer const_pointer
typename T::pointer pointer
Strong_Adapter(std::span< const typename Container_Strong_Adapter_Base< T >::value_type > span)
T wrapped_type
The type wrapped by this strong type.
constexpr const T & get() const &
Strong_Base(Strong_Base &&) noexcept=default
Move constructor.
Strong_Base()=default
Default constructor, value initializes the wrapped value.
constexpr const T && get() const &&
Strong_Base(const Strong_Base &)=default
Copy constructor.
constexpr bool has_capability
ASN1_Type operator|(ASN1_Type x, ASN1_Type y)
BigInt operator*(const BigInt &x, const BigInt &y)
constexpr auto operator&=(Strong< T1, Tags... > &a, T2 b)
OctetString operator^(const OctetString &k1, const OctetString &k2)
OctetString operator+(const OctetString &k1, const OctetString &k2)
constexpr auto operator++(Strong< T, Tags... > &a, int)
std::ostream & operator<<(std::ostream &out, const OID &oid)
constexpr auto operator>>=(Strong< T1, Tags... > &a, T2 b)
BigInt operator/(const BigInt &x, const BigInt &y)
BigInt operator-(const BigInt &x, const BigInt &y)
constexpr auto operator<<=(Strong< T1, Tags... > &a, T2 b)
constexpr decltype(auto) unwrap_strong_type(T &&t)
Generically unwraps a strong type to its underlying type.
constexpr auto operator|=(Strong< T1, Tags... > &a, T2 b)
typename detail::wrapped_type_helper< std::remove_cvref_t< T > >::type strong_type_wrapped_type
Extracts the wrapped type from a strong type.
constexpr decltype(auto) wrap_strong_type(ParamT &&t)
Wraps a value into a caller-defined (strong) type.
std::vector< uint8_t, Alloc > & operator^=(std::vector< uint8_t, Alloc > &out, const std::vector< uint8_t, Alloc2 > &in)
auto operator<=>(const Strong< T, Tags... > &lhs, const Strong< T, Tags... > &rhs)
constexpr bool is_strong_span_v
std::vector< T, Alloc > & operator+=(std::vector< T, Alloc > &out, const std::vector< T, Alloc2 > &in)
int operator>>(int fd, Pipe &pipe)
constexpr bool is_strong_type_v
bool operator==(const AlgorithmIdentifier &x, const AlgorithmIdentifier &y)
constexpr auto operator*=(Strong< T1, Tags... > &a, T2 b)
constexpr auto operator--(Strong< T, Tags... > &a, int)
constexpr auto operator/=(Strong< T1, Tags... > &a, T2 b)
constexpr auto operator-=(Strong< T1, Tags... > &a, T2 b)
ECIES_Flags operator&(ECIES_Flags a, ECIES_Flags b)
typename T::wrapped_type type
The resolved type.