@Override
  protected String buildWriteMethodBody() {
    resetStringBuilder();
    buildString("{");

    buildString("if($2 == null) {");
    buildString("  if($3) {");
    buildString(
        "    throw new %s(\"Attempted to write null\");", MessageTypeException.class.getName());
    buildString("  }");
    buildString("  $1.writeNil();");
    buildString("  return;");
    buildString("}");

    buildString("%s _$$_t = (%s)$2;", origName, origName);
    buildString("$1.writeArrayBegin(%d);", entries.length);

    for (int i = 0; i < entries.length; i++) {
      BeansFieldEntry e = entries[i];
      if (!e.isAvailable()) {
        buildString("$1.writeNil();");
        continue;
      }
      Class<?> type = e.getType();
      if (type.isPrimitive()) {
        buildString("$1.%s(_$$_t.%s());", primitiveWriteName(type), e.getGetterName());
      } else {
        buildString("if(_$$_t.%s() == null) {", e.getGetterName());
        if (e.isNotNullable()) {
          buildString("throw new %s();", MessageTypeException.class.getName());
        } else {
          buildString("$1.writeNil();");
        }
        buildString("} else {");
        buildString("  this.templates[%d].write($1, _$$_t.%s());", i, e.getGetterName());
        buildString("}");
      }
    }

    buildString("$1.writeArrayEnd();");
    buildString("}");
    return getBuiltString();
  }
  @Override
  protected String buildReadMethodBody() {
    resetStringBuilder();
    buildString("{ ");

    buildString("if(!$3 && $1.trySkipNil()) {");
    buildString("  return null;");
    buildString("}");

    buildString("%s _$$_t;", origName);
    buildString("if($2 == null) {");
    buildString("  _$$_t = new %s();", origName);
    buildString("} else {");
    buildString("  _$$_t = (%s)$2;", origName);
    buildString("}");

    buildString("$1.readArrayBegin();");

    for (int i = 0; i < entries.length; i++) {
      BeansFieldEntry e = entries[i];

      if (!e.isAvailable()) {
        buildString("$1.skip();"); // TODO #MN
        continue;
      }

      if (e.isOptional()) {
        buildString("if($1.trySkipNil()) {");
        buildString("_$$_t.%s(null);", e.getSetterName());
        buildString("} else {");
      }

      Class<?> type = e.getType();
      if (type.isPrimitive()) {
        buildString("_$$_t.%s( $1.%s() );", e.getSetterName(), primitiveReadName(type));
      } else {
        buildString(
            "_$$_t.%s( (%s)this.templates[%d].read($1, _$$_t.%s()) );",
            e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName());
      }

      if (e.isOptional()) {
        buildString("}");
      }
    }

    buildString("$1.readArrayEnd();");
    buildString("return _$$_t;");

    buildString("}");

    return getBuiltString();
  }