1// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2// Licensed under the MIT License:
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21
22#pragma once
23
24#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
25#pragma GCC system_header
26#endif
27
28#include "layout.h"
29#include "list.h"
30
31namespace capnp {
32namespace _ { // private
33
34// PointerHelpers is a template class that assists in wrapping/unwrapping the low-level types in
35// layout.h with the high-level public API and generated types. This way, the code generator
36// and other templates do not have to specialize on each kind of pointer.
37
38template <typename T>
39struct PointerHelpers<T, Kind::STRUCT> {
40 static inline typename T::Reader get(PointerReader reader, const word* defaultValue = nullptr) {
41 return typename T::Reader(reader.getStruct(defaultValue));
42 }
43 static inline typename T::Builder get(PointerBuilder builder,
44 const word* defaultValue = nullptr) {
45 return typename T::Builder(builder.getStruct(structSize<T>(), defaultValue));
46 }
47 static inline void set(PointerBuilder builder, typename T::Reader value) {
48 builder.setStruct(value._reader);
49 }
50 static inline void setCanonical(PointerBuilder builder, typename T::Reader value) {
51 builder.setStruct(value._reader, true);
52 }
53 static inline typename T::Builder init(PointerBuilder builder) {
54 return typename T::Builder(builder.initStruct(structSize<T>()));
55 }
56 static inline void adopt(PointerBuilder builder, Orphan<T>&& value) {
57 builder.adopt(kj::mv(value.builder));
58 }
59 static inline Orphan<T> disown(PointerBuilder builder) {
60 return Orphan<T>(builder.disown());
61 }
62 static inline _::StructReader getInternalReader(const typename T::Reader& reader) {
63 return reader._reader;
64 }
65 static inline _::StructBuilder getInternalBuilder(typename T::Builder&& builder) {
66 return builder._builder;
67 }
68};
69
70template <typename T>
71struct PointerHelpers<List<T>, Kind::LIST> {
72 static inline typename List<T>::Reader get(PointerReader reader,
73 const word* defaultValue = nullptr) {
74 return typename List<T>::Reader(List<T>::getFromPointer(reader, defaultValue));
75 }
76 static inline typename List<T>::Builder get(PointerBuilder builder,
77 const word* defaultValue = nullptr) {
78 return typename List<T>::Builder(List<T>::getFromPointer(builder, defaultValue));
79 }
80 static inline void set(PointerBuilder builder, typename List<T>::Reader value) {
81 builder.setList(value.reader);
82 }
83 static inline void setCanonical(PointerBuilder builder, typename List<T>::Reader value) {
84 builder.setList(value.reader, true);
85 }
86 static void set(PointerBuilder builder, kj::ArrayPtr<const ReaderFor<T>> value) {
87 auto l = init(builder, value.size());
88 uint i = 0;
89 for (auto& element: value) {
90 l.set(i++, element);
91 }
92 }
93 static inline typename List<T>::Builder init(PointerBuilder builder, uint size) {
94 return typename List<T>::Builder(List<T>::initPointer(builder, size));
95 }
96 static inline void adopt(PointerBuilder builder, Orphan<List<T>>&& value) {
97 builder.adopt(kj::mv(value.builder));
98 }
99 static inline Orphan<List<T>> disown(PointerBuilder builder) {
100 return Orphan<List<T>>(builder.disown());
101 }
102 static inline _::ListReader getInternalReader(const typename List<T>::Reader& reader) {
103 return reader.reader;
104 }
105 static inline _::ListBuilder getInternalBuilder(typename List<T>::Builder&& builder) {
106 return builder.builder;
107 }
108};
109
110template <typename T>
111struct PointerHelpers<T, Kind::BLOB> {
112 static inline typename T::Reader get(PointerReader reader,
113 const void* defaultValue = nullptr,
114 uint defaultBytes = 0) {
115 return reader.getBlob<T>(defaultValue, bounded(defaultBytes) * BYTES);
116 }
117 static inline typename T::Builder get(PointerBuilder builder,
118 const void* defaultValue = nullptr,
119 uint defaultBytes = 0) {
120 return builder.getBlob<T>(defaultValue, bounded(defaultBytes) * BYTES);
121 }
122 static inline void set(PointerBuilder builder, typename T::Reader value) {
123 builder.setBlob<T>(value);
124 }
125 static inline void setCanonical(PointerBuilder builder, typename T::Reader value) {
126 builder.setBlob<T>(value);
127 }
128 static inline typename T::Builder init(PointerBuilder builder, uint size) {
129 return builder.initBlob<T>(bounded(size) * BYTES);
130 }
131 static inline void adopt(PointerBuilder builder, Orphan<T>&& value) {
132 builder.adopt(kj::mv(value.builder));
133 }
134 static inline Orphan<T> disown(PointerBuilder builder) {
135 return Orphan<T>(builder.disown());
136 }
137};
138
139struct UncheckedMessage {
140 typedef const word* Reader;
141};
142
143template <> struct Kind_<UncheckedMessage> { static constexpr Kind kind = Kind::OTHER; };
144
145template <>
146struct PointerHelpers<UncheckedMessage> {
147 // Reads an AnyPointer field as an unchecked message pointer. Requires that the containing
148 // message is itself unchecked. This hack is currently private. It is used to locate default
149 // values within encoded schemas.
150
151 static inline const word* get(PointerReader reader) {
152 return reader.getUnchecked();
153 }
154};
155
156} // namespace _ (private)
157} // namespace capnp
158