persolijn

an efficient router for busses
Log | Files | Refs

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 }