20
20
import java .nio .charset .CoderMalfunctionError ;
21
21
import java .nio .charset .StandardCharsets ;
22
22
import java .util .Map ;
23
+ import java .util .concurrent .ConcurrentHashMap ;
24
+ import java .util .concurrent .ConcurrentMap ;
23
25
24
26
import org .reactivestreams .Publisher ;
25
27
import reactor .core .publisher .Flux ;
@@ -49,6 +51,9 @@ public final class CharSequenceEncoder extends AbstractEncoder<CharSequence> {
49
51
*/
50
52
public static final Charset DEFAULT_CHARSET = StandardCharsets .UTF_8 ;
51
53
54
+ private final ConcurrentMap <Charset , Float > charsetToMaxBytesPerChar =
55
+ new ConcurrentHashMap <>(3 );
56
+
52
57
53
58
private CharSequenceEncoder (MimeType ... mimeTypes ) {
54
59
super (mimeTypes );
@@ -76,7 +81,8 @@ public Flux<DataBuffer> encode(Publisher<? extends CharSequence> inputStream,
76
81
});
77
82
}
78
83
boolean release = true ;
79
- DataBuffer dataBuffer = bufferFactory .allocateBuffer ();
84
+ int capacity = calculateCapacity (charSequence , charset );
85
+ DataBuffer dataBuffer = bufferFactory .allocateBuffer (capacity );
80
86
try {
81
87
dataBuffer .write (charSequence , charset );
82
88
release = false ;
@@ -93,6 +99,13 @@ public Flux<DataBuffer> encode(Publisher<? extends CharSequence> inputStream,
93
99
});
94
100
}
95
101
102
+ private int calculateCapacity (CharSequence sequence , Charset charset ) {
103
+ float maxBytesPerChar = this .charsetToMaxBytesPerChar
104
+ .computeIfAbsent (charset , cs -> cs .newEncoder ().maxBytesPerChar ());
105
+ float maxBytesForSequence = sequence .length () * maxBytesPerChar ;
106
+ return (int ) Math .ceil (maxBytesForSequence );
107
+ }
108
+
96
109
private Charset getCharset (@ Nullable MimeType mimeType ) {
97
110
if (mimeType != null && mimeType .getCharset () != null ) {
98
111
return mimeType .getCharset ();
0 commit comments