/**
  * Method for outputting indicate Json numeric value. Can be called in any context where a value
  * is expected (Array value, Object field value, root-level value). Additional white space may be
  * added around the value if pretty-printing is enabled.
  */
 @Override
 public void writeNumber(float f) throws IOException, JsonGenerationException {
   if (fieldContext == null) return;
   switch (fieldContext.getProtobufType()) {
     case DEFAULT:
     case FLOAT:
       outputContext.startElement();
       outputContext.writeKey(WireType.Fixed32);
       outputContext.fixed32(f);
       outputContext.endElement();
       break;
     case DOUBLE:
       outputContext.startElement();
       outputContext.writeKey(WireType.Fixed64);
       outputContext.fixed64((double) f);
       outputContext.endElement();
       break;
     case INT32:
     case INT64:
     case UINT32:
     case UINT64:
     case SINT32:
     case SINT64:
     case FIXED32:
     case FIXED64:
     case SFIXED32:
     case SFIXED64:
       writeNumber((long) f);
       break;
   }
 }
 /**
  * Method similar to {@link #writeString(String)}, but that takes {@link SerializableString} which
  * can make this potentially more efficient to call as generator may be able to reuse quoted
  * and/or encoded representation.
  *
  * <p>Default implementation just calls {@link #writeString(String)}; sub-classes should override
  * it with more efficient implementation if possible.
  */
 @SuppressWarnings("fallthrough")
 public void writeString(SerializableString text) throws IOException, JsonGenerationException {
   if (fieldContext == null) return;
   EnumDescription enumDescription;
   switch (fieldContext.getProtobufType()) {
     case DEFAULT:
       enumDescription = schema.getEnumDescription(fieldContext);
       if (enumDescription != null) {
         Integer value = enumDescription.getValue(text.getValue());
         if (value != null) {
           outputContext.startElement();
           outputContext.writeKey(WireType.Varint);
           outputContext.varint(value);
           outputContext.endElement();
         }
         return;
       }
       /*FALLTHROUGH*/
     case STRING:
     case BYTES:
       byte[] bytes = text.asUnquotedUTF8();
       outputContext.startElement();
       outputContext.writeKey(WireType.LengthDelimited);
       outputContext.varint(bytes.length);
       outputContext.out().write(bytes);
       outputContext.endElement();
       break;
     default:
       // ... automatic conversions...
   }
 }
 /**
  * Method for outputting literal Json boolean value (one of Strings 'true' and 'false'). Can be
  * called in any context where a value is expected (Array value, Object field value, root-level
  * value). Additional white space may be added around the value if pretty-printing is enabled.
  */
 @Override
 public void writeBoolean(boolean state) throws IOException, JsonGenerationException {
   if (fieldContext == null) return;
   switch (fieldContext.getProtobufType()) {
     case DEFAULT:
       outputContext.startElement();
       outputContext.writeKey(WireType.Varint);
       outputContext.out().write(state ? 1 : 0);
       outputContext.endElement();
       break;
   }
 }
 /**
  * Method for writing starting marker of a JSON Array value (character '['; plus possible white
  * space decoration if pretty-printing is enabled).
  *
  * <p>Array values can be written in any context where values are allowed: meaning everywhere
  * except for when a field name is expected.
  */
 @Override
 public void writeStartArray() throws IOException, JsonGenerationException {
   if (fieldContext == null) {
     outputContext = new IgnoredContext(outputContext, false);
     return;
   }
   if (fieldContext.isPacked()) {
     outputContext.startElement();
     outputContext.writeKey(WireType.LengthDelimited);
     outputContext = new PackedOutputContext(outputContext);
     return;
   }
   outputContext = new RepeatedOutputContext(outputContext);
 }
 /**
  * Method that will output given chunk of binary data as base64 encoded, as a complete String
  * value (surrounded by double quotes). This method defaults
  *
  * <p>Note: because Json Strings can not contain unescaped linefeeds, if linefeeds are included
  * (as per last argument), they must be escaped. This adds overhead for decoding without improving
  * readability. Alternatively if linefeeds are not included, resulting String value may violate
  * the requirement of base64 RFC which mandates line-length of 76 characters and use of linefeeds.
  * However, all {@link JsonParser} implementations are required to accept such "long line base64";
  * as do typical production-level base64 decoders.
  *
  * @param b64variant Base64 variant to use: defines details such as whether padding is used (and
  *     if so, using which character); what is the maximum line length before adding linefeed, and
  *     also the underlying alphabet to use.
  */
 @Override
 public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len)
     throws IOException, JsonGenerationException {
   if (fieldContext == null) return;
   switch (fieldContext.getProtobufType()) {
     case DEFAULT:
     case BYTES:
       outputContext.startElement();
       outputContext.writeKey(WireType.LengthDelimited);
       outputContext.varint(len);
       outputContext.out().write(data, offset, len);
       outputContext.endElement();
       break;
   }
 }
 /**
  * Method for outputting given value as Json number. Can be called in any context where a value is
  * expected (Array value, Object field value, root-level value). Additional white space may be
  * added around the value if pretty-printing is enabled.
  */
 @Override
 public void writeNumber(int v) throws IOException, JsonGenerationException {
   if (fieldContext == null) return;
   switch (fieldContext.getProtobufType()) {
     case DEFAULT:
     case INT32:
     case INT64:
     case UINT32:
     case UINT64:
       outputContext.startElement();
       outputContext.writeKey(WireType.Varint);
       outputContext.varint(v);
       outputContext.endElement();
       break;
     case SINT32:
     case SINT64:
       outputContext.startElement();
       outputContext.writeKey(WireType.Varint);
       outputContext.svarint(v);
       outputContext.endElement();
       break;
     case FIXED32:
       outputContext.startElement();
       outputContext.writeKey(WireType.Fixed32);
       outputContext.fixed32(v);
       outputContext.endElement();
       break;
     case FIXED64:
       outputContext.startElement();
       outputContext.writeKey(WireType.Fixed64);
       outputContext.fixed64(v);
       outputContext.endElement();
       break;
     case SFIXED32:
       outputContext.startElement();
       outputContext.writeKey(WireType.Fixed32);
       outputContext.sfixed32(v);
       outputContext.endElement();
       break;
     case SFIXED64:
       outputContext.startElement();
       outputContext.writeKey(WireType.Fixed64);
       outputContext.sfixed64(v);
       outputContext.endElement();
       break;
   }
 }