JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
adapter_for.hpp
Go to the documentation of this file.
1/// \file jsonv/serialization/adapter_for.hpp
2///
3/// Copyright (c) 2015-2026 by Travis Gockel. All rights reserved.
4///
5/// This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
6/// as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
7/// version.
8///
9/// \author Travis Gockel (travis@gockelhut.com)
10#pragma once
11
12#include <jsonv/config.hpp>
14#include <jsonv/value.hpp>
15
16#include <expected>
17#include <new>
18#include <utility>
19
20namespace jsonv
21{
22
23/// \addtogroup Serialization
24/// \{
25
26/// An adapter for the type \c T. This is a utility class which converts the `void*`s used in the \c extractor and
27/// \c serializer interfaces into the more-friendly \c T.
28///
29/// \see extractor_for
30/// \see serializer_for
31/// \see value_adapter_for
32template <typename T>
34 public adapter
35{
36public:
37 /// \see extractor::get_type
38 /// \see serializer::get_type
40 virtual const std::type_info& get_type() const noexcept override
41 {
42 return typeid(T);
43 }
44
45 /// \see extractor::extract
47 virtual std::expected<void, ast_node_type>
48 extract(extraction_context& context, reader& from, void* into) const override
49 {
50 if (auto created = create(context, from))
51 {
52 try
53 {
54 new(into) T(std::move(created).value());
55 }
56 catch (...)
57 {
58 // `create` succeeded, so the cursor is already one past the value this was built from. Moving it
59 // into place is the last thing which can fail, and `T` is the caller's type; a loop recovering from
60 // that failure must not step over the value a second time.
61 context.note_value_consumed(from);
62 throw;
63 }
64 return {};
65 }
66 else
67 {
68 return std::unexpected(created.error());
69 }
70 }
71
72 /// \see serializer::to_json
75 const void* from
76 ) const override
77 {
78 return to_json(context, *static_cast<const T*>(from));
79 }
80
81protected:
82 /// Create an instance of \c T by reading \a from.
83 ///
84 /// \param context Extra information to help you decode sub-objects, such as looking up other \c extractor
85 /// implementations via \c formats. Record any problem you encounter with
86 /// \c extraction_context::problem.
87 /// \param from The JSON \c reader to extract from. On a successful return it should sit one position past the
88 /// value which was read, as \c reader::next_value would have left it.
89 ///
90 /// \returns The created instance; otherwise a \c std::unexpected carrying the \c ast_node_type actually found
91 /// when the failure was a type mismatch, or \c ast_node_type::error otherwise.
93 virtual std::expected<T, ast_node_type> create(extraction_context& context, reader& from) const = 0;
94
96 virtual value to_json(const serialization_context& context, const T& from) const = 0;
97};
98
99/// A base for adapters written against the older \c value -based extraction interface.
100///
101/// The subtree under the reader is materialised with \c read_value and handed to the subclass, whose \c create runs
102/// unchanged. This costs the whole subtree in memory, which is exactly what extracting off a \c reader is meant to
103/// avoid -- so it is a stepping stone for ports, not a destination. New adapters should derive from \c adapter_for and
104/// walk the \c reader.
105template <typename T>
107 public adapter_for<T>
108{
109protected:
111 virtual std::expected<T, ast_node_type>
112 create(extraction_context& context, reader& from) const final override
113 {
114 // An extraction_error thrown by the subclass is deliberately left to propagate: extraction_context::extract
115 // folds its problem list onto the context, which is how the path and message an older adapter throws with
116 // survive into the pipeline's std::expected channel.
117 detail::borrowed_subtree subtree(context, from);
118 T out = create(context, subtree.get());
119
120 // Only once the older body is through: a throw out of it leaves the cursor on the value which failed, so the
121 // problem names that rather than whatever follows it.
122 subtree.commit();
123 return out;
124 }
125
126 /// Create an instance of \c T from the materialised \a from.
127 ///
128 /// \throws extraction_error if \a from cannot be converted to a \c T.
130 virtual T create(extraction_context& context, const value& from) const = 0;
131};
132
133/// \}
134
135}
Copyright (c) 2015-2020 by Travis Gockel.
An adapter for the type T.
virtual const std::type_info & get_type() const noexcept override
virtual value to_json(const serialization_context &context, const void *from) const override
virtual std::expected< T, ast_node_type > create(extraction_context &context, reader &from) const =0
Create an instance of T by reading from.
virtual std::expected< void, ast_node_type > extract(extraction_context &context, reader &from, void *into) const override
An adapter is both an extractor and a serializer.
Definition adapter.hpp:27
Provides extra information to routines used for extraction and serialization.
Definition context.hpp:26
Provides extra information to routines used for extraction, collects the problems they encounter,...
Definition extract.hpp:391
A reader instance reads from some form of JSON source (probably a string) and converts it into a JSON...
Definition reader.hpp:104
A base for adapters written against the older value -based extraction interface.
virtual std::expected< T, ast_node_type > create(extraction_context &context, reader &from) const final override
Create an instance of T by reading from.
virtual T create(extraction_context &context, const value &from) const =0
Create an instance of T from the materialised from.
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
Definition value.hpp:113
Copyright (c) 2014-2020 by Travis Gockel.
#define JSONV_NODISCARD
Warn if the caller discards the result of this function.
Definition config.hpp:132
Copyright (c) 2012-2020 by Travis Gockel.