private Object readDynamicGroup(int size, ByteSource in) throws IOException {
    ByteBuf inbuf = (ByteBuf) in;
    int expectedEndPos = inbuf.position() + size;
    // PENDING: currently msgcodec only supports int32 as group id
    int groupId = (int) NativeBlinkInput.readUInt64(inbuf);
    inbuf.skip(4); // discard extension offset (not supported)
    try {
      Object group = readStaticGroup(groupId, inbuf);

      int skip = expectedEndPos - inbuf.position();
      if (skip < 0) {
        throw new DecodeException(
            "Malformed dynamic group. Read " + (-skip) + " bytes beyond group size.");
      } else if (skip > 0) {
        in.skip(skip);
      }
      return group;
    } catch (Exception e) {
      GroupDef groupDef = codec.getSchema().getGroup(groupId);
      if (groupDef != null) {
        throw new GroupDecodeException(groupDef.getName(), e);
      } else {
        throw e;
      }
    }
  }
 @Override
 public Object readDynamicGroupNull(ByteSource in) throws IOException {
   if (in.read() != 0) {
     return readDynamicGroup(in);
   } else {
     return null;
   }
 }