1 /*
2  * RESTinio
3  */
4 
5 /*!
6  * @file
7  * @brief Stuff related to value of Accept HTTP-field.
8  *
9  * @since v.0.6.1
10  */
11 
12 #pragma once
13 
14 #include <restinio/helpers/http_field_parsers/media-type.hpp>
15 
16 namespace restinio
17 {
18 
19 namespace http_field_parsers
20 {
21 
22 //
23 // accept_value_t
24 //
25 /*!
26  * @brief Tools for working with the value of Accept HTTP-field.
27  *
28  * This struct represents parsed value of HTTP-field Accept
29  * (see https://tools.ietf.org/html/rfc7231#section-5.3.2):
30 @verbatim
31      Accept = #( media-range [ accept-params ] )
32 
33      media-range    = ( "*" "/" "*"
34                       / ( type "/" "*" )
35                       / ( type "/" subtype )
36                       ) *( OWS ";" OWS parameter )
37      accept-params  = weight *( accept-ext )
38      accept-ext = OWS ";" OWS token [ "=" ( token / quoted-string ) ]
39 
40      weight = OWS ";" OWS "q=" qvalue
41      qvalue = ( "0" [ "." 0*3DIGIT ] )
42             / ( "1" [ "." 0*3("0") ] )
43 @endverbatim
44  *
45  * @note
46  * Parameter names are converted to lower case during the parsing.
47  * Parameter values are left as they are.
48  *
49  * @since v.0.6.1
50  */
51 struct accept_value_t
52 {
53 	struct item_t
54 	{
55 		using accept_ext_t = parameter_with_optional_value_t;
56 
57 		using accept_ext_container_t = parameter_with_optional_value_container_t;
58 
59 		media_type_value_t media_type;
60 		restinio::optional_t< qvalue_t > weight;
61 		accept_ext_container_t accept_params;
62 	};
63 
64 	using item_container_t = std::vector< item_t >;
65 
66 	item_container_t items;
67 
68 	/*!
69 	 * @brief A factory function for a parser of Accept value.
70 	 *
71 	 * @since v.0.6.1
72 	 */
73 	RESTINIO_NODISCARD
74 	static auto
make_parserrestinio::http_field_parsers::accept_value_t75 	make_parser()
76 	{
77 		const auto media_type = media_type_value_t::make_weight_aware_parser();
78 
79 		return produce< accept_value_t >(
80 			maybe_empty_comma_separated_list_p< item_container_t >(
81 				produce< item_t >(
82 					media_type >> &item_t::media_type,
83 					maybe(
84 						weight_p() >> &item_t::weight,
85 						params_with_opt_value_p() >> &item_t::accept_params
86 					)
87 				)
88 			) >> &accept_value_t::items
89 		);
90 	}
91 
92 	/*!
93 	 * @brief An attempt to parse Accept HTTP-field.
94 	 *
95 	 * @since v.0.6.1
96 	 */
97 	RESTINIO_NODISCARD
98 	static expected_t< accept_value_t, restinio::easy_parser::parse_error_t >
try_parserestinio::http_field_parsers::accept_value_t99 	try_parse( string_view_t what )
100 	{
101 		return restinio::easy_parser::try_parse( what, make_parser() );
102 	}
103 };
104 
105 } /* namespace http_field_parsers */
106 
107 } /* namespace restinio */
108 
109