• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

brick / geo / 17456208570

04 Sep 2025 07:10AM UTC coverage: 50.432%. Remained the same
17456208570

push

github

BenMorel
Use @extends and @implements instead of @template-* variants

For consistency with the rest of the project.

1867 of 3702 relevant lines covered (50.43%)

1140.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.83
/src/Io/Internal/AbstractWkbWriter.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Brick\Geo\Io\Internal;
6

7
use Brick\Geo\CircularString;
8
use Brick\Geo\CompoundCurve;
9
use Brick\Geo\Curve;
10
use Brick\Geo\CurvePolygon;
11
use Brick\Geo\Exception\GeometryIoException;
12
use Brick\Geo\Geometry;
13
use Brick\Geo\GeometryCollection;
14
use Brick\Geo\LineString;
15
use Brick\Geo\Point;
16
use Brick\Geo\Polygon;
17
use Brick\Geo\PolyhedralSurface;
18

19
use function pack;
20
use function sprintf;
21
use function strrev;
22

23
/**
24
 * Base class for WkbWriter and EwkbWriter.
25
 *
26
 * @internal
27
 */
28
abstract class AbstractWkbWriter
29
{
30
    private WkbByteOrder $byteOrder;
31

32
    private WkbByteOrder $machineByteOrder;
33

34
    /**
35
     * @throws GeometryIoException
36
     */
37
    public function __construct()
38
    {
39
        $this->byteOrder = $this->machineByteOrder = WkbTools::getMachineByteOrder();
5,448✔
40
    }
41

42
    public function setByteOrder(WkbByteOrder $byteOrder): void
43
    {
44
        $this->byteOrder = $byteOrder;
5,376✔
45
    }
46

47
    /**
48
     * @param Geometry $geometry The geometry to export as WKB.
49
     *
50
     * @return string The WKB representation of the given geometry.
51
     *
52
     * @throws GeometryIoException If the given geometry cannot be exported as WKB.
53
     */
54
    public function write(Geometry $geometry): string
55
    {
56
        return $this->doWrite($geometry, true);
7,327✔
57
    }
58

59
    /**
60
     * @param Geometry $geometry The geometry export as WKB write.
61
     * @param bool     $outer    False if the geometry is nested in another geometry, true otherwise.
62
     *
63
     * @return string The WKB representation of the given geometry.
64
     *
65
     * @throws GeometryIoException If the given geometry cannot be exported as WKT.
66
     */
67
    protected function doWrite(Geometry $geometry, bool $outer): string
68
    {
69
        if ($geometry instanceof Point) {
7,327✔
70
            return $this->writePoint($geometry, $outer);
1,210✔
71
        }
72

73
        if ($geometry instanceof LineString) {
6,835✔
74
            return $this->writeCurve($geometry, $outer);
2,295✔
75
        }
76

77
        if ($geometry instanceof CircularString) {
5,758✔
78
            return $this->writeCurve($geometry, $outer);
839✔
79
        }
80

81
        if ($geometry instanceof Polygon) {
5,338✔
82
            return $this->writePolygon($geometry, $outer);
2,323✔
83
        }
84

85
        if ($geometry instanceof CompoundCurve) {
3,991✔
86
            return $this->writeComposedGeometry($geometry, $outer);
508✔
87
        }
88

89
        if ($geometry instanceof CurvePolygon) {
3,579✔
90
            return $this->writeComposedGeometry($geometry, $outer);
398✔
91
        }
92

93
        if ($geometry instanceof GeometryCollection) {
3,181✔
94
            return $this->writeComposedGeometry($geometry, $outer);
2,405✔
95
        }
96

97
        if ($geometry instanceof PolyhedralSurface) {
776✔
98
            return $this->writeComposedGeometry($geometry, $outer);
776✔
99
        }
100

101
        throw GeometryIoException::unsupportedGeometryType($geometry->geometryType());
×
102
    }
103

104
    protected function packUnsignedInteger(int $uint): string
105
    {
106
        return pack(match ($this->byteOrder) {
7,327✔
107
            WkbByteOrder::BigEndian => 'N',
7,327✔
108
            WkbByteOrder::LittleEndian => 'V'
7,327✔
109
        }, $uint);
7,327✔
110
    }
111

112
    abstract protected function packHeader(Geometry $geometry, bool $outer): string;
113

114
    private function packByteOrder(): string
115
    {
116
        return pack('C', $this->byteOrder->value);
7,327✔
117
    }
118

119
    private function packDouble(float $double): string
120
    {
121
        $binary = pack('d', $double);
4,935✔
122

123
        if ($this->byteOrder !== $this->machineByteOrder) {
4,935✔
124
            return strrev($binary);
1,536✔
125
        }
126

127
        return $binary;
3,399✔
128
    }
129

130
    /**
131
     * @throws GeometryIoException
132
     */
133
    private function packPoint(Point $point): string
134
    {
135
        if ($point->isEmpty()) {
4,999✔
136
            throw new GeometryIoException('Empty points have no WKB representation.');
64✔
137
        }
138

139
        /** @psalm-suppress PossiblyNullArgument */
140
        $binary = $this->packDouble($point->x()) . $this->packDouble($point->y());
4,935✔
141

142
        if (null !== $z = $point->z()) {
4,935✔
143
            $binary .= $this->packDouble($z);
1,677✔
144
        }
145
        if (null !== $m = $point->m()) {
4,935✔
146
            $binary .= $this->packDouble($m);
1,632✔
147
        }
148

149
        return $binary;
4,935✔
150
    }
151

152
    /**
153
     * @throws GeometryIoException
154
     */
155
    private function packCurve(Curve $curve): string
156
    {
157
        if (! $curve instanceof LineString && ! $curve instanceof CircularString) {
4,563✔
158
            // CompoundCurve is not a list of Points, not sure if WKB supports it!
159
            // For now, let's just not support it ourselves.
160
            throw new GeometryIoException(sprintf('Writing a %s as WKB is not supported.', $curve->geometryType()));
×
161
        }
162

163
        $wkb = $this->packUnsignedInteger($curve->count());
4,563✔
164

165
        foreach ($curve as $point) {
4,563✔
166
            $wkb .= $this->packPoint($point);
4,171✔
167
        }
168

169
        return $wkb;
4,563✔
170
    }
171

172
    private function writePoint(Point $point, bool $outer): string
173
    {
174
        $wkb = $this->packByteOrder();
1,210✔
175
        $wkb .= $this->packHeader($point, $outer);
1,210✔
176
        $wkb .= $this->packPoint($point);
1,210✔
177

178
        return $wkb;
1,146✔
179
    }
180

181
    private function writeCurve(Curve $curve, bool $outer): string
182
    {
183
        $wkb = $this->packByteOrder();
2,722✔
184
        $wkb .= $this->packHeader($curve, $outer);
2,722✔
185
        $wkb .= $this->packCurve($curve);
2,722✔
186

187
        return $wkb;
2,722✔
188
    }
189

190
    private function writePolygon(Polygon $polygon, bool $outer): string
191
    {
192
        $wkb = $this->packByteOrder();
2,323✔
193
        $wkb .= $this->packHeader($polygon, $outer);
2,323✔
194
        $wkb .= $this->packUnsignedInteger($polygon->count());
2,323✔
195

196
        foreach ($polygon as $ring) {
2,323✔
197
            $wkb .= $this->packCurve($ring);
1,939✔
198
        }
199

200
        return $wkb;
2,323✔
201
    }
202

203
    private function writeComposedGeometry(CompoundCurve|CurvePolygon|GeometryCollection|PolyhedralSurface $collection, bool $outer): string
204
    {
205
        $wkb = $this->packByteOrder();
3,991✔
206
        $wkb .= $this->packHeader($collection, $outer);
3,991✔
207
        $wkb .= $this->packUnsignedInteger($collection->count());
3,991✔
208

209
        foreach ($collection as $geometry) {
3,991✔
210
            $wkb .= $this->doWrite($geometry, false);
2,439✔
211
        }
212

213
        return $wkb;
3,991✔
214
    }
215
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc