@@ -130,26 +130,76 @@ public unsafe void Write(string value, int offset, int length)
130130 }
131131 }
132132#else
133- public void Write ( string value ) => Write ( value . AsSpan ( ) ) ;
134- public void Write ( string value , int offset , int length ) => Write ( value . AsSpan ( offset , length ) ) ;
133+ public void Write ( string value ) => Write ( value . AsSpan ( ) , flush : true ) ;
134+ public void Write ( string value , int offset , int length ) => Write ( value . AsSpan ( offset , length ) , flush : true ) ;
135135
136- public void Write ( ReadOnlySpan < char > chars )
136+ public void Write ( ReadOnlySpan < char > chars , bool flush )
137137 {
138138 m_encoder ??= Encoding . UTF8 . GetEncoder ( ) ;
139139 while ( chars . Length > 0 )
140140 {
141141 if ( m_output . Length < 4 )
142142 Reallocate ( ) ;
143- m_encoder . Convert ( chars , m_output . Span , true , out var charsUsed , out var bytesUsed , out var completed ) ;
143+ m_encoder . Convert ( chars , m_output . Span , flush : false , out var charsUsed , out var bytesUsed , out var completed ) ;
144144 chars = chars . Slice ( charsUsed ) ;
145145 m_output = m_output . Slice ( bytesUsed ) ;
146146 if ( ! completed )
147147 Reallocate ( ) ;
148148 Debug . Assert ( completed == ( chars . Length == 0 ) ) ;
149149 }
150+
151+ if ( flush && m_encoder is not null )
152+ {
153+ if ( m_output . Length < 4 )
154+ Reallocate ( ) ;
155+ m_encoder . Convert ( "" . AsSpan ( ) , m_output . Span , flush : true , out _ , out var bytesUsed , out _ ) ;
156+ m_output = m_output . Slice ( bytesUsed ) ;
157+ }
150158 }
151159#endif
152160
161+ public void WriteLengthEncodedString ( StringBuilder stringBuilder )
162+ {
163+ #if ! NET45 && ! NET461 && ! NET471 && ! NETSTANDARD1_3 && ! NETSTANDARD2_0 && ! NETSTANDARD2_1 && ! NETCOREAPP2_1
164+ // save where the length will be written
165+ var lengthPosition = Position ;
166+ if ( m_output . Length < 9 )
167+ Reallocate ( 9 ) ;
168+ Advance ( 9 ) ;
169+
170+ // write all the text as UTF-8
171+ m_encoder ??= Encoding . UTF8 . GetEncoder ( ) ;
172+ foreach ( var chunk in stringBuilder . GetChunks ( ) )
173+ {
174+ var currentSpan = chunk . Span ;
175+ while ( currentSpan . Length > 0 )
176+ {
177+ if ( m_output . Length < 4 )
178+ Reallocate ( ) ;
179+ m_encoder . Convert ( currentSpan , m_output . Span , false , out var charsUsed , out var bytesUsed , out var completed ) ;
180+ currentSpan = currentSpan . Slice ( charsUsed ) ;
181+ m_output = m_output . Slice ( bytesUsed ) ;
182+ if ( ! completed )
183+ Reallocate ( ) ;
184+ Debug . Assert ( completed == ( currentSpan . Length == 0 ) ) ;
185+ }
186+ }
187+
188+ // flush the output
189+ if ( m_output . Length < 4 )
190+ Reallocate ( ) ;
191+ m_encoder . Convert ( "" . AsSpan ( ) , m_output . Span , true , out _ , out var finalBytesUsed , out _ ) ;
192+ m_output = m_output . Slice ( finalBytesUsed ) ;
193+
194+ // write the length (as a 64-bit integer) in the reserved space
195+ var textLength = Position - ( lengthPosition + 9 ) ;
196+ m_buffer [ lengthPosition ] = 0xFE ;
197+ BinaryPrimitives . WriteUInt64LittleEndian ( m_buffer . AsSpan ( lengthPosition + 1 ) , ( ulong ) textLength ) ;
198+ #else
199+ this . WriteLengthEncodedString ( stringBuilder . ToString ( ) ) ;
200+ #endif
201+ }
202+
153203 public void WriteString ( short value )
154204 {
155205 int bytesWritten ;
@@ -255,7 +305,7 @@ public static void WriteLengthEncodedString(this ByteBufferWriter writer, ReadOn
255305 {
256306 var byteCount = Encoding . UTF8 . GetByteCount ( value ) ;
257307 writer . WriteLengthEncodedInteger ( ( ulong ) byteCount ) ;
258- writer . Write ( value ) ;
308+ writer . Write ( value , flush : true ) ;
259309 }
260310#endif
261311
0 commit comments