Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:44:02

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_HTTP_FIELDS_HPP
0011 #define BOOST_BEAST_HTTP_FIELDS_HPP
0012 
0013 #include <boost/beast/http/fields_fwd.hpp>
0014 
0015 #include <boost/beast/core/detail/allocator.hpp>
0016 #include <boost/beast/core/detail/config.hpp>
0017 #include <boost/beast/core/error.hpp>
0018 #include <boost/beast/core/string.hpp>
0019 #include <boost/beast/http/field.hpp>
0020 #include <boost/asio/buffer.hpp>
0021 #include <boost/core/empty_value.hpp>
0022 #include <boost/intrusive/list.hpp>
0023 #include <boost/intrusive/set.hpp>
0024 #include <boost/optional.hpp>
0025 #include <cctype>
0026 #include <cstring>
0027 #include <memory>
0028 #include <type_traits>
0029 #include <utility>
0030 
0031 namespace boost {
0032 namespace beast {
0033 namespace http {
0034 
0035 /** A container for storing HTTP header fields.
0036 
0037     This container is designed to store the field value pairs that make
0038     up the fields and trailers in an HTTP message. Objects of this type
0039     are iterable, with each element holding the field name and field
0040     value.
0041 
0042     Field names are stored as-is, but comparisons are case-insensitive.
0043     The container behaves as a `std::multiset`; there will be a separate
0044     value for each occurrence of the same field name. When the container
0045     is iterated the fields are presented in the order of insertion, with
0046     fields having the same name following each other consecutively.
0047 
0048     Meets the requirements of <em>Fields</em>
0049 
0050     @tparam Allocator The allocator to use.
0051 */
0052 template<class Allocator>
0053 class basic_fields
0054 #if ! BOOST_BEAST_DOXYGEN
0055     : private boost::empty_value<Allocator>
0056 #endif
0057 {
0058     // Fancy pointers are not supported
0059     static_assert(std::is_pointer<typename
0060         std::allocator_traits<Allocator>::pointer>::value,
0061         "Allocator must use regular pointers");
0062 
0063 #ifndef BOOST_BEAST_DOXYGEN
0064     friend class fields_test; // for `header`
0065 #endif
0066 
0067     struct element;
0068 
0069     using off_t = std::uint16_t;
0070 
0071 public:
0072     /// The type of allocator used.
0073     using allocator_type = Allocator;
0074 
0075     /// The type of element used to represent a field
0076     class value_type
0077     {
0078 #ifndef BOOST_BEAST_DOXYGEN
0079         friend class basic_fields;
0080 #endif
0081 
0082         off_t off_;
0083         off_t len_;
0084         field f_;
0085 
0086         char*
0087         data() const;
0088 
0089         net::const_buffer
0090         buffer() const;
0091 
0092     protected:
0093         value_type(field name,
0094             string_view sname, string_view value);
0095 
0096     public:
0097         /// Constructor (deleted)
0098         value_type(value_type const&) = delete;
0099 
0100         /// Assignment (deleted)
0101         value_type& operator=(value_type const&) = delete;
0102 
0103         /// Returns the field enum, which can be @ref boost::beast::http::field::unknown
0104         field
0105         name() const;
0106 
0107         /// Returns the field name as a string
0108         string_view const
0109         name_string() const;
0110 
0111         /// Returns the value of the field
0112         string_view const
0113         value() const;
0114     };
0115 
0116     /** A strictly less predicate for comparing keys, using a case-insensitive comparison.
0117 
0118         The case-comparison operation is defined only for low-ASCII characters.
0119     */
0120 #if BOOST_BEAST_DOXYGEN
0121     using key_compare = __implementation_defined__;
0122 #else
0123     struct key_compare : beast::iless
0124 #endif
0125     {
0126         /// Returns `true` if lhs is less than rhs using a strict ordering
0127         bool
0128         operator()(
0129             string_view lhs,
0130             value_type const& rhs) const noexcept
0131         {
0132             if(lhs.size() < rhs.name_string().size())
0133                 return true;
0134             if(lhs.size() > rhs.name_string().size())
0135                 return false;
0136             return iless::operator()(lhs, rhs.name_string());
0137         }
0138 
0139         /// Returns `true` if lhs is less than rhs using a strict ordering
0140         bool
0141         operator()(
0142             value_type const& lhs,
0143             string_view rhs) const noexcept
0144         {
0145             if(lhs.name_string().size() < rhs.size())
0146                 return true;
0147             if(lhs.name_string().size() > rhs.size())
0148                 return false;
0149             return iless::operator()(lhs.name_string(), rhs);
0150         }
0151 
0152         /// Returns `true` if lhs is less than rhs using a strict ordering
0153         bool
0154         operator()(
0155             value_type const& lhs,
0156             value_type const& rhs) const noexcept
0157         {
0158             if(lhs.name_string().size() < rhs.name_string().size())
0159                 return true;
0160             if(lhs.name_string().size() > rhs.name_string().size())
0161                 return false;
0162             return iless::operator()(lhs.name_string(), rhs.name_string());
0163         }
0164     };
0165 
0166     /// The algorithm used to serialize the header
0167 #if BOOST_BEAST_DOXYGEN
0168     using writer = __implementation_defined__;
0169 #else
0170     class writer;
0171 #endif
0172 
0173 private:
0174     struct element
0175         : public boost::intrusive::list_base_hook<
0176             boost::intrusive::link_mode<
0177                 boost::intrusive::normal_link>>
0178         , public boost::intrusive::set_base_hook<
0179             boost::intrusive::link_mode<
0180                 boost::intrusive::normal_link>>
0181         , public value_type
0182     {
0183         element(field name,
0184             string_view sname, string_view value);
0185     };
0186 
0187     using list_t = typename boost::intrusive::make_list<
0188         element,
0189         boost::intrusive::constant_time_size<false>
0190             >::type;
0191 
0192     using set_t = typename boost::intrusive::make_multiset<
0193         element,
0194         boost::intrusive::constant_time_size<false>,
0195         boost::intrusive::compare<key_compare>
0196             >::type;
0197 
0198     using align_type = typename
0199         boost::type_with_alignment<alignof(element)>::type;
0200 
0201     using rebind_type = typename
0202         beast::detail::allocator_traits<Allocator>::
0203             template rebind_alloc<align_type>;
0204 
0205     using alloc_traits =
0206         beast::detail::allocator_traits<rebind_type>;
0207 
0208     using pocma = typename
0209         alloc_traits::propagate_on_container_move_assignment;
0210 
0211     using pocca = typename
0212         alloc_traits::propagate_on_container_copy_assignment;
0213 
0214     using pocs = typename
0215         alloc_traits::propagate_on_container_swap;
0216 
0217     using size_type = typename
0218         beast::detail::allocator_traits<Allocator>::size_type;
0219 
0220 
0221 public:
0222     /// Maximum field name size
0223     static std::size_t constexpr max_name_size =
0224         (std::numeric_limits<std::uint16_t>::max)() - 2;
0225 
0226     /// Maximum field value size
0227     static std::size_t constexpr max_value_size =
0228         (std::numeric_limits<std::uint16_t>::max)() - 2;
0229 
0230     /// Destructor
0231     ~basic_fields();
0232 
0233     /// Constructor.
0234     basic_fields() = default;
0235 
0236     /** Constructor.
0237 
0238         @param alloc The allocator to use.
0239     */
0240     explicit
0241     basic_fields(Allocator const& alloc) noexcept;
0242 
0243     /** Move constructor.
0244 
0245         The state of the moved-from object is
0246         as if constructed using the same allocator.
0247     */
0248     basic_fields(basic_fields&&) noexcept;
0249 
0250     /** Move constructor.
0251 
0252         The state of the moved-from object is
0253         as if constructed using the same allocator.
0254 
0255         @param alloc The allocator to use.
0256     */
0257     basic_fields(basic_fields&&, Allocator const& alloc);
0258 
0259     /// Copy constructor.
0260     basic_fields(basic_fields const&);
0261 
0262     /** Copy constructor.
0263 
0264         @param alloc The allocator to use.
0265     */
0266     basic_fields(basic_fields const&, Allocator const& alloc);
0267 
0268     /// Copy constructor.
0269     template<class OtherAlloc>
0270     basic_fields(basic_fields<OtherAlloc> const&);
0271 
0272     /** Copy constructor.
0273 
0274         @param alloc The allocator to use.
0275     */
0276     template<class OtherAlloc>
0277     basic_fields(basic_fields<OtherAlloc> const&,
0278         Allocator const& alloc);
0279 
0280     /** Move assignment.
0281 
0282         The state of the moved-from object is
0283         as if constructed using the same allocator.
0284     */
0285     basic_fields& operator=(basic_fields&&) noexcept(
0286         pocma::value && std::is_nothrow_move_assignable<Allocator>::value);
0287 
0288     /// Copy assignment.
0289     basic_fields& operator=(basic_fields const&);
0290 
0291     /// Copy assignment.
0292     template<class OtherAlloc>
0293     basic_fields& operator=(basic_fields<OtherAlloc> const&);
0294 
0295 public:
0296     /// A constant iterator to the field sequence.
0297 #if BOOST_BEAST_DOXYGEN
0298     using const_iterator = __implementation_defined__;
0299 #else
0300     using const_iterator = typename list_t::const_iterator;
0301 #endif
0302 
0303     /// A constant iterator to the field sequence.
0304     using iterator = const_iterator;
0305 
0306     /// Return a copy of the allocator associated with the container.
0307     allocator_type
0308     get_allocator() const
0309     {
0310         return this->get();
0311     }
0312 
0313     //--------------------------------------------------------------------------
0314     //
0315     // Element access
0316     //
0317     //--------------------------------------------------------------------------
0318 
0319     /** Returns the value for a field, or throws an exception.
0320 
0321         If more than one field with the specified name exists, the
0322         first field defined by insertion order is returned.
0323 
0324         @param name The name of the field.
0325 
0326         @return The field value.
0327 
0328         @throws std::out_of_range if the field is not found.
0329     */
0330     string_view const
0331     at(field name) const;
0332 
0333     /** Returns the value for a field, or throws an exception.
0334 
0335         If more than one field with the specified name exists, the
0336         first field defined by insertion order is returned.
0337 
0338         @param name The name of the field. It is interpreted as a case-insensitive string.
0339 
0340         @return The field value.
0341 
0342         @throws std::out_of_range if the field is not found.
0343     */
0344     string_view const
0345     at(string_view name) const;
0346 
0347     /** Returns the value for a field, or `""` if it does not exist.
0348 
0349         If more than one field with the specified name exists, the
0350         first field defined by insertion order is returned.
0351 
0352         @param name The name of the field.
0353     */
0354     string_view const
0355     operator[](field name) const;
0356 
0357     /** Returns the value for a case-insensitive matching header, or `""` if it does not exist.
0358 
0359         If more than one field with the specified name exists, the
0360         first field defined by insertion order is returned.
0361 
0362         @param name The name of the field. It is interpreted as a case-insensitive string.
0363     */
0364     string_view const
0365     operator[](string_view name) const;
0366 
0367     //--------------------------------------------------------------------------
0368     //
0369     // Iterators
0370     //
0371     //--------------------------------------------------------------------------
0372 
0373     /// Return a const iterator to the beginning of the field sequence.
0374     const_iterator
0375     begin() const
0376     {
0377         return list_.cbegin();
0378     }
0379 
0380     /// Return a const iterator to the end of the field sequence.
0381     const_iterator
0382     end() const
0383     {
0384         return list_.cend();
0385     }
0386 
0387     /// Return a const iterator to the beginning of the field sequence.
0388     const_iterator
0389     cbegin() const
0390     {
0391         return list_.cbegin();
0392     }
0393 
0394     /// Return a const iterator to the end of the field sequence.
0395     const_iterator
0396     cend() const
0397     {
0398         return list_.cend();
0399     }
0400 
0401     //--------------------------------------------------------------------------
0402     //
0403     // Capacity
0404     //
0405     //--------------------------------------------------------------------------
0406 
0407 private:
0408     // VFALCO Since the header and message derive from Fields,
0409     //        what does the expression m.empty() mean? Its confusing.
0410     bool
0411     empty() const
0412     {
0413         return list_.empty();
0414     }
0415 public:
0416 
0417     //--------------------------------------------------------------------------
0418     //
0419     // Modifiers
0420     //
0421     //--------------------------------------------------------------------------
0422 
0423     /** Remove all fields from the container
0424 
0425         All references, pointers, or iterators referring to contained
0426         elements are invalidated. All past-the-end iterators are also
0427         invalidated.
0428 
0429         @par Postconditions:
0430         @code
0431             std::distance(this->begin(), this->end()) == 0
0432         @endcode
0433     */
0434     void
0435     clear();
0436 
0437     /** Insert a field.
0438 
0439         If one or more fields with the same name already exist,
0440         the new field will be inserted after the last field with
0441         the matching name, in serialization order.
0442         The value can be an empty string.
0443 
0444         @param name The field name.
0445 
0446         @param value The field value.
0447 
0448         @throws boost::system::system_error Thrown if an error occurs:
0449             @li If the size of @c value exceeds @ref max_value_size, the
0450             error code will be @ref error::header_field_value_too_large.
0451     */
0452     void
0453     insert(field name, string_view value);
0454 
0455     void
0456     insert(field, std::nullptr_t) = delete;
0457 
0458     /** Insert a field.
0459 
0460         If one or more fields with the same name already exist,
0461         the new field will be inserted after the last field with
0462         the matching name, in serialization order.
0463         The value can be an empty string.
0464 
0465         @param name The field name. It is interpreted as a case-insensitive string.
0466 
0467         @param value The field value.
0468 
0469         @throws boost::system::system_error Thrown if an error occurs:
0470             @li If the size of @c name exceeds @ref max_name_size, the
0471             error code will be @ref error::header_field_name_too_large.
0472             @li If the size of @c value exceeds @ref max_value_size, the
0473             error code will be @ref error::header_field_value_too_large.
0474     */
0475     void
0476     insert(string_view name, string_view value);
0477 
0478     void
0479     insert(string_view, std::nullptr_t) = delete;
0480 
0481     /** Insert a field.
0482 
0483         If one or more fields with the same name already exist,
0484         the new field will be inserted after the last field with
0485         the matching name, in serialization order.
0486         The value can be an empty string.
0487 
0488         @param name The field name.
0489 
0490         @param name_string The literal text corresponding to the
0491         field name. If `name != field::unknown`, then this value
0492         must be equal to `to_string(name)` using a case-insensitive
0493         comparison, otherwise the behavior is undefined.
0494 
0495         @param value The field value.
0496 
0497         @throws boost::system::system_error Thrown if an error occurs:
0498             @li If the size of @c name_string exceeds @ref max_name_size,
0499             the error code will be @ref error::header_field_name_too_large.
0500             @li If the size of @c value exceeds @ref max_value_size, the
0501             error code will be @ref error::header_field_value_too_large.
0502     */
0503     void
0504     insert(field name, string_view name_string,
0505         string_view value);
0506 
0507     void
0508     insert(field, string_view, std::nullptr_t) = delete;
0509 
0510     /** Insert a field.
0511 
0512         If one or more fields with the same name already exist,
0513         the new field will be inserted after the last field with
0514         the matching name, in serialization order.
0515         The value can be an empty string.
0516 
0517         @param name The field name.
0518 
0519         @param name_string The literal text corresponding to the
0520         field name. If `name != field::unknown`, then this value
0521         must be equal to `to_string(name)` using a case-insensitive
0522         comparison, otherwise the behavior is undefined.
0523 
0524         @param value The field value.
0525 
0526         @param ec Set to indicate what error occurred:
0527             @li If the size of @c name_string exceeds @ref max_name_size,
0528             the error code will be @ref error::header_field_name_too_large.
0529             @li If the size of @c value exceeds @ref max_value_size, the
0530             error code will be @ref error::header_field_value_too_large.
0531     */
0532     void
0533     insert(field name, string_view name_string,
0534         string_view value, error_code& ec);
0535 
0536     void
0537     insert(field, string_view, std::nullptr_t, error_code& ec) = delete;
0538 
0539     /** Set a field value, removing any other instances of that field.
0540 
0541         First removes any values with matching field names, then
0542         inserts the new field value. The value may be an empty string.
0543 
0544         @param name The field name.
0545 
0546         @param value The field value.
0547 
0548         @throws boost::system::system_error Thrown if an error occurs:
0549             @li If the size of @c value exceeds @ref max_value_size, the
0550             error code will be @ref error::header_field_value_too_large.
0551     */
0552     void
0553     set(field name, string_view value);
0554 
0555     void
0556     set(field, std::nullptr_t) = delete;
0557 
0558     /** Set a field value, removing any other instances of that field.
0559 
0560         First removes any values with matching field names, then
0561         inserts the new field value. The value can be an empty string.
0562 
0563         @param name The field name. It is interpreted as a case-insensitive string.
0564 
0565         @param value The field value.
0566 
0567         @throws boost::system::system_error Thrown if an error occurs:
0568             @li If the size of @c name exceeds @ref max_name_size, the
0569             error code will be @ref error::header_field_name_too_large.
0570             @li If the size of @c value exceeds @ref max_value_size, the
0571             error code will be @ref error::header_field_value_too_large.
0572     */
0573     void
0574     set(string_view name, string_view value);
0575 
0576     void
0577     set(string_view, std::nullptr_t) = delete;
0578 
0579     /** Remove a field.
0580 
0581         References and iterators to the erased elements are
0582         invalidated. Other references and iterators are not
0583         affected.
0584 
0585         @param pos An iterator to the element to remove.
0586 
0587         @return An iterator following the last removed element.
0588         If the iterator refers to the last element, the end()
0589         iterator is returned.
0590     */
0591     const_iterator
0592     erase(const_iterator pos);
0593 
0594     /** Remove all fields with the specified name.
0595 
0596         All fields with the same field name are erased from the
0597         container.
0598         References and iterators to the erased elements are
0599         invalidated. Other references and iterators are not
0600         affected.
0601 
0602         @param name The field name.
0603 
0604         @return The number of fields removed.
0605     */
0606     std::size_t
0607     erase(field name);
0608 
0609     /** Remove all fields with the specified name.
0610 
0611         All fields with the same field name are erased from the
0612         container.
0613         References and iterators to the erased elements are
0614         invalidated. Other references and iterators are not
0615         affected.
0616 
0617         @param name The field name. It is interpreted as a case-insensitive string.
0618 
0619         @return The number of fields removed.
0620     */
0621     std::size_t
0622     erase(string_view name);
0623 
0624     /** Return a buffer sequence representing the trailers.
0625 
0626         This function returns a buffer sequence holding the
0627         serialized representation of the trailer fields promised
0628         in the Accept field. Before calling this function the
0629         Accept field must contain the exact trailer fields
0630         desired. Each field must also exist.
0631     */
0632 
0633 
0634     /// Swap this container with another
0635     void
0636     swap(basic_fields& other);
0637 
0638     /// Swap two field containers
0639     template<class Alloc>
0640     friend
0641     void
0642     swap(basic_fields<Alloc>& lhs, basic_fields<Alloc>& rhs);
0643 
0644     //--------------------------------------------------------------------------
0645     //
0646     // Lookup
0647     //
0648     //--------------------------------------------------------------------------
0649 
0650     /** Return the number of fields with the specified name.
0651 
0652         @param name The field name.
0653     */
0654     std::size_t
0655     count(field name) const;
0656 
0657     /** Return the number of fields with the specified name.
0658 
0659         @param name The field name. It is interpreted as a case-insensitive string.
0660     */
0661     std::size_t
0662     count(string_view name) const;
0663 
0664     /** Returns an iterator to the case-insensitive matching field.
0665 
0666         If more than one field with the specified name exists, the
0667         first field defined by insertion order is returned.
0668 
0669         @param name The field name.
0670 
0671         @return An iterator to the matching field, or `end()` if
0672         no match was found.
0673     */
0674     const_iterator
0675     find(field name) const;
0676 
0677     /** Returns an iterator to the case-insensitive matching field name.
0678 
0679         If more than one field with the specified name exists, the
0680         first field defined by insertion order is returned.
0681 
0682         @param name The field name. It is interpreted as a case-insensitive string.
0683 
0684         @return An iterator to the matching field, or `end()` if
0685         no match was found.
0686     */
0687     const_iterator
0688     find(string_view name) const;
0689 
0690     /** Returns a range of iterators to the fields with the specified name.
0691 
0692         This function returns the first and last iterators to the ordered
0693         fields with the specified name.
0694 
0695         @note The fields represented by the range are ordered. Its elements
0696         are guaranteed to match the field ordering of the message. This
0697         means users do not need to sort this range when comparing fields
0698         of the same name in different messages.
0699 
0700         @param name The field name.
0701 
0702         @return A range of iterators to fields with the same name,
0703         otherwise an empty range.
0704     */
0705     std::pair<const_iterator, const_iterator>
0706     equal_range(field name) const;
0707 
0708     /// @copydoc boost::beast::http::basic_fields::equal_range(boost::beast::http::field) const
0709     std::pair<const_iterator, const_iterator>
0710     equal_range(string_view name) const;
0711 
0712     //--------------------------------------------------------------------------
0713     //
0714     // Observers
0715     //
0716     //--------------------------------------------------------------------------
0717 
0718     /// Returns a copy of the key comparison function
0719     key_compare
0720     key_comp() const
0721     {
0722         return key_compare{};
0723     }
0724 
0725 protected:
0726     /** Returns the request-method string.
0727 
0728         @note Only called for requests.
0729     */
0730     string_view
0731     get_method_impl() const;
0732 
0733     /** Returns the request-target string.
0734 
0735         @note Only called for requests.
0736     */
0737     string_view
0738     get_target_impl() const;
0739 
0740     /** Returns the response reason-phrase string.
0741 
0742         @note Only called for responses.
0743     */
0744     string_view
0745     get_reason_impl() const;
0746 
0747     /** Returns the chunked Transfer-Encoding setting
0748     */
0749     bool
0750     get_chunked_impl() const;
0751 
0752     /** Returns the keep-alive setting
0753     */
0754     bool
0755     get_keep_alive_impl(unsigned version) const;
0756 
0757     /** Returns `true` if the Content-Length field is present.
0758     */
0759     bool
0760     has_content_length_impl() const;
0761 
0762     /** Set or clear the method string.
0763 
0764         @note Only called for requests.
0765     */
0766     void
0767     set_method_impl(string_view s);
0768 
0769     /** Set or clear the target string.
0770 
0771         @note Only called for requests.
0772     */
0773     void
0774     set_target_impl(string_view s);
0775 
0776     /** Set or clear the reason string.
0777 
0778         @note Only called for responses.
0779     */
0780     void
0781     set_reason_impl(string_view s);
0782 
0783     /** Adjusts the chunked Transfer-Encoding value
0784     */
0785     void
0786     set_chunked_impl(bool value);
0787 
0788     /** Sets or clears the Content-Length field
0789     */
0790     void
0791     set_content_length_impl(
0792         boost::optional<std::uint64_t> const& value);
0793 
0794     /** Adjusts the Connection field
0795     */
0796     void
0797     set_keep_alive_impl(
0798         unsigned version, bool keep_alive);
0799 
0800 private:
0801     template<class OtherAlloc>
0802     friend class basic_fields;
0803 
0804     element*
0805     try_create_new_element(
0806         field name,
0807         string_view sname,
0808         string_view value,
0809         error_code& ec);
0810 
0811     element&
0812     new_element(
0813         field name,
0814         string_view sname,
0815         string_view value);
0816 
0817     void
0818     insert_element(element& e);
0819 
0820     void
0821     delete_element(element& e);
0822 
0823     void
0824     set_element(element& e);
0825 
0826     void
0827     realloc_string(string_view& dest, string_view s);
0828 
0829     void
0830     realloc_target(
0831         string_view& dest, string_view s);
0832 
0833     template<class OtherAlloc>
0834     void
0835     copy_all(basic_fields<OtherAlloc> const&);
0836 
0837     void
0838     clear_all();
0839 
0840     void
0841     delete_list();
0842 
0843     void
0844     move_assign(basic_fields&, std::true_type);
0845 
0846     void
0847     move_assign(basic_fields&, std::false_type);
0848 
0849     void
0850     copy_assign(basic_fields const&, std::true_type);
0851 
0852     void
0853     copy_assign(basic_fields const&, std::false_type);
0854 
0855     void
0856     swap(basic_fields& other, std::true_type);
0857 
0858     void
0859     swap(basic_fields& other, std::false_type);
0860 
0861     set_t set_;
0862     list_t list_;
0863     string_view method_;
0864     string_view target_or_reason_;
0865 };
0866 
0867 #if BOOST_BEAST_DOXYGEN
0868 /// A typical HTTP header fields container
0869 using fields = basic_fields<std::allocator<char>>;
0870 #endif
0871 
0872 } // http
0873 } // beast
0874 } // boost
0875 
0876 #include <boost/beast/http/impl/fields.hpp>
0877 
0878 #endif