private void writeObjectFields(
     Object toWrite,
     FSTClazzInfo serializationInfo,
     FSTClazzInfo.FSTFieldInfo[] fieldInfo,
     int startIndex,
     int version)
     throws IOException {
   try {
     int booleanMask = 0;
     int boolcount = 0;
     final int length = fieldInfo.length;
     int j = startIndex;
     if (!codec.isWritingAttributes()) {
       for (; ; j++) {
         if (j == length || fieldInfo[j].getVersion() != version) {
           if (boolcount > 0) {
             codec.writeFByte(booleanMask << (8 - boolcount));
           }
           break;
         }
         final FSTClazzInfo.FSTFieldInfo subInfo = fieldInfo[j];
         if (subInfo.getIntegralType() != subInfo.BOOL) {
           if (boolcount > 0) {
             codec.writeFByte(booleanMask << (8 - boolcount));
           }
           break;
         } else {
           if (boolcount == 8) {
             codec.writeFByte(booleanMask << (8 - boolcount));
             boolcount = 0;
             booleanMask = 0;
           }
           boolean booleanValue = subInfo.getBooleanValue(toWrite);
           booleanMask = booleanMask << 1;
           booleanMask = (booleanMask | (booleanValue ? 1 : 0));
           boolcount++;
         }
       }
     }
     for (int i = j; i < length; i++) {
       final FSTClazzInfo.FSTFieldInfo subInfo = fieldInfo[i];
       if (subInfo.getVersion() != version) {
         codec.writeVersionTag(subInfo.getVersion());
         writeObjectFields(toWrite, serializationInfo, fieldInfo, i, subInfo.getVersion());
         return;
       }
       codec.writeAttributeName(subInfo);
       if (subInfo.isPrimitive()) {
         // speed safe
         int integralType = subInfo.getIntegralType();
         switch (integralType) {
           case FSTClazzInfo.FSTFieldInfo.BOOL:
             codec.writeFByte(subInfo.getBooleanValue(toWrite) ? 1 : 0);
             break;
           case FSTClazzInfo.FSTFieldInfo.BYTE:
             codec.writeFByte(subInfo.getByteValue(toWrite));
             break;
           case FSTClazzInfo.FSTFieldInfo.CHAR:
             codec.writeFChar((char) subInfo.getCharValue(toWrite));
             break;
           case FSTClazzInfo.FSTFieldInfo.SHORT:
             codec.writeFShort((short) subInfo.getShortValue(toWrite));
             break;
           case FSTClazzInfo.FSTFieldInfo.INT:
             codec.writeFInt(subInfo.getIntValue(toWrite));
             break;
           case FSTClazzInfo.FSTFieldInfo.LONG:
             codec.writeFLong(subInfo.getLongValue(toWrite));
             break;
           case FSTClazzInfo.FSTFieldInfo.FLOAT:
             codec.writeFFloat(subInfo.getFloatValue(toWrite));
             break;
           case FSTClazzInfo.FSTFieldInfo.DOUBLE:
             codec.writeFDouble(subInfo.getDoubleValue(toWrite));
             break;
         }
       } else if (subInfo.isConditional()) {
         final int conditional = codec.getWritten();
         codec.skip(4);
         // object
         Object subObject = subInfo.getObjectValue(toWrite);
         if (subObject == null) {
           codec.writeTag(NULL, null, 0, toWrite);
         } else {
           writeObjectWithContext(subInfo, subObject);
         }
         int v = codec.getWritten();
         codec.writeInt32At(conditional, v);
       } else {
         // object
         Object subObject = subInfo.getObjectValue(toWrite);
         if (subObject == null) {
           codec.writeTag(NULL, null, 0, toWrite);
         } else {
           writeObjectWithContext(subInfo, subObject);
         }
       }
     }
     codec.writeVersionTag((byte) 0);
   } catch (IllegalAccessException ex) {
     throw FSTUtil.rethrow(ex);
   }
 }