Skip to content

Commit e4d4717

Browse files
nordlow9il
andauthored
Complete use of isSomeChar and isOutputRange in template restrictions in mir.format (#361)
Co-authored-by: Ilya Yaroshenko <ilyayaroshenko@gmail.com>
1 parent 9a6abda commit e4d4717

File tree

1 file changed

+23
-14
lines changed

1 file changed

+23
-14
lines changed

source/mir/format.d

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Authors: Ilya Yaroshenko
77
module mir.format;
88

99
import std.traits;
10+
import mir.primitives: isOutputRange;
1011

1112
/// `mir.conv: to` extension.
1213
version(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
+/
339342
ref 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
407411
version (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
418421
Decodes `char` `c` to the form `u00XX`, where `XX` is 2 hexadecimal characters.
419422
+/
420423
ref 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)
434438
Decodes `char` `c` to the form `u00XX`, where `XX` is 2 hexadecimal characters.
435439
+/
436440
ref 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)
452457
Decodes ushort `c` to the form `uXXXX`, where `XXXX` is 2 hexadecimal characters.
453458
+/
454459
ref 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
///
472478
ref 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
///
483489
ref 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)
490496
Multiargument overload.
491497
+/
492498
ref 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
503509
ref 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
540546
ref 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
568575
pragma(inline, false)
569576
ref 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
602610
pragma(inline, false)
603611
ref 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'`.
633641
pragma(inline, false)
634642
ref 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
689698
ref 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
697706
ref 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
717726
ref 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
809818
pragma(inline, false)
810819
ref 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
872881
pragma(inline, false)
873882
ref 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
895904
pragma(inline, false)
896905
ref 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
///
962971
ref 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
///
10101019
ref 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

Comments
 (0)