di 0.1.0
Loading...
Searching...
No Matches
percent_encoded.h
Go to the documentation of this file.
1#pragma once
2
4#include "di/format/prelude.h"
6#include "di/parser/prelude.h"
8
9namespace di::serialization {
15template<typename String = di::TransparentString>
16requires(concepts::SameAs<meta::Encoding<String>, container::string::TransparentEncoding>)
18public:
19 using IsAtom = void;
20
21 PercentEncoded() = default;
22
23 constexpr static auto from_raw_data(String string) -> PercentEncoded { return PercentEncoded(di::move(string)); }
24
25 constexpr auto underlying_string() const& -> String const& { return m_string; }
26 constexpr auto underlying_string() && -> String&& { return di::move(m_string); }
27
28 auto operator==(PercentEncoded const& other) const -> bool = default;
29
30private:
31 constexpr explicit PercentEncoded(String string) : m_string(di::move(string)) {}
32
33 constexpr static auto hex_digit(u8 value) -> c32 {
34 if (value >= 10) {
35 return c32('A' + (value - 10));
36 }
37 return c32('0' + value);
38 }
39
40 constexpr static auto hex_value(char value) -> di::Optional<u8> {
41 if (('0'_mc - '9'_mc)(value)) {
42 return value - '0';
43 }
44 if (('A'_mc - 'F'_mc)(value)) {
45 return u8(10u + (value - 'A'));
46 }
47 if (('a'_mc - 'f'_mc)(value)) {
48 return u8(10u + (value - 'a'));
49 }
50 return {};
51 }
52
53 template<concepts::Encoding Enc>
56 auto do_output = [](concepts::FormatContext auto& context,
57 concepts::DecaySameAs<PercentEncoded> auto&& percent_encoded) -> Result<> {
58 constexpr auto allowed =
59 ('0'_mc - '9'_mc || 'a'_mc - 'z'_mc || 'A'_mc - 'Z'_mc || '-'_mc || '.'_mc || '_'_mc || '~'_mc);
60
61 for (auto ch : percent_encoded.m_string) {
62 if (allowed(ch)) {
63 (void) context.output(ch);
64 } else {
65 (void) context.output(U'%');
66 (void) context.output(hex_digit(u8(ch) >> 4));
67 (void) context.output(hex_digit(u8(ch) & 0xFu));
68 }
69 }
70 return {};
71 };
72 return Result<decltype(do_output)>(di::move(do_output));
73 }
74
76 // Only accept characters which are valid ASCII.
77 constexpr auto valid_base64 = ('\0'_m - '\x7f'_m);
78
79 return (parser::match_zero_or_more(valid_base64)) <<
80 []<typename Context>(
81 Context& context,
83 auto result = PercentEncoded {};
84 auto expected_chars = 0;
85 auto accumulator = u8(0);
86 for (auto ch : results) {
87 if (expected_chars > 0) {
88 accumulator <<= 4;
89 auto value = hex_value(ch);
90 if (!value) {
91 return Unexpected(context.make_error());
92 }
93 accumulator |= value.value();
94
95 if (--expected_chars == 0) {
96 result.m_string.push_back(char(accumulator));
97 }
98 continue;
99 }
100 if (ch == '%') {
101 expected_chars = 2;
102 accumulator = 0;
103 continue;
104 }
105 result.m_string.push_back(ch);
106 }
107 if (expected_chars > 0) {
108 return Unexpected(context.make_error());
109 }
110 return result;
111 };
112 }
113
114 String m_string;
115};
116}
117
118namespace di {
119inline namespace literals {
120 inline namespace percent_encoded_literals {
121 constexpr auto operator""_percent_encoded(char const* data, usize size) -> serialization::PercentEncoded<> {
122 auto view = di::TransparentStringView { data, size };
124 }
125 }
126}
127}
128
129namespace di {
131
133}
134
135#if !defined(DI_NO_GLOBALS) && !defined(DI_NO_GLOBAL_PERCENT_ENCODED_LITERALS)
137#endif
PercentEncoded()=default
Definition format_parse_context.h:14
Helper class for performing percent encoding.
Definition percent_encoded.h:17
static constexpr auto from_raw_data(String string) -> PercentEncoded
Definition percent_encoded.h:23
constexpr friend auto tag_invoke(types::Tag< parser::create_parser_in_place >, InPlaceType< PercentEncoded >)
Definition percent_encoded.h:75
constexpr friend auto tag_invoke(types::Tag< format::formatter_in_place >, InPlaceType< PercentEncoded >, FormatParseContext< Enc > &)
Definition percent_encoded.h:54
constexpr auto underlying_string() const &-> String const &
Definition percent_encoded.h:25
auto operator==(PercentEncoded const &other) const -> bool=default
constexpr auto underlying_string() &&-> String &&
Definition percent_encoded.h:26
void IsAtom
Definition percent_encoded.h:19
Definition optional_forward_declaration.h:5
Definition unexpected.h:14
Definition operations.h:34
Definition util.h:59
Definition format_context.h:9
string::StringImpl< string::Utf8Encoding > String
Definition string.h:11
string::StringViewImpl< string::TransparentEncoding > TransparentStringView
Definition string_view.h:13
Definition percent_encoded.h:120
vocab::Expected< T, meta::ParserContextError< Context > > ParserContextResult
Definition parser_context_result.h:8
constexpr auto match_zero_or_more
Definition match_zero_or_more.h:48
constexpr auto parse_unchecked
Definition parse_unchecked.h:25
Definition base64.h:16
size_t usize
Definition integers.h:33
__UINT8_TYPE__ u8
Definition integers.h:9
char32_t c32
Definition char.h:6
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
Expected< T, Error > Result
Definition result.h:8
Definition any_storable.h:9
constexpr auto size
Definition size.h:62
constexpr auto data
Definition data.h:51
PercentEncoded< di::TransparentStringView > PercentEncodedView
Definition percent_encoded.h:132
Definition in_place_type.h:5