code: public static <Message extends PMessage<Message, Field>, Field extends PField>
      int writeMessage(BigEndianBinaryWriter writer, Message message)
              throws IOException {
          if (message instanceof BinaryWriter) {
              return ((BinaryWriter) message).writeBinary(writer);
          }
  
          int len = 0;
          if (message instanceof PUnion) {
              if (((PUnion) message).unionFieldIsSet()) {
                  PField field = ((PUnion) message).unionField();
                  len += writeFieldSpec(writer, forType(field.getDescriptor().getType()), field.getId());
                  len += writeFieldValue(writer,
                                         message.get(field.getId()),
                                         field.getDescriptor());
              }
          } else {
              for (PField field : message.descriptor().getFields()) {
                  if (message.has(field.getId())) {
                      len += writeFieldSpec(writer, forType(field.getDescriptor().getType()), field.getId());
                      len += writeFieldValue(writer,
                                             message.get(field.getId()),
                                             field.getDescriptor());
                  }
              }
          }
          len += writer.writeUInt8(BinaryType.STOP);
          return len;
      }
docs: Write message to writer.
  
  @param writer The binary writer.
  @param message The message to write.
  @param <Message> The message type.
  @param <Field> The field type.
  @return The number of bytes written.
  @throws IOException If write failed.