userver: userver/storages/postgres/io/geometry_types.hpp Source File
Loading...
Searching...
No Matches
geometry_types.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/io/geometry_types.hpp
4/// @brief Geometry I/O support
5
6#include <array>
7
8#include <userver/storages/postgres/exceptions.hpp>
9#include <userver/storages/postgres/io/buffer_io_base.hpp>
10#include <userver/storages/postgres/io/field_buffer.hpp>
11#include <userver/storages/postgres/io/floating_point_types.hpp>
12#include <userver/storages/postgres/io/traits.hpp>
13#include <userver/storages/postgres/io/type_mapping.hpp>
14#include <userver/storages/postgres/io/type_traits.hpp>
15#include <userver/storages/postgres/io/user_types.hpp>
16
17USERVER_NAMESPACE_BEGIN
18
19namespace storages::postgres::io {
20
21namespace detail {
22
23//@{
24/** @name On-the-wire representation of geometry types */
25// These structures are mere helpers for parsing/formatting PostgreSQL buffers
26// and are not intended to be used as types for geometry calculations
27struct Point {
28 constexpr bool operator==(const Point& rhs) const { return x == rhs.x && y == rhs.y; }
29
30 double x;
31 double y;
32};
33
34struct LineSegment {
35 constexpr bool operator==(const LineSegment& rhs) const { return ends[0] == rhs.ends[0] && ends[1] == rhs.ends[1]; }
36
37 std::array<Point, 2> ends{};
38};
39
40// Line is stored as coefficients to equation a*x + b*y + c = 0
41struct Line {
42 constexpr bool operator==(const Line& rhs) const { return a == rhs.a && b == rhs.b && c == rhs.c; }
43
44 double a;
45 double b;
46 double c;
47};
48
49struct Box {
50 constexpr bool operator==(const Box& rhs) const {
51 return corners[0] == rhs.corners[0] && corners[1] == rhs.corners[1];
52 }
53
54 std::array<Point, 2> corners{};
55};
56
57struct Path {
58 bool operator==(const Path& rhs) const { return is_closed == rhs.is_closed && points == rhs.points; }
59
60 bool is_closed{false};
61 std::vector<Point> points;
62};
63
64struct Polygon {
65 bool operator==(const Polygon& rhs) const { return points == rhs.points; }
66
67 std::vector<Point> points;
68};
69
70struct Circle {
71 constexpr bool operator==(const Circle& rhs) const { return center == rhs.center && radius == rhs.radius; }
72
73 Point center;
74 double radius;
75};
76//@}
77
78struct PointParser : BufferParserBase<Point> {
79 using BaseType = BufferParserBase<Point>;
80 using BaseType::BaseType;
81
82 void operator()(FieldBuffer buffer) {
83 buffer.Read(value.x);
84 buffer.Read(value.y);
85 }
86};
87
88struct PointFormatter : BufferFormatterBase<Point> {
89 using BaseType = BufferFormatterBase<Point>;
90 using BaseType::BaseType;
91
92 template <typename Buffer>
93 void operator()(const UserTypes& types, Buffer& buffer) const {
94 io::WriteBuffer(types, buffer, value.x);
95 io::WriteBuffer(types, buffer, value.y);
96 }
97};
98
99struct LineSegmentParser : BufferParserBase<LineSegment> {
100 using BaseType = BufferParserBase<LineSegment>;
101 using BaseType::BaseType;
102
103 void operator()(FieldBuffer buffer) {
104 buffer.Read(value.ends[0]);
105 buffer.Read(value.ends[1]);
106 }
107};
108
109struct LineSegmentFormatter : BufferFormatterBase<LineSegment> {
110 using BaseType = BufferFormatterBase<LineSegment>;
111 using BaseType::BaseType;
112
113 template <typename Buffer>
114 void operator()(const UserTypes& types, Buffer& buffer) const {
115 io::WriteBuffer(types, buffer, value.ends[0]);
116 io::WriteBuffer(types, buffer, value.ends[1]);
117 }
118};
119
120struct LineParser : BufferParserBase<Line> {
121 using BaseType = BufferParserBase<Line>;
122 using BaseType::BaseType;
123
124 void operator()(FieldBuffer buffer) {
125 buffer.Read(value.a);
126 buffer.Read(value.b);
127 buffer.Read(value.c);
128 }
129};
130
131struct LineFormatter : BufferFormatterBase<Line> {
132 using BaseType = BufferFormatterBase<Line>;
133 using BaseType::BaseType;
134
135 template <typename Buffer>
136 void operator()(const UserTypes& types, Buffer& buffer) const {
137 io::WriteBuffer(types, buffer, value.a);
138 io::WriteBuffer(types, buffer, value.b);
139 io::WriteBuffer(types, buffer, value.c);
140 }
141};
142
143struct BoxParser : BufferParserBase<Box> {
144 using BaseType = BufferParserBase<Box>;
145 using BaseType::BaseType;
146
147 void operator()(FieldBuffer buffer) {
148 buffer.Read(value.corners[0]);
149 buffer.Read(value.corners[1]);
150 }
151};
152
153struct BoxFormatter : BufferFormatterBase<Box> {
154 using BaseType = BufferFormatterBase<Box>;
155 using BaseType::BaseType;
156
157 template <typename Buffer>
158 void operator()(const UserTypes& types, Buffer& buffer) const {
159 io::WriteBuffer(types, buffer, value.corners[0]);
160 io::WriteBuffer(types, buffer, value.corners[1]);
161 }
162};
163
164struct PathParser : BufferParserBase<Path> {
165 using BaseType = BufferParserBase<Path>;
166 using BaseType::BaseType;
167
168 void operator()(FieldBuffer buffer) {
169 buffer.Read(value.is_closed);
170 Integer point_no{0};
171 buffer.Read(point_no);
172 value.points.resize(point_no);
173 for (auto i = 0; i < point_no; ++i) {
174 buffer.Read(value.points[i]);
175 }
176 }
177};
178
179struct PathFormatter : BufferFormatterBase<Path> {
180 using BaseType = BufferFormatterBase<Path>;
181 using BaseType::BaseType;
182
183 template <typename Buffer>
184 void operator()(const UserTypes& types, Buffer& buffer) const {
185 io::WriteBuffer(types, buffer, value.is_closed);
186 const Integer points_no = value.points.size();
187 io::WriteBuffer(types, buffer, points_no);
188 for (const auto& p : value.points) {
189 io::WriteBuffer(types, buffer, p);
190 }
191 }
192};
193
194struct PolygonParser : BufferParserBase<Polygon> {
195 using BaseType = BufferParserBase<Polygon>;
196 using BaseType::BaseType;
197
198 void operator()(FieldBuffer buffer) {
199 Integer point_no{0};
200 buffer.Read(point_no);
201 value.points.resize(point_no);
202 for (auto i = 0; i < point_no; ++i) {
203 buffer.Read(value.points[i]);
204 }
205 }
206};
207
208struct PolygonFormatter : BufferFormatterBase<Polygon> {
209 using BaseType = BufferFormatterBase<Polygon>;
210 using BaseType::BaseType;
211
212 template <typename Buffer>
213 void operator()(const UserTypes& types, Buffer& buffer) const {
214 const Integer points_no = value.points.size();
215 io::WriteBuffer(types, buffer, points_no);
216 for (const auto& p : value.points) {
217 io::WriteBuffer(types, buffer, p);
218 }
219 }
220};
221
222struct CircleParser : BufferParserBase<Circle> {
223 using BaseType = BufferParserBase<Circle>;
224 using BaseType::BaseType;
225
226 void operator()(FieldBuffer buffer) {
227 buffer.Read(value.center);
228 buffer.Read(value.radius);
229 }
230};
231
232struct CircleFormatter : BufferFormatterBase<Circle> {
233 using BaseType = BufferFormatterBase<Circle>;
234 using BaseType::BaseType;
235
236 template <typename Buffer>
237 void operator()(const UserTypes& types, Buffer& buffer) const {
238 io::WriteBuffer(types, buffer, value.center);
239 io::WriteBuffer(types, buffer, value.radius);
240 }
241};
242
243} // namespace detail
244
245namespace traits {
246
247template <>
248struct Input<io::detail::Point> {
249 using type = io::detail::PointParser;
250};
251
252template <>
253struct ParserBufferCategory<io::detail::PointParser>
254 : std::integral_constant<BufferCategory, BufferCategory::kPlainBuffer> {};
255
256template <>
257struct Output<io::detail::Point> {
258 using type = io::detail::PointFormatter;
259};
260
261template <>
262struct Input<io::detail::LineSegment> {
263 using type = io::detail::LineSegmentParser;
264};
265
266template <>
267struct ParserBufferCategory<io::detail::LineSegmentParser>
268 : std::integral_constant<BufferCategory, BufferCategory::kPlainBuffer> {};
269
270template <>
271struct Output<io::detail::LineSegment> {
272 using type = io::detail::LineSegmentFormatter;
273};
274
275template <>
276struct Input<io::detail::Line> {
277 using type = io::detail::LineParser;
278};
279
280template <>
281struct ParserBufferCategory<io::detail::LineParser>
282 : std::integral_constant<BufferCategory, BufferCategory::kPlainBuffer> {};
283
284template <>
285struct Output<io::detail::Line> {
286 using type = io::detail::LineFormatter;
287};
288
289template <>
290struct Input<io::detail::Box> {
291 using type = io::detail::BoxParser;
292};
293
294template <>
295struct ParserBufferCategory<io::detail::BoxParser>
296 : std::integral_constant<BufferCategory, BufferCategory::kPlainBuffer> {};
297
298template <>
299struct Output<io::detail::Box> {
300 using type = io::detail::BoxFormatter;
301};
302
303template <>
304struct Input<io::detail::Path> {
305 using type = io::detail::PathParser;
306};
307
308template <>
309struct ParserBufferCategory<io::detail::PathParser>
310 : std::integral_constant<BufferCategory, BufferCategory::kPlainBuffer> {};
311
312template <>
313struct Output<io::detail::Path> {
314 using type = io::detail::PathFormatter;
315};
316
317template <>
318struct Input<io::detail::Polygon> {
319 using type = io::detail::PolygonParser;
320};
321
322template <>
323struct ParserBufferCategory<io::detail::PolygonParser>
324 : std::integral_constant<BufferCategory, BufferCategory::kPlainBuffer> {};
325
326template <>
327struct Output<io::detail::Polygon> {
328 using type = io::detail::PolygonFormatter;
329};
330
331template <>
332struct Input<io::detail::Circle> {
333 using type = io::detail::CircleParser;
334};
335
336template <>
337struct ParserBufferCategory<io::detail::CircleParser>
338 : std::integral_constant<BufferCategory, BufferCategory::kPlainBuffer> {};
339
340template <>
341struct Output<io::detail::Circle> {
342 using type = io::detail::CircleFormatter;
343};
344
345} // namespace traits
346
347template <>
348struct CppToSystemPg<detail::Point> : PredefinedOid<PredefinedOids::kPoint> {};
349template <>
350struct CppToSystemPg<detail::LineSegment> : PredefinedOid<PredefinedOids::kLseg> {};
351template <>
352struct CppToSystemPg<detail::Line> : PredefinedOid<PredefinedOids::kLine> {};
353template <>
354struct CppToSystemPg<detail::Box> : PredefinedOid<PredefinedOids::kBox> {};
355template <>
356struct CppToSystemPg<detail::Path> : PredefinedOid<PredefinedOids::kPath> {};
357template <>
358struct CppToSystemPg<detail::Polygon> : PredefinedOid<PredefinedOids::kPolygon> {};
359template <>
360struct CppToSystemPg<detail::Circle> : PredefinedOid<PredefinedOids::kCircle> {};
361
362} // namespace storages::postgres::io
363
364USERVER_NAMESPACE_END