userver: userver/storages/postgres/io/geometry_types.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 {
29 return x == rhs.x && y == rhs.y;
30 }
31 constexpr bool operator!=(const Point& rhs) const { return !(*this == rhs); }
32
33 double x;
34 double y;
35};
36
37struct LineSegment {
38 constexpr bool operator==(const LineSegment& rhs) const {
39 return ends[0] == rhs.ends[0] && ends[1] == rhs.ends[1];
40 }
41 constexpr bool operator!=(const LineSegment& rhs) const {
42 return !(*this == rhs);
43 }
44
45 std::array<Point, 2> ends{};
46};
47
48// Line is stored as coefficients to equation a*x + b*y + c = 0
49struct Line {
50 constexpr bool operator==(const Line& rhs) const {
51 return a == rhs.a && b == rhs.b && c == rhs.c;
52 }
53 constexpr bool operator!=(const Line& rhs) const { return !(*this == rhs); }
54
55 double a;
56 double b;
57 double c;
58};
59
60struct Box {
61 constexpr bool operator==(const Box& rhs) const {
62 return corners[0] == rhs.corners[0] && corners[1] == rhs.corners[1];
63 }
64 constexpr bool operator!=(const Box& rhs) const { return !(*this == rhs); }
65
66 std::array<Point, 2> corners{};
67};
68
69struct Path {
70 bool operator==(const Path& rhs) const {
71 return is_closed == rhs.is_closed && points == rhs.points;
72 }
73 bool operator!=(const Path& rhs) const { return !(*this == rhs); }
74
75 bool is_closed{false};
76 std::vector<Point> points;
77};
78
79struct Polygon {
80 bool operator==(const Polygon& rhs) const { return points == rhs.points; }
81 bool operator!=(const Polygon& rhs) const { return !(*this == rhs); }
82
83 std::vector<Point> points;
84};
85
86struct Circle {
87 constexpr bool operator==(const Circle& rhs) const {
88 return center == rhs.center && radius == rhs.radius;
89 }
90 constexpr bool operator!=(const Circle& rhs) const { return !(*this == rhs); }
91
92 Point center;
93 double radius;
94};
95//@}
96
97struct PointParser : BufferParserBase<Point> {
98 using BaseType = BufferParserBase<Point>;
99 using BaseType::BaseType;
100
101 void operator()(FieldBuffer buffer) {
102 buffer.Read(value.x);
103 buffer.Read(value.y);
104 }
105};
106
107struct PointFormatter : BufferFormatterBase<Point> {
108 using BaseType = BufferFormatterBase<Point>;
109 using BaseType::BaseType;
110
111 template <typename Buffer>
112 void operator()(const UserTypes& types, Buffer& buffer) const {
113 io::WriteBuffer(types, buffer, value.x);
114 io::WriteBuffer(types, buffer, value.y);
115 }
116};
117
118struct LineSegmentParser : BufferParserBase<LineSegment> {
119 using BaseType = BufferParserBase<LineSegment>;
120 using BaseType::BaseType;
121
122 void operator()(FieldBuffer buffer) {
123 buffer.Read(value.ends[0]);
124 buffer.Read(value.ends[1]);
125 }
126};
127
128struct LineSegmentFormatter : BufferFormatterBase<LineSegment> {
129 using BaseType = BufferFormatterBase<LineSegment>;
130 using BaseType::BaseType;
131
132 template <typename Buffer>
133 void operator()(const UserTypes& types, Buffer& buffer) const {
134 io::WriteBuffer(types, buffer, value.ends[0]);
135 io::WriteBuffer(types, buffer, value.ends[1]);
136 }
137};
138
139struct LineParser : BufferParserBase<Line> {
140 using BaseType = BufferParserBase<Line>;
141 using BaseType::BaseType;
142
143 void operator()(FieldBuffer buffer) {
144 buffer.Read(value.a);
145 buffer.Read(value.b);
146 buffer.Read(value.c);
147 }
148};
149
150struct LineFormatter : BufferFormatterBase<Line> {
151 using BaseType = BufferFormatterBase<Line>;
152 using BaseType::BaseType;
153
154 template <typename Buffer>
155 void operator()(const UserTypes& types, Buffer& buffer) const {
156 io::WriteBuffer(types, buffer, value.a);
157 io::WriteBuffer(types, buffer, value.b);
158 io::WriteBuffer(types, buffer, value.c);
159 }
160};
161
162struct BoxParser : BufferParserBase<Box> {
163 using BaseType = BufferParserBase<Box>;
164 using BaseType::BaseType;
165
166 void operator()(FieldBuffer buffer) {
167 buffer.Read(value.corners[0]);
168 buffer.Read(value.corners[1]);
169 }
170};
171
172struct BoxFormatter : BufferFormatterBase<Box> {
173 using BaseType = BufferFormatterBase<Box>;
174 using BaseType::BaseType;
175
176 template <typename Buffer>
177 void operator()(const UserTypes& types, Buffer& buffer) const {
178 io::WriteBuffer(types, buffer, value.corners[0]);
179 io::WriteBuffer(types, buffer, value.corners[1]);
180 }
181};
182
183struct PathParser : BufferParserBase<Path> {
184 using BaseType = BufferParserBase<Path>;
185 using BaseType::BaseType;
186
187 void operator()(FieldBuffer buffer) {
188 buffer.Read(value.is_closed);
189 Integer point_no{0};
190 buffer.Read(point_no);
191 value.points.resize(point_no);
192 for (auto i = 0; i < point_no; ++i) {
193 buffer.Read(value.points[i]);
194 }
195 }
196};
197
198struct PathFormatter : BufferFormatterBase<Path> {
199 using BaseType = BufferFormatterBase<Path>;
200 using BaseType::BaseType;
201
202 template <typename Buffer>
203 void operator()(const UserTypes& types, Buffer& buffer) const {
204 io::WriteBuffer(types, buffer, value.is_closed);
205 Integer points_no = value.points.size();
206 io::WriteBuffer(types, buffer, points_no);
207 for (const auto& p : value.points) {
208 io::WriteBuffer(types, buffer, p);
209 }
210 }
211};
212
213struct PolygonParser : BufferParserBase<Polygon> {
214 using BaseType = BufferParserBase<Polygon>;
215 using BaseType::BaseType;
216
217 void operator()(FieldBuffer buffer) {
218 Integer point_no{0};
219 buffer.Read(point_no);
220 value.points.resize(point_no);
221 for (auto i = 0; i < point_no; ++i) {
222 buffer.Read(value.points[i]);
223 }
224 }
225};
226
227struct PolygonFormatter : BufferFormatterBase<Polygon> {
228 using BaseType = BufferFormatterBase<Polygon>;
229 using BaseType::BaseType;
230
231 template <typename Buffer>
232 void operator()(const UserTypes& types, Buffer& buffer) const {
233 Integer points_no = value.points.size();
234 io::WriteBuffer(types, buffer, points_no);
235 for (const auto& p : value.points) {
236 io::WriteBuffer(types, buffer, p);
237 }
238 }
239};
240
241struct CircleParser : BufferParserBase<Circle> {
242 using BaseType = BufferParserBase<Circle>;
243 using BaseType::BaseType;
244
245 void operator()(FieldBuffer buffer) {
246 buffer.Read(value.center);
247 buffer.Read(value.radius);
248 }
249};
250
251struct CircleFormatter : BufferFormatterBase<Circle> {
252 using BaseType = BufferFormatterBase<Circle>;
253 using BaseType::BaseType;
254
255 template <typename Buffer>
256 void operator()(const UserTypes& types, Buffer& buffer) const {
257 io::WriteBuffer(types, buffer, value.center);
258 io::WriteBuffer(types, buffer, value.radius);
259 }
260};
261
262} // namespace detail
263
264namespace traits {
265
266template <>
267struct Input<io::detail::Point> {
268 using type = io::detail::PointParser;
269};
270
271template <>
272struct ParserBufferCategory<io::detail::PointParser>
274
275template <>
276struct Output<io::detail::Point> {
277 using type = io::detail::PointFormatter;
278};
279
280template <>
281struct Input<io::detail::LineSegment> {
283};
284
285template <>
286struct ParserBufferCategory<io::detail::LineSegmentParser>
288
289template <>
290struct Output<io::detail::LineSegment> {
292};
293
294template <>
295struct Input<io::detail::Line> {
296 using type = io::detail::LineParser;
297};
298
299template <>
300struct ParserBufferCategory<io::detail::LineParser>
302
303template <>
304struct Output<io::detail::Line> {
305 using type = io::detail::LineFormatter;
306};
307
308template <>
309struct Input<io::detail::Box> {
310 using type = io::detail::BoxParser;
311};
312
313template <>
314struct ParserBufferCategory<io::detail::BoxParser>
316
317template <>
318struct Output<io::detail::Box> {
319 using type = io::detail::BoxFormatter;
320};
321
322template <>
323struct Input<io::detail::Path> {
324 using type = io::detail::PathParser;
325};
326
327template <>
328struct ParserBufferCategory<io::detail::PathParser>
330
331template <>
332struct Output<io::detail::Path> {
333 using type = io::detail::PathFormatter;
334};
335
336template <>
337struct Input<io::detail::Polygon> {
338 using type = io::detail::PolygonParser;
339};
340
341template <>
342struct ParserBufferCategory<io::detail::PolygonParser>
344
345template <>
346struct Output<io::detail::Polygon> {
347 using type = io::detail::PolygonFormatter;
348};
349
350template <>
351struct Input<io::detail::Circle> {
352 using type = io::detail::CircleParser;
353};
354
355template <>
356struct ParserBufferCategory<io::detail::CircleParser>
358
359template <>
360struct Output<io::detail::Circle> {
361 using type = io::detail::CircleFormatter;
362};
363
364} // namespace traits
365
366template <>
367struct CppToSystemPg<detail::Point> : PredefinedOid<PredefinedOids::kPoint> {};
368template <>
369struct CppToSystemPg<detail::LineSegment>
370 : PredefinedOid<PredefinedOids::kLseg> {};
371template <>
372struct CppToSystemPg<detail::Line> : PredefinedOid<PredefinedOids::kLine> {};
373template <>
374struct CppToSystemPg<detail::Box> : PredefinedOid<PredefinedOids::kBox> {};
375template <>
376struct CppToSystemPg<detail::Path> : PredefinedOid<PredefinedOids::kPath> {};
377template <>
378struct CppToSystemPg<detail::Polygon>
379 : PredefinedOid<PredefinedOids::kPolygon> {};
380template <>
381struct CppToSystemPg<detail::Circle> : PredefinedOid<PredefinedOids::kCircle> {
382};
383
384} // namespace storages::postgres::io
385
386USERVER_NAMESPACE_END