@@ -39,6 +39,10 @@ private TextFormat() {}
39
39
private static final Logger logger = Logger .getLogger (TextFormat .class .getName ());
40
40
41
41
private static final String DEBUG_STRING_SILENT_MARKER = " \t " ;
42
+ private static final String ENABLE_INSERT_SILENT_MARKER_ENV_NAME =
43
+ "SILENT_MARKER_INSERTION_ENABLED" ;
44
+ private static final boolean ENABLE_INSERT_SILENT_MARKER =
45
+ "true" .equals (System .getenv (ENABLE_INSERT_SILENT_MARKER_ENV_NAME ));
42
46
43
47
private static final String REDACTED_MARKER = "[REDACTED]" ;
44
48
@@ -118,6 +122,11 @@ public static Printer debugFormatPrinter() {
118
122
return Printer .DEFAULT_DEBUG_FORMAT ;
119
123
}
120
124
125
+ /** Printer instance which escapes non-ASCII characters and prints in the debug format. */
126
+ public static Printer defaultFormatPrinter () {
127
+ return Printer .DEFAULT_FORMAT ;
128
+ }
129
+
121
130
/** Helper class for converting protobufs to text. */
122
131
public static final class Printer {
123
132
@@ -141,6 +150,27 @@ public static final class Printer {
141
150
/* enablingSafeDebugFormat= */ true ,
142
151
/* singleLine= */ false );
143
152
153
+ // Printer instance which escapes non-ASCII characters and inserts a silent marker.
154
+ private static final Printer DEFAULT_FORMAT =
155
+ new Printer (
156
+ /* escapeNonAscii= */ true ,
157
+ /* useShortRepeatedPrimitives= */ false ,
158
+ TypeRegistry .getEmptyTypeRegistry (),
159
+ ExtensionRegistryLite .getEmptyRegistry (),
160
+ /* enablingSafeDebugFormat= */ false ,
161
+ /* singleLine= */ false )
162
+ .setInsertSilentMarker (ENABLE_INSERT_SILENT_MARKER );
163
+
164
+ static Printer getOutputModePrinter () {
165
+ if (ProtobufToStringOutput .isDefaultFormat ()) {
166
+ return defaultFormatPrinter ();
167
+ } else if (ProtobufToStringOutput .shouldOutputDebugFormat ()) {
168
+ return debugFormatPrinter ();
169
+ } else {
170
+ return printer ();
171
+ }
172
+ }
173
+
144
174
/**
145
175
* A list of the public APIs that output human-readable text from a message. A higher-level API
146
176
* must be larger than any lower-level APIs it calls under the hood, e.g
@@ -186,6 +216,14 @@ static enum FieldReporterLevel {
186
216
187
217
private final boolean singleLine ;
188
218
219
+ private boolean insertSilentMarker ;
220
+
221
+ @ CanIgnoreReturnValue
222
+ private Printer setInsertSilentMarker (boolean insertSilentMarker ) {
223
+ this .insertSilentMarker = insertSilentMarker ;
224
+ return this ;
225
+ }
226
+
189
227
// Any API level equal to or greater than this level will be reported. This is set to
190
228
// REPORT_NONE by default to prevent reporting for now.
191
229
private static final ThreadLocal <FieldReporterLevel > sensitiveFieldReportingLevel =
@@ -209,6 +247,7 @@ private Printer(
209
247
this .extensionRegistry = extensionRegistry ;
210
248
this .enablingSafeDebugFormat = enablingSafeDebugFormat ;
211
249
this .singleLine = singleLine ;
250
+ this .insertSilentMarker = false ;
212
251
}
213
252
214
253
/**
@@ -338,7 +377,12 @@ public void print(final MessageOrBuilder message, final Appendable output) throw
338
377
void print (final MessageOrBuilder message , final Appendable output , FieldReporterLevel level )
339
378
throws IOException {
340
379
TextGenerator generator =
341
- setSingleLineOutput (output , this .singleLine , message .getDescriptorForType (), level );
380
+ setSingleLineOutput (
381
+ output ,
382
+ this .singleLine ,
383
+ message .getDescriptorForType (),
384
+ level ,
385
+ this .insertSilentMarker );
342
386
print (message , generator );
343
387
}
344
388
@@ -408,7 +452,9 @@ private boolean printAny(final MessageOrBuilder message, final TextGenerator gen
408
452
}
409
453
generator .print ("[" );
410
454
generator .print (typeUrl );
411
- generator .print ("] {" );
455
+ generator .print ("]" );
456
+ generator .maybePrintSilentMarker ();
457
+ generator .print ("{" );
412
458
generator .eol ();
413
459
generator .indent ();
414
460
print (contentBuilder , generator );
@@ -792,11 +838,13 @@ private void printSingleField(
792
838
}
793
839
794
840
if (field .getJavaType () == FieldDescriptor .JavaType .MESSAGE ) {
795
- generator .print (" {" );
841
+ generator .maybePrintSilentMarker ();
842
+ generator .print ("{" );
796
843
generator .eol ();
797
844
generator .indent ();
798
845
} else {
799
- generator .print (": " );
846
+ generator .print (":" );
847
+ generator .maybePrintSilentMarker ();
800
848
}
801
849
802
850
printFieldValue (field , value , generator );
@@ -831,7 +879,8 @@ private static void printUnknownFields(
831
879
redact );
832
880
for (final UnknownFieldSet value : field .getGroupList ()) {
833
881
generator .print (entry .getKey ().toString ());
834
- generator .print (" {" );
882
+ generator .maybePrintSilentMarker ();
883
+ generator .print ("{" );
835
884
generator .eol ();
836
885
generator .indent ();
837
886
printUnknownFields (value , generator , redact );
@@ -851,7 +900,8 @@ private static void printUnknownField(
851
900
throws IOException {
852
901
for (final Object value : values ) {
853
902
generator .print (String .valueOf (number ));
854
- generator .print (": " );
903
+ generator .print (":" );
904
+ generator .maybePrintSilentMarker ();
855
905
printUnknownFieldValue (wireType , value , generator , redact );
856
906
generator .eol ();
857
907
}
@@ -879,22 +929,26 @@ public static String unsignedToString(final long value) {
879
929
}
880
930
881
931
private static TextGenerator setSingleLineOutput (Appendable output , boolean singleLine ) {
882
- return new TextGenerator (output , singleLine , null , Printer .FieldReporterLevel .TEXT_GENERATOR );
932
+ return new TextGenerator (
933
+ output , singleLine , null , Printer .FieldReporterLevel .TEXT_GENERATOR , false );
883
934
}
884
935
885
936
private static TextGenerator setSingleLineOutput (
886
937
Appendable output ,
887
938
boolean singleLine ,
888
939
Descriptor rootMessageType ,
889
- Printer .FieldReporterLevel fieldReporterLevel ) {
890
- return new TextGenerator (output , singleLine , rootMessageType , fieldReporterLevel );
940
+ Printer .FieldReporterLevel fieldReporterLevel ,
941
+ boolean shouldEmitSilentMarker ) {
942
+ return new TextGenerator (
943
+ output , singleLine , rootMessageType , fieldReporterLevel , shouldEmitSilentMarker );
891
944
}
892
945
893
946
/** An inner class for writing text to the output stream. */
894
947
private static final class TextGenerator {
895
948
private final Appendable output ;
896
949
private final StringBuilder indent = new StringBuilder ();
897
950
private final boolean singleLineMode ;
951
+ private boolean shouldEmitSilentMarker ;
898
952
// While technically we are "at the start of a line" at the very beginning of the output, all
899
953
// we would do in response to this is emit the (zero length) indentation, so it has no effect.
900
954
// Setting it false here does however suppress an unwanted leading space in single-line mode.
@@ -910,11 +964,13 @@ private TextGenerator(
910
964
final Appendable output ,
911
965
boolean singleLineMode ,
912
966
Descriptor rootMessageType ,
913
- Printer .FieldReporterLevel fieldReporterLevel ) {
967
+ Printer .FieldReporterLevel fieldReporterLevel ,
968
+ boolean shouldEmitSilentMarker ) {
914
969
this .output = output ;
915
970
this .singleLineMode = singleLineMode ;
916
971
this .rootMessageType = rootMessageType ;
917
972
this .fieldReporterLevel = fieldReporterLevel ;
973
+ this .shouldEmitSilentMarker = shouldEmitSilentMarker ;
918
974
}
919
975
920
976
/**
@@ -958,6 +1014,15 @@ public void eol() throws IOException {
958
1014
}
959
1015
atStartOfLine = true ;
960
1016
}
1017
+
1018
+ void maybePrintSilentMarker () throws IOException {
1019
+ if (shouldEmitSilentMarker ) {
1020
+ output .append (DEBUG_STRING_SILENT_MARKER );
1021
+ shouldEmitSilentMarker = false ;
1022
+ } else {
1023
+ output .append (" " );
1024
+ }
1025
+ }
961
1026
}
962
1027
963
1028
// =================================================================
0 commit comments