diff --git a/include/boost/json/detail/value_to.hpp b/include/boost/json/detail/value_to.hpp index 66c3858c7..b0e0f3794 100644 --- a/include/boost/json/detail/value_to.hpp +++ b/include/boost/json/detail/value_to.hpp @@ -38,37 +38,34 @@ using reserve_implementation = mp11::mp_cond< mp11::mp_true, mp11::mp_int<0>>; template -error -try_reserve( - T&, - std::size_t size, - mp11::mp_int<2>) +system::result +try_reserve(T& cnt, std::size_t size, mp11::mp_int<2>) + noexcept { constexpr std::size_t N = std::tuple_size>::value; if ( N != size ) - return error::size_mismatch; - return error(); + { + system::error_code ec; + BOOST_JSON_FAIL(ec, error::size_mismatch); + return {boost::system::in_place_error, ec}; + } + return cnt; } template -error -try_reserve( - T& cont, - std::size_t size, - mp11::mp_int<1>) +system::result +try_reserve(T& cnt, std::size_t size, mp11::mp_int<1>) { - cont.reserve(size); - return error(); + cnt.reserve(size); + return cnt; } template -error -try_reserve( - T&, - std::size_t, - mp11::mp_int<0>) +system::result +try_reserve(T& cnt, std::size_t, mp11::mp_int<0>) + noexcept { - return error(); + return cnt; } @@ -212,35 +209,28 @@ value_to_impl( value const& jv, Ctx const& ctx ) { - object const* obj = jv.if_object(); - if( !obj ) - { - system::error_code ec; - BOOST_JSON_FAIL(ec, error::not_object); - return {boost::system::in_place_error, ec}; - } - T res; - error const e = detail::try_reserve( - res, obj->size(), reserve_implementation()); - if( e != error() ) - { - system::error_code ec; - BOOST_JSON_FAIL( ec, e ); - return {boost::system::in_place_error, ec}; - } - - auto ins = detail::inserter(res, inserter_implementation()); - for( key_value_pair const& kv: *obj ) + return jv.try_as_object() & [&](object const& jo) { - auto elem_res = try_value_to>( kv.value(), ctx ); - if( elem_res.has_error() ) - return {boost::system::in_place_error, elem_res.error()}; - *ins++ = value_type{ - key_type(kv.key()), - std::move(elem_res.unsafe_value())}; - } - return res; + return detail::try_reserve( + res, jo.size(), reserve_implementation()) + & [&](T& res) -> system::result + { + auto ins = detail::inserter(res, inserter_implementation()); + for(key_value_pair const& kv: jo) + { + auto elem_res = try_value_to>( + kv.value(), ctx); + if( elem_res.has_error() ) + return { + boost::system::in_place_error, elem_res.error()}; + *ins++ = value_type{ + key_type(kv.key()), + std::move( elem_res.unsafe_value() )}; + } + return std::move(res); + }; + }; } // all other containers @@ -252,33 +242,25 @@ value_to_impl( value const& jv, Ctx const& ctx ) { - array const* arr = jv.if_array(); - if( !arr ) - { - system::error_code ec; - BOOST_JSON_FAIL(ec, error::not_array); - return {boost::system::in_place_error, ec}; - } - - T result; - error const e = detail::try_reserve( - result, arr->size(), reserve_implementation()); - if( e != error() ) - { - system::error_code ec; - BOOST_JSON_FAIL( ec, e ); - return {boost::system::in_place_error, ec}; - } - - auto ins = detail::inserter(result, inserter_implementation()); - for( value const& val: *arr ) + T res; + return jv.try_as_array() & [&](array const& ja) { - auto elem_res = try_value_to>( val, ctx ); - if( elem_res.has_error() ) - return {boost::system::in_place_error, elem_res.error()}; - *ins++ = std::move(elem_res.unsafe_value()); - } - return result; + return detail::try_reserve( + res, ja.size(), reserve_implementation()) + & [&](T& res) -> system::result + { + auto ins = detail::inserter(res, inserter_implementation()); + for(value const& val: ja) + { + auto elem_res = try_value_to>(val, ctx); + if( elem_res.has_error() ) + return { + boost::system::in_place_error, elem_res.error()}; + *ins++ = std::move( elem_res.unsafe_value() ); + } + return std::move(res); + }; + }; } // tuple-like types diff --git a/include/boost/json/impl/value.ipp b/include/boost/json/impl/value.ipp index 5d136dbe5..65fdbfb8b 100644 --- a/include/boost/json/impl/value.ipp +++ b/include/boost/json/impl/value.ipp @@ -528,37 +528,26 @@ value::try_as_null() const noexcept boost::system::result value::try_at(string_view key) noexcept { - auto r = try_as_object(); - if( !r ) - return r.error(); - return r.unsafe_value().try_at(key); + return try_as_object() & [key](object& jo) { return jo.try_at(key); }; } boost::system::result value::try_at(string_view key) const noexcept { - auto r = try_as_object(); - if( !r ) - return r.error(); - return r.unsafe_value().try_at(key); + return try_as_object() + & [key](object const& jo) { return jo.try_at(key); }; } boost::system::result value::try_at(std::size_t pos) noexcept { - auto r = try_as_array(); - if( !r ) - return r.error(); - return r.unsafe_value().try_at(pos); + return try_as_array() & [pos](array& ja) { return ja.try_at(pos); }; } boost::system::result value::try_at(std::size_t pos) const noexcept { - auto r = try_as_array(); - if( !r ) - return r.error(); - return r.unsafe_value().try_at(pos); + return try_as_array() & [pos](array const& ja) { return ja.try_at(pos); }; } object const&