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 {
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