@@ -7,6 +7,7 @@ Authors: Ilya Yaroshenko
77module mir.format ;
88
99import std.traits ;
10+ import mir.primitives: isOutputRange;
1011
1112// / `mir.conv: to` extension.
1213version (mir_test)
@@ -276,6 +277,7 @@ struct FormattedFloating(T)
276277
277278 // /
278279 void toString (C = char , W)(scope ref W w) scope const
280+ if (isSomeChar! C && isOutputRange! (W, C))
279281 {
280282 C[512 ] buf = void ;
281283 auto n = printFloatingPoint(value, spec, buf);
@@ -302,6 +304,7 @@ struct HexAddress(T)
302304
303305 // /
304306 void toString (C = char , W)(scope ref W w) scope const
307+ if (isSomeChar! C && isOutputRange! (W, C))
305308 {
306309 enum N = T.sizeof * 2 ;
307310 static if (isFastBuffer! W)
@@ -337,6 +340,7 @@ enum escapeFormatQuote(EscapeFormat escapeFormat) = escapeFormat == EscapeFormat
337340/+ +
338341+/
339342ref W printEscaped (C, EscapeFormat escapeFormat = EscapeFormat.ion, W)(scope return ref W w, scope const (C)[] str)
343+ if (isOutputRange! (W, C))
340344{
341345 import mir.utility: _expect;
342346 foreach (C c; str)
@@ -406,7 +410,6 @@ ref W printEscaped(C, EscapeFormat escapeFormat = EscapeFormat.ion, W)(scope ret
406410@safe pure nothrow @nogc
407411version (mir_test) unittest
408412{
409-
410413 import mir.format: stringBuf;
411414 stringBuf w;
412415 assert (w.printEscaped(" Hi \a\v\0\f\t\b \\\r\n " ~ ` "@nogc"` ).data == ` Hi \a\v\0\f\t\b \\\r\n\"@nogc\"` );
@@ -418,6 +421,7 @@ version (mir_test) unittest
418421Decodes `char` `c` to the form `u00XX`, where `XX` is 2 hexadecimal characters.
419422+/
420423ref W put_xXX (C = char , W)(scope return ref W w, char c)
424+ if (isSomeChar! C && isOutputRange! (W, C))
421425{
422426 ubyte [2 ] spl;
423427 spl[0 ] = c >> 4 ;
@@ -434,6 +438,7 @@ ref W put_xXX(C = char, W)(scope return ref W w, char c)
434438Decodes `char` `c` to the form `u00XX`, where `XX` is 2 hexadecimal characters.
435439+/
436440ref W put_uXXXX (C = char , W)(scope return ref W w, char c)
441+ if (isSomeChar! C && isOutputRange! (W, C))
437442{
438443 ubyte [2 ] spl;
439444 spl[0 ] = c >> 4 ;
@@ -452,6 +457,7 @@ ref W put_uXXXX(C = char, W)(scope return ref W w, char c)
452457Decodes ushort `c` to the form `uXXXX`, where `XXXX` is 2 hexadecimal characters.
453458+/
454459ref W put_uXXXX (C = char , W)(scope return ref W w, ushort c)
460+ if (isSomeChar! C && isOutputRange! (W, C))
455461{
456462 ubyte [4 ] spl;
457463 spl[0 ] = (c >> 12 ) & 0xF ;
@@ -470,7 +476,7 @@ ref W put_uXXXX(C = char, W)(scope return ref W w, ushort c)
470476
471477// /
472478ref W printElement (C, EscapeFormat escapeFormat = EscapeFormat.ion, W)(scope return ref W w, scope const (C)[] c)
473- if (isSomeChar! C)
479+ if (isSomeChar! C && isOutputRange ! (W, C) )
474480{
475481 static immutable C[1 ] quote = ' \" ' ;
476482 return w
@@ -481,7 +487,7 @@ ref W printElement(C, EscapeFormat escapeFormat = EscapeFormat.ion, W)(scope ret
481487
482488// /
483489ref W printElement (C = char , EscapeFormat escapeFormat = EscapeFormat.ion, W, T)(scope return ref W w, scope auto ref const T c)
484- if (! isSomeString! T)
490+ if (! isSomeString! T && isOutputRange ! (W, C) )
485491{
486492 return w.print! C(c);
487493}
@@ -490,7 +496,7 @@ ref W printElement(C = char, EscapeFormat escapeFormat = EscapeFormat.ion, W, T)
490496Multiargument overload.
491497+/
492498ref W print (C = char , W, Args... )(scope return ref W w, scope auto ref const Args args)
493- if (Args.length > 1 )
499+ if (isSomeChar ! C && isOutputRange ! (W, C) && Args.length > 1 )
494500{
495501 foreach (i, ref c; args)
496502 static if (i < Args.length - 1 )
@@ -501,7 +507,7 @@ ref W print(C = char, W, Args...)(scope return ref W w, scope auto ref const Arg
501507
502508// / Prints enums
503509ref W print (C = char , W, T)(scope return ref W w, const T c)
504- if (is (T == enum ))
510+ if (isSomeChar ! C && isOutputRange ! (W, C) && is (T == enum ))
505511{
506512 import mir.enums: getEnumIndex, enumStrings;
507513 import mir.utility: _expect;
@@ -538,6 +544,7 @@ version (mir_test) unittest
538544
539545// / Prints boolean
540546ref W print (C = char , W)(scope return ref W w, bool c)
547+ if (isSomeChar! C && isOutputRange! (W, C))
541548{
542549 enum N = 5 ;
543550 static if (isFastBuffer! W)
@@ -567,6 +574,7 @@ version (mir_test) unittest
567574// / Prints associative array
568575pragma (inline, false )
569576ref W print (C = char , W, V, K)(scope return ref W w, scope const V[K] c)
577+ if (isSomeChar! C && isOutputRange! (W, C))
570578{
571579 enum C left = ' [' ;
572580 enum C right = ' ]' ;
@@ -601,7 +609,7 @@ version (mir_test) unittest
601609// / Prints array
602610pragma (inline, false )
603611ref W print (C = char , W, T)(scope return ref W w, scope const (T)[] c)
604- if (! isSomeChar! T)
612+ if (isSomeChar ! C && isOutputRange ! (W, C) && ! isSomeChar! T)
605613{
606614 enum C left = ' [' ;
607615 enum C right = ' ]' ;
@@ -632,6 +640,7 @@ version (mir_test) unittest
632640// / Prints escaped character in the form `'c'`.
633641pragma (inline, false )
634642ref W print (C = char , W)(scope return ref W w, char c)
643+ if (isSomeChar! C && isOutputRange! (W, C))
635644{
636645 w.put(' \' ' );
637646 if (c >= 0x20 )
@@ -687,15 +696,15 @@ version (mir_test) unittest
687696
688697// / Prints some string
689698ref W print (C = char , W)(scope return ref W w, scope const (C)[] c)
690- if (isSomeChar! C)
699+ if (isSomeChar! C && isOutputRange ! (W, C) )
691700{
692701 w.put(c);
693702 return w;
694703}
695704
696705// / Prints integers
697706ref W print (C = char , W, I)(scope return ref W w, const I c)
698- if (isIntegral! I && ! is (I == enum ))
707+ if (isSomeChar ! C && isOutputRange ! (W, C) && isIntegral! I && ! is (I == enum ))
699708{
700709 static if (I.sizeof == 16 )
701710 enum N = 39 ;
@@ -715,7 +724,7 @@ ref W print(C = char, W, I)(scope return ref W w, const I c)
715724
716725// / Prints floating point numbers
717726ref W print (C = char , W, T)(scope return ref W w, const T c, NumericSpec spec = NumericSpec.init)
718- if (is (T == float ) || is (T == double ) || is (T == real ))
727+ if (isSomeChar ! C && isOutputRange ! (W, C) && is (T == float ) || is (T == double ) || is (T == real ))
719728{
720729 import mir.bignum.decimal;
721730 auto decimal = Decimal! (T.mant_dig < 64 ? 1 : 2 )(c);
@@ -808,7 +817,7 @@ unittest
808817// / Prints structs and unions
809818pragma (inline, false )
810819ref W print (C = char , W, T)(scope return ref W w, ref const T c)
811- if (is (T == struct ) || is (T == union ) && ! is (T : NumericSpec))
820+ if (isSomeChar ! C && isOutputRange ! (W, C) && is (T == struct ) || is (T == union ) && ! is (T : NumericSpec))
812821{
813822 static if (__traits(hasMember, T, " toString" ))
814823 {
@@ -871,7 +880,7 @@ ref W print(C = char, W, T)(scope return ref W w, ref const T c)
871880// FUTURE: remove it
872881pragma (inline, false )
873882ref W print (C = char , W, T)(scope return ref W w, scope const T c)
874- if (is (T == struct ) || is (T == union ))
883+ if (isSomeChar ! C && isOutputRange ! (W, C) && is (T == struct ) || is (T == union ))
875884{
876885 return print! (C, W, T)(w, c);
877886}
@@ -894,7 +903,7 @@ version (mir_test) unittest
894903// / Prints classes and interfaces
895904pragma (inline, false )
896905ref W print (C = char , W, T)(scope return ref W w, scope const T c)
897- if (is (T == class ) || is (T == interface ))
906+ if (isSomeChar ! C && isOutputRange ! (W, C) && is (T == class ) || is (T == interface ))
898907{
899908 enum C[4 ] Null = " null" ;
900909 static if (__traits(hasMember, T, " toString" ) || __traits(compiles, { scope const (C)[] string_of_c = c; }))
@@ -960,7 +969,7 @@ version (mir_test) unittest
960969
961970// /
962971ref W printStaticString (C, size_t N, W)(scope return ref W w, ref scope const C[N] c)
963- if (is (C == char ) || is (C == wchar ) || is (C == dchar ))
972+ if (isSomeChar ! C && isOutputRange ! (W, C) && is (C == char ) || is (C == wchar ) || is (C == dchar ))
964973{
965974 static if (isFastBuffer! W)
966975 {
@@ -1008,7 +1017,7 @@ template isFastBuffer(W)
10081017
10091018// /
10101019ref W printZeroPad (C = char , W, I)(scope return ref W w, const I c, size_t minimalLength)
1011- if (isIntegral! I && ! is (I == enum ))
1020+ if (isSomeChar ! C && isOutputRange ! (W, C) && isIntegral! I && ! is (I == enum ))
10121021{
10131022 static if (I.sizeof == 16 )
10141023 enum N = 39 ;
0 commit comments