Blob.java (2490B)
1 package osm.message; 2 3 import java.util.zip.Inflater; 4 5 import protobuf.Message; 6 import protobuf.ProtobufReader; 7 8 import java.io.UnsupportedEncodingException; 9 import java.util.Iterator; 10 import java.util.List; 11 import 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. 18 public 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 }