11using System ;
2+ using System . Buffers ;
23using System . Collections . Generic ;
34using System . IO ;
45using System . Linq ;
78using Newtonsoft . Json ;
89using Newtonsoft . Json . Linq ;
910
10- using Wiry . Base32 ;
11-
1211using Xunit ;
1312using Xunit . Sdk ;
1413
1514namespace StructuredFieldValues . Tests ;
1615
1716public class Rfc8941ParserTests
1817{
18+ private const string Base32StdEncodeMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" ;
1919 private static readonly DateTime Epoch = new DateTime ( 1970 , 1 , 1 , 0 , 0 , 0 , DateTimeKind . Utc ) ;
2020
2121 [ Theory ]
@@ -493,7 +493,7 @@ internal void WhatWgTestsPass(WhatWgTestCase testCase)
493493 {
494494 Token token => new JObject { [ "__type" ] = "token" , [ "value" ] = token . ToString ( ) } ,
495495 DisplayString token => new JObject { [ "__type" ] = "displaystring" , [ "value" ] = token . ToString ( ) } ,
496- ReadOnlyMemory < byte > binary => new JObject { [ "__type" ] = "binary" , [ "value" ] = Base32Encoding . Standard . GetString ( binary . ToArray ( ) ) } ,
496+ ReadOnlyMemory < byte > binary => new JObject { [ "__type" ] = "binary" , [ "value" ] = ToBase32StdString ( binary . Span ) } ,
497497 IReadOnlyList < ParsedItem > list => ConvertList ( list ) ,
498498 DateTime date => new JObject { [ "__type" ] = "date" , [ "value" ] = ( long ) Math . Ceiling ( ( date . ToUniversalTime ( ) - Epoch ) . TotalSeconds ) } ,
499499 object other => other ,
@@ -506,5 +506,45 @@ internal void WhatWgTestsPass(WhatWgTestCase testCase)
506506 static JArray ConvertList ( IReadOnlyList < ParsedItem > list ) => new ( list . Select ( i => ConvertItem ( i ) ) ) ;
507507
508508 static JArray ConvertDictionary ( IReadOnlyDictionary < string , ParsedItem > dictionary ) => new ( dictionary . Select ( p => new JArray ( p . Key , ConvertItem ( p . Value ) ) ) ) ;
509+
510+ static string ToBase32StdString ( ReadOnlySpan < byte > bytes )
511+ {
512+ if ( bytes . Length == 0 )
513+ {
514+ return "" ;
515+ }
516+
517+ var length = ( ( ( ( bytes . Length * 8 ) + 4 ) / 5 ) + 7 ) / 8 * 8 ;
518+ var bitBuffer = 0 ;
519+ var bitsInBuffer = 0 ;
520+ var outputIndex = 0 ;
521+ var pool = ArrayPool < char > . Shared ;
522+ var buffer = pool . Rent ( length ) ;
523+ foreach ( var b in bytes )
524+ {
525+ bitBuffer = ( bitBuffer << 8 ) | b ;
526+ bitsInBuffer += 8 ;
527+
528+ while ( bitsInBuffer >= 5 )
529+ {
530+ bitsInBuffer -= 5 ;
531+ buffer [ outputIndex ++ ] = Base32StdEncodeMap [ ( bitBuffer >> bitsInBuffer ) & 0x1F ] ;
532+ }
533+ }
534+
535+ if ( bitsInBuffer > 0 )
536+ {
537+ buffer [ outputIndex ++ ] = Base32StdEncodeMap [ ( bitBuffer << ( 5 - bitsInBuffer ) ) & 0x1F ] ;
538+ }
539+
540+ while ( outputIndex < length )
541+ {
542+ buffer [ outputIndex ++ ] = '=' ;
543+ }
544+
545+ var result = new string ( buffer , 0 , length ) ;
546+ pool . Return ( buffer ) ;
547+ return result ;
548+ }
509549 }
510550}
0 commit comments