comparison pkg/mesh/meshserialize.go @ 5710:37c8feeecb4d

Merged branch sr-v2 into default.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 20 Feb 2024 21:28:56 +0100
parents ef80748ae4f3
children 1ea1d3ef2258
comparison
equal deleted inserted replaced
5672:b1a10654bf0f 5710:37c8feeecb4d
1 // This is Free Software under GNU Affero General Public License v >= 3.0
2 // without warranty, see README.md and license for details.
3 //
4 // SPDX-License-Identifier: AGPL-3.0-or-later
5 // License-Filename: LICENSES/AGPL-3.0.txt
6 //
7 // Copyright (C) 2018 by via donau
8 // – Österreichische Wasserstraßen-Gesellschaft mbH
9 // Software engineering by Intevation GmbH
10 //
11 // Author(s):
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de>
13
14 package mesh
15
16 import (
17 "bufio"
18 "bytes"
19 "compress/gzip"
20 "encoding/binary"
21 "fmt"
22 "io"
23
24 "gemma.intevation.de/gemma/pkg/log"
25 )
26
27 // Version is current version of the format the mesh index is stored in.
28 const Version = 2
29
30 // magicHeader is a magic header to tell if the data blob is a mesh index.
31 const magicHeader = "SR3D"
32
33 // coalesceVersion returns the most recent version if version is less or equal zero.
34 func coalesceVersion(version int) int {
35 if version > 0 {
36 return version
37 }
38 return Version
39 }
40
41 // OptimizeForSerialization apply version specific storage optimizations
42 // before serialization.
43 func (s *STRTree) OptimizeForSerialization(version int) {
44 version = coalesceVersion(version)
45 if version == 2 {
46 s.optimizeForSerializationV2()
47 }
48 }
49
50 // Bytes serializes this tree to a byte slice.
51 func (s *STRTree) Bytes(version int) ([]byte, int, error) {
52 var buf bytes.Buffer
53 w, err := gzip.NewWriterLevel(&buf, gzip.BestSpeed)
54 if err != nil {
55 return nil, 0, err
56 }
57 version = coalesceVersion(version)
58 if err := s.serializeVn(w, version); err != nil {
59 return nil, 0, err
60 }
61 if err := w.Close(); err != nil {
62 return nil, 0, err
63 }
64 return buf.Bytes(), version, nil
65 }
66
67 func (s *STRTree) serializeVn(w io.Writer, version int) error {
68 switch version {
69 case 1:
70 return s.serializeV1(w)
71 case 2:
72 return s.serializeV2(w)
73 default:
74 return fmt.Errorf("cannot serialize mesh version %d", version)
75 }
76 }
77
78 // FromBytes restores a STRTree from a binary representation.
79 func (s *STRTree) FromBytes(data []byte, version int) error {
80 version = coalesceVersion(version)
81 r, err := gzip.NewReader(bytes.NewReader(data))
82 if err != nil {
83 return err
84 }
85 return s.deserialize(bufio.NewReader(r), version)
86 }
87
88 func (s *STRTree) deserialize(r *bufio.Reader, version int) error {
89 header, err := r.Peek(8)
90 if err != nil {
91 return err
92 }
93 if bytes.HasPrefix(header, []byte(magicHeader)) {
94 realVersion := int(binary.LittleEndian.Uint32(header[4:]))
95 if realVersion != version {
96 return fmt.Errorf("mesh version mismatch: Have %d expect %d",
97 realVersion, version)
98 }
99 // Skip the header
100 if _, err := r.Discard(8); err != nil {
101 return err
102 }
103 return s.deserializeVn(r, realVersion)
104 }
105 return s.deserializeV1(r)
106 }
107
108 func (s *STRTree) deserializeVn(r *bufio.Reader, version int) error {
109 switch version {
110 case 1:
111 return s.deserializeV1(r)
112 case 2:
113 return s.deserializeV2(r)
114 default:
115 return fmt.Errorf("cannot deserialize mesh version %d", version)
116 }
117 }
118
119 // serializer is a generic function to apply a chain of
120 // serializer/deserializer functions to an object given a reader or writer.
121 func serializer[T, S any](
122 s S,
123 t T,
124 fns ...func(T, S) error,
125 ) error {
126 for _, fn := range fns {
127 if err := fn(t, s); err != nil {
128 return err
129 }
130 }
131 return nil
132 }
133
134 func (s *STRTree) serializeEntries(w io.Writer) error {
135 return binary.Write(w, binary.LittleEndian, uint8(s.Entries))
136 }
137
138 func (s *STRTree) deserializeEntries(r *bufio.Reader) error {
139 var numEntries uint8
140 if err := binary.Read(r, binary.LittleEndian, &numEntries); err != nil {
141 return err
142 }
143 s.Entries = int(numEntries)
144 return nil
145 }
146
147 func (t *Tin) serializeExtent(w io.Writer) error {
148 if err := t.Min.Write(w); err != nil {
149 return err
150 }
151 return t.Max.Write(w)
152 }
153
154 func (t *Tin) deserializeExtent(r *bufio.Reader) error {
155 if err := t.Min.Read(r); err != nil {
156 return err
157 }
158 if err := t.Max.Read(r); err != nil {
159 return err
160 }
161 log.Infof("BBOX: [[%f, %f, %f], [%f, %f, %f]]\n",
162 t.Min.X, t.Min.Y, t.Min.Z,
163 t.Max.X, t.Max.Y, t.Max.Z)
164 return nil
165 }
166
167 func (t *Tin) serializeEPSG(w io.Writer) error {
168 return binary.Write(w, binary.LittleEndian, t.EPSG)
169 }
170
171 func (t *Tin) deserializeEPSG(r *bufio.Reader) error {
172 if err := binary.Read(r, binary.LittleEndian, &t.EPSG); err != nil {
173 return err
174 }
175 log.Infof("EPSG: %d\n", t.EPSG)
176 return nil
177 }
178
179 func serializeHeader() func(*STRTree, io.Writer) error {
180 return func(_ *STRTree, w io.Writer) error {
181 _, err := w.Write([]byte(magicHeader))
182 return err
183 }
184 }
185
186 func serializeVersion(version int) func(*STRTree, io.Writer) error {
187 return func(_ *STRTree, w io.Writer) error {
188 return binary.Write(w, binary.LittleEndian, uint32(version))
189 }
190 }