22#pragma once
33
44#include < nonstd/expected.hpp>
5+ #include < span>
56
67#include " bencode/detail/symbol.hpp"
78#include " bencode/detail/utils.hpp"
@@ -40,35 +41,54 @@ convert_from_bvalue_string_impl(customization_point_type<const char*>,
4041 return s.c_str ();
4142}
4243
43- // Conversion via iterators pair constructor
44+ // Conversion to T via pair of iterators
4445
45- template <typename T, typename Policy>
46+ template <typename T, basic_bvalue_instantiation U, typename Policy = typename std:: remove_cvref_t <U>::policy_type >
4647 requires
47- std::constructible_from<
48- typename policy_string_t <Policy>::value_type, rng::range_value_t <T>> &&
49- std::constructible_from<
50- policy_string_t <Policy>, rng:: iterator_t <T>, rng::sentinel_t <T >>
48+ std::constructible_from<typename policy_string_t <Policy>::value_type,
49+ rng::range_value_t <T>> &&
50+ std::constructible_from<T, rng:: iterator_t < policy_string_t <Policy>>,
51+ rng::sentinel_t <policy_string_t <Policy> >>
5152constexpr nonstd::expected<T, conversion_errc>
5253convert_from_bvalue_string_impl (customization_point_type<T>,
53- const basic_bvalue<Policy> & b,
54- priority_tag<1 >) noexcept
54+ U& & b,
55+ priority_tag<2 >) noexcept
5556{
5657 if (!holds_string (b)) [[unlikely]]
5758 return nonstd::make_unexpected (conversion_errc::not_string_type);
5859
59- const auto & bstring = get_string (b);
60+ auto & bstring = get_string (b);
6061 try { return T (rng::begin (bstring), rng::end (bstring)); }
6162 catch (...) { return nonstd::make_unexpected (conversion_errc::construction_error); }
6263}
6364
65+ // Conversion to T via pointer and size
66+
67+ template <typename T, basic_bvalue_instantiation U, typename Policy = typename std::remove_cvref_t <U>::policy_type>
68+ requires rng::contiguous_range<policy_string_t <Policy>> &&
69+ std::constructible_from<T, rng::range_value_t <policy_string_t <Policy>>*,
70+ rng::range_size_t <policy_string_t <Policy>>>
71+ constexpr nonstd::expected<T, conversion_errc>
72+ convert_from_bvalue_string_impl (customization_point_type<T>,
73+ U&& b,
74+ priority_tag<3 >) noexcept
75+ {
76+ if (!holds_string (b)) [[unlikely]]
77+ return nonstd::make_unexpected (conversion_errc::not_string_type);
78+
79+ auto & bstring = get_string (b);
80+ try { return T (rng::data (bstring), rng::size (bstring)); }
81+ catch (...) { return nonstd::make_unexpected (conversion_errc::construction_error); }
82+ }
83+
6484// Conversion through std::string_view.
6585
66- template <typename T, typename Policy>
86+ template <typename T, basic_bvalue_instantiation U, typename Policy = typename std:: remove_cvref_t <U>::policy_type >
6787 requires std::constructible_from<T, std::string_view> &&
6888 std::convertible_to<policy_string_t <Policy>, std::string_view>
6989constexpr nonstd::expected<T, conversion_errc>
7090convert_from_bvalue_string_impl (customization_point_type<T>,
71- const basic_bvalue<Policy> & b,
91+ U& & b,
7292 priority_tag<0 >) noexcept
7393
7494{
@@ -79,23 +99,23 @@ convert_from_bvalue_string_impl(customization_point_type<T>,
7999}
80100
81101
82- // Conversion of byte stringsauto
102+ // Conversion of byte strings auto
83103
84- template <typename T, typename Policy>
85- requires std::same_as<rng::range_value_t <T>, std::byte> &&
86- std::constructible_from<T, const std::byte *, const std::byte *> &&
104+ template <typename T, basic_bvalue_instantiation U, typename Policy = typename std:: remove_cvref_t <U>::policy_type >
105+ requires std::same_as<std:: remove_cv_t < rng::range_value_t <T> >, std::byte> &&
106+ std::constructible_from<T, rng:: range_value_t <T> *, rng:: range_value_t <T> *> &&
87107 rng::contiguous_range<policy_string_t <Policy>>
88108constexpr nonstd::expected<T, conversion_errc> convert_from_bvalue_string_impl (
89109 customization_point_type<T>,
90- const basic_bvalue<Policy> & b,
110+ U& & b,
91111 priority_tag<0 >) noexcept
92112{
93113 if (!holds_string (b)) [[unlikely]]
94114 return nonstd::make_unexpected (conversion_errc::not_string_type);
95115
96- const auto & bstring = get_string (b);
97- try { return T (reinterpret_cast <const std::byte*>(rng::data (bstring)),
98- reinterpret_cast <const std::byte*>(rng::data (bstring)+rng::size (bstring))); }
116+ auto & bstring = get_string (b);
117+ try { return T (reinterpret_cast <std::byte*>(rng::data (bstring)),
118+ reinterpret_cast <std::byte*>(rng::data (bstring)+rng::size (bstring))); }
99119 catch (...) { return nonstd::make_unexpected (conversion_errc::construction_error); }
100120}
101121
@@ -167,7 +187,6 @@ constexpr nonstd::expected<T, conversion_errc> convert_from_bvalue_list_impl(
167187 std::apply (
168188 [&]<std::size_t ... IS>(std::index_sequence<IS...>&&) constexpr {
169189 using std::get;
170-
171190 ( (get<IS>(out) = get_as<std::tuple_element_t <IS, T>>(
172191 detail::forward_like<BV>(blist[IS]))) , ... );
173192 },
@@ -181,6 +200,27 @@ constexpr nonstd::expected<T, conversion_errc> convert_from_bvalue_list_impl(
181200 return out;
182201}
183202
203+ // conversion to std::span<const char> or std::span<const std::byte>
204+
205+ template <typename Tp, basic_bvalue_instantiation BV, typename U = std::remove_cvref_t <BV>>
206+ requires (std::same_as<Tp, const char > || std::same_as<Tp, const std::byte>)
207+ && std::same_as<typename detail::policy_string_t <BV>::value_type, char >
208+ constexpr nonstd::expected<std::span<const Tp>, conversion_errc> convert_from_bvalue_list_impl (
209+ customization_point_type<std::span<const Tp>>,
210+ BV&& b,
211+ priority_tag<0 >) noexcept
212+ {
213+ if (!holds_string (b)) [[unlikely]]
214+ return nonstd::make_unexpected (conversion_errc::not_list_type);
215+
216+ const auto & s = get_string (b);
217+ if constexpr (std::same_as<Tp, std::byte>) {
218+ return std::span (reinterpret_cast <const std::byte*>(s.data ()), s.size ());
219+ } else {
220+ return std::span (s.data (), s.size ());
221+ }
222+ }
223+
184224// Dict conversion
185225
186226template <typename T, basic_bvalue_instantiation BV, typename Policy = typename std::remove_cvref_t <BV>::policy_type>
0 commit comments