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