docs: public static MultipleObjectsBundle fromStream(BundleStreamSource source) {
      MultipleObjectsBundle bundle = new MultipleObjectsBundle();
      boolean stop = false;
      DBIDVar var = null;
      ArrayModifiableDBIDs ids = null;
      int size = 0;
      while(!stop) {
        BundleStreamSource.Event ev = source.nextEvent();
        switch(ev){
        case END_OF_STREAM:
          stop = true;
          break;
        case META_CHANGED:
          BundleMeta smeta = source.getMeta();
          // rebuild bundle meta
          bundle.meta = new BundleMeta();
          for(int i = 0; i < bundle.columns.size(); i++) {
            bundle.meta.add(smeta.get(i));
          }
          for(int i = bundle.metaLength(); i < smeta.size(); i++) {
            List<Object> data = new ArrayList<>(bundle.dataLength() + 1);
            bundle.appendColumn(smeta.get(i), data);
          }
          if(var == null && source.hasDBIDs()) {
            var = DBIDUtil.newVar();
            ids = DBIDUtil.newArray();
          }
          continue;
        case NEXT_OBJECT:
          if(var != null && source.assignDBID(var)) {
            ids.add(var);
          }
          for(int i = 0; i < bundle.metaLength(); i++) {
            @SuppressWarnings("unchecked")
            final List<Object> col = (List<Object>) bundle.columns.get(i);
            col.add(source.data(i));
          }
          ++size;
          continue;
        default:
          LoggingUtil.warning("Unknown event: " + ev);
          continue;
        }
      }
      if(ids != null) {
        if(size != ids.size()) {
          LOG.warning("Not every object had an DBID - discarding DBIDs: " + size + " != " + ids.size());
        }
        else {
          bundle.setDBIDs(ids);
        }
      }
      return bundle;
    }