Skip to content

Commit abd1312

Browse files
committed
std.fmt: check result types in parseInt functions
Produces compiler errors on failed checks advising of the cause Also documents `parseIntWithSign` with reference to `parseInt`
1 parent 9ef4bdf commit abd1312

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

lib/std/fmt.zig

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,17 +1514,27 @@ pub fn Formatter(comptime formatFn: anytype) type {
15141514
///
15151515
/// Ignores '_' character in `buf`.
15161516
/// See also `parseUnsigned`.
1517+
///
1518+
/// Asserts 'T' is an integer type
15171519
pub fn parseInt(comptime T: type, buf: []const u8, base: u8) ParseIntError!T {
1520+
if (@typeInfo(T) != .int) {
1521+
@compileError("Cannot parse an integer into a non-integer type");
1522+
}
15181523
return parseIntWithGenericCharacter(T, u8, buf, base);
15191524
}
15201525

15211526
/// Like `parseInt`, but with a generic `Character` type.
1527+
///
1528+
/// Asserts that 'Result' is an integer type
15221529
pub fn parseIntWithGenericCharacter(
15231530
comptime Result: type,
15241531
comptime Character: type,
15251532
buf: []const Character,
15261533
base: u8,
15271534
) ParseIntError!Result {
1535+
if (@typeInfo(Result) != .int) {
1536+
@compileError("Cannot parse an integer into a non-integer type");
1537+
}
15281538
if (buf.len == 0) return error.InvalidCharacter;
15291539
if (buf[0] == '+') return parseIntWithSign(Result, Character, buf[1..], base, .pos);
15301540
if (buf[0] == '-') return parseIntWithSign(Result, Character, buf[1..], base, .neg);
@@ -1591,13 +1601,30 @@ test parseInt {
15911601
try std.testing.expectEqual(@as(i5, -16), try std.fmt.parseInt(i5, "-10", 16));
15921602
}
15931603

1604+
/// Parses an integer with a specified `sign`, accepting a generic `Character`
1605+
/// type for width and a buffer of `Character`s, in the specified `base` of an
1606+
/// integral type of value `Result`
1607+
///
1608+
/// When `base` is zero the string prefix is examined to detect the true base:
1609+
/// * A prefix of "0b" implies base=2,
1610+
/// * A prefix of "0o" implies base=8,
1611+
/// * A prefix of "0x" implies base=16,
1612+
/// * Otherwise base=10 is assumed.
1613+
///
1614+
/// Ignores '_' character in `buf`.
1615+
///
1616+
/// Asserts that `Result` is an integer type
15941617
fn parseIntWithSign(
15951618
comptime Result: type,
15961619
comptime Character: type,
15971620
buf: []const Character,
15981621
base: u8,
15991622
comptime sign: enum { pos, neg },
16001623
) ParseIntError!Result {
1624+
if (@typeInfo(Result) != .int) {
1625+
@compileError("Cannot parse an integer into a non-integer type");
1626+
}
1627+
16011628
if (buf.len == 0) return error.InvalidCharacter;
16021629

16031630
var buf_base = base;
@@ -1670,7 +1697,12 @@ fn parseIntWithSign(
16701697
///
16711698
/// Ignores '_' character in `buf`.
16721699
/// See also `parseInt`.
1700+
///
1701+
/// Asserts 'T' is an integer type
16731702
pub fn parseUnsigned(comptime T: type, buf: []const u8, base: u8) ParseIntError!T {
1703+
if (@typeInfo(T) != .int) {
1704+
@compileError("Cannot parse an integer into a non-integer type");
1705+
}
16741706
return parseIntWithSign(T, u8, buf, base, .pos);
16751707
}
16761708

0 commit comments

Comments
 (0)