misc/persolijn

osm-protobuf/src/main/java/osm/message/Blob.java in master
Repositories | Summary | Log | Files

Blob.java (2490B) download


 1package osm.message;
 2
 3import java.util.zip.Inflater;
 4
 5import protobuf.Message;
 6import protobuf.ProtobufReader;
 7
 8import java.io.UnsupportedEncodingException;
 9import java.util.Iterator;
10import java.util.List;
11import java.util.zip.DataFormatException;
12
13// optional bytes raw = 1; // No compression
14// optional int32 raw_size = 2; // When compressed, the uncompressed size
15// optional bytes zlib_data = 3;
16// optional bytes lzma_data = 4;
17// optional bytes OBSOLETE_bzip2_data = 5 [deprecated=true]; // Don't reuse this tag number.
18public class Blob implements Message<Blob> {
19    public final String headerType;
20    public int size = 0;
21
22    public HeaderBlock header = null;
23    public List<Entity> primitive = null;
24
25    public Blob(String headerType) {
26        this.headerType = headerType;
27    }
28
29    @Override
30    public Blob parse(Iterator<ProtobufReader> tags) {
31        while (tags.hasNext()) {
32            ProtobufReader message = tags.next();
33            switch (message.tag()) {
34                case 1 -> {
35                    switch (headerType) {
36                        case "OSMHeader" -> header = message.message(new HeaderBlock());
37                        case "OSMData" -> primitive = message.message(new PrimitiveBlock());
38                    }
39                }
40                case 2 -> size = message.varint32();
41                case 3 -> {
42                    switch (headerType) {
43                        case "OSMHeader" -> message.delayed(new HeaderBlock(), this::decompress, this::setHeader);
44                        case "OSMData" -> message.delayed(new PrimitiveBlock(), this::decompress, this::setPrimitive);
45                    }
46                }
47                default -> message.throwUnexpected();
48            }
49        }
50
51        return this;
52    }
53
54    private void setHeader(HeaderBlock header) {
55        this.header = header;
56    }
57
58    private void setPrimitive(List<Entity> primitive) {
59        this.primitive = primitive;
60    }
61
62    private byte[] decompress(byte[] block) {
63        Inflater decompresser = new Inflater();
64        decompresser.setInput(block);
65
66        try {
67            byte[] buffer = new byte[size];
68            int uncompressedSize = decompresser.inflate(buffer);
69
70            if (uncompressedSize != size) {
71                throw new RuntimeException("Invalid blob payload size");
72            }
73
74            return buffer;
75        } catch (DataFormatException exc) {
76            throw new RuntimeException(exc);
77        }
78    }
79}