code: public static <Message extends PMessage<Message, Field>, Field extends PField>
      Message readMessage(BigEndianBinaryReader input,
                          PMessageDescriptor<Message, Field> descriptor,
                          boolean strict) throws IOException {
          PMessageBuilder<Message, Field> builder = descriptor.builder();
          if (builder instanceof BinaryReader) {
              ((BinaryReader) builder).readBinary(input, strict);
          } else {
              FieldInfo fieldInfo = readFieldInfo(input);
              while (fieldInfo != null) {
                  PField field = descriptor.findFieldById(fieldInfo.getId());
                  if (field != null) {
                      Object value = readFieldValue(input, fieldInfo, field.getDescriptor(), strict);
                      builder.set(field.getId(), value);
                  } else {
                      readFieldValue(input, fieldInfo, null, false);
                  }
  
                  fieldInfo = readFieldInfo(input);
              }
  
              if (strict) {
                  try {
                      builder.validate();
                  } catch (IllegalStateException e) {
                      throw new SerializerException(e, e.getMessage());
                  }
              }
          }
  
          return builder.build();
      }
docs: Read message from reader.
  
  @param input The input reader.
  @param descriptor The message descriptor.
  @param strict If the message should be read in strict mode.
  @param <Message> The message type.
  @param <Field> The field type.
  @return The read and parsed message.
  @throws IOException If read failed.