Boost logo

Boost :

From: Alan de Freitas (alandefreitas_at_[hidden])
Date: 2022-08-23 17:07:26


>
> Ok, I'm convinced. I am still not convinced that the containers that
> maintain these invariants should be lazy. That still seems weird to

me. If they own the data, and are regular types, they should probably
> be eager. The larger issue to me is that they have a subset of the
> expected STL API.

Yes. If I understand the discussion correctly, the container that maintains
the invariant is not lazy but the documentation could probably be better at
explaining some other things.
It's the urls::url that maintains the invariants and owns the data in

url u( "ldap:local:userdb/8675309" );
u.remove_scheme();
(u == "local%3a/8675309");

The urls::segment and urls::params views are just references to part of
this urls::url. The invariants belong to the url.
They are helpers to operate on the urls::url segments and parameters at an
individual level, while the underlying urls::url adjusts itself to keep the
invariants:

url u( "" );
u.set_path("//index.htm");
(u == "/.//index.htm");

url u( "" );
u.is_absolute(true);
u.segments().append({"", "index.htm"});
(u == "/.//index.htm");

So the eager urls::url is the one maintaining the invariants, but the
segment or parameter views are a better way to operate on the URL when
dealing with individual subcomponents.
Thus, the functions are not exactly a subset of the STL because the
operations are ensuring the invariants of the underlying url remain valid.
(The names "segments" and "params" might be a little confusing because it
sounds like it owns the data. Some other review has recommended
mutable_segments_view/mutable_params_view.)

The views are useful because it gives us a single contiguous string with
the complete URL at the end.
This buffer is always ready to be used by another application. All
consecutive URL components are also always immediately available as a
contiguous buffer.

boost::asio::connect(sock, r.resolve(u.encoded_host));

or

boost::beast::http::request<http::string_body> req{http::verb::get, target,
version};
req.set(http::field::host, u.encoded_host());

Besides performance reasons, this contiguous representation is quite useful
because we don't have to reassemble the URLs or combinations of components
in another string to be able to use it.
They can go straight in a buffer sequence. The documentation should
probably highlight that design a little more: the idea that we try to keep
things in a single contiguous buffer and why.

An isolated container owning only the segments or parameters wouldn't be
very useful because it wouldn't do much more than a std::vector or a
std::map would.
These containers would maintain all the invariants we need in decoded
segments and params and some other function could then percent-encode the
data in these containers to paste that into a url.
But what the library is attempting to achieve is avoiding this process.

-- 
Alan Freitas
https://github.com/alandefreitas

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk