diff --git a/std/format/spec.d b/std/format/spec.d index 74243becf..b828bb65b 100644 --- a/std/format/spec.d +++ b/std/format/spec.d @@ -127,14 +127,16 @@ if (is(Unqual!Char == Char)) Counting starts with `1`. Set to `0` if not used. Default: `0`. */ - ubyte indexStart; + ushort indexStart; /** Index of the last argument for positional parameter ranges. Counting starts with `1`. Set to `0` if not used. Default: `0`. + + The maximum value of this field is used as a sentinel to indicate the arguments' length. */ - ubyte indexEnd; + ushort indexEnd; version (StdDdoc) { @@ -851,6 +853,18 @@ if (is(Unqual!Char == Char)) assert(f.indexStart == 0); } +// https://github.com/dlang/phobos/issues/10699 +@safe pure unittest +{ + import std.array : appender; + auto f = FormatSpec!char("%1:$d"); + auto w = appender!(char[])(); + + f.writeUpToNextSpec(w); + assert(f.indexStart == 1); + assert(f.indexEnd == ushort.max); +} + /** Helper function that returns a `FormatSpec` for a single format specifier. diff --git a/std/format/write.d b/std/format/write.d index 078fa786e..d704c14f5 100644 --- a/std/format/write.d +++ b/std/format/write.d @@ -648,9 +648,16 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[] break SWITCH; } default: - throw new FormatException( - text("Positional specifier %", spec.indexStart, '$', spec.spec, - " index exceeds ", Args.length)); + if (spec.indexEnd == spec.indexEnd.max) + break; + else if (spec.indexEnd == spec.indexStart) + throw new FormatException( + text("Positional specifier %", spec.indexStart, '$', spec.spec, + " index exceeds ", Args.length)); + else + throw new FormatException( + text("Positional specifier %", spec.indexStart, ":", spec.indexEnd, '$', spec.spec, + " index exceeds ", Args.length)); } } return currentArg; @@ -1199,6 +1206,16 @@ if (isSomeString!(typeof(fmt))) formattedWrite(stream, "%s", aa); } +// https://github.com/dlang/phobos/issues/10699 +@safe pure unittest +{ + import std.array : appender; + auto w = appender!(char[])(); + + formattedWrite(w, "%1:$d", 1, 2, 3); + assert(w.data == "123"); +} + /** Formats a value of any type according to a format specifier and writes the result to an output range.