Skip to content

[BUG] Using parse_partial_with_options for some formats returns length of 0 when successfully parsing integer '0' #225

@JakeDern

Description

@JakeDern

Description

parse_partial_with_options returns a length of 0 rather than 1 when parsing the integer '0' when using some of the pre-baked formats like JSON or TOML. This doesn't happen when using other formats like XML.

The difference seems like it might be related to this option which is set on JSON/TOML but not on XML:

    .no_integer_leading_zeros(true)

When I use a custom format without that option it seems to fix it.

Prerequisites

Here are a few things you should provide to help me understand the issue:

  • Rust version: rustc 1.85.0 (4d91de4e4 2025-02-17)
  • lexical version: 7.0.4
  • lexical compilation features used: ["parse-integers", "parse-floats", "format"]

Test case

Please provide a short, complete (with crate import, etc) test case for
the issue, showing clearly the expected and obtained results.

Example test case:

use lexical::{NumberFormatBuilder, format, parse_partial, parse_partial_with_options};

// Pass
#[test]
fn test_lexical() {
    let input = vec![b'0'];
    let (num, len) = parse_partial::<u64, _>(input).unwrap();
    assert_eq!(num, 0);
    assert_eq!(len, 1);
}

// Fail
#[test]
fn test_lexical_json() {
    let input = vec![b'0'];
    let opts = lexical::ParseIntegerOptions::new();
    let (num, len) = parse_partial_with_options::<u64, _, { format::JSON }>(input, &opts).unwrap();
    assert_eq!(num, 0);
    assert_eq!(len, 1);
}

// Pass
#[test]
fn test_lexical_xml() {
    let input = vec![b'0'];
    let opts = lexical::ParseIntegerOptions::new();
    let (num, len) = parse_partial_with_options::<u64, _, { format::XML }>(input, &opts).unwrap();
    assert_eq!(num, 0);
    assert_eq!(len, 1);
}

// Fail
#[test]
fn test_lexical_toml() {
    let input = vec![b'0'];
    let opts = lexical::ParseIntegerOptions::new();
    let (num, len) = parse_partial_with_options::<u64, _, { format::TOML }>(input, &opts).unwrap();
    assert_eq!(num, 0);
    assert_eq!(len, 1);
}

// Pass
#[test]
fn test_lexical_json_two_digits() {
    let input = vec![b'1', b'0'];
    let opts = lexical::ParseIntegerOptions::new();
    let (num, len) = parse_partial_with_options::<u64, _, { format::JSON }>(input, &opts).unwrap();
    assert_eq!(num, 10);
    assert_eq!(len, 2);
}

const JSON_LEADING_0: u128 = NumberFormatBuilder::new()
    .required_digits(true)
    .no_positive_mantissa_sign(true)
    .no_special(true)
    // .no_integer_leading_zeros(true)
    .no_float_leading_zeros(true)
    .build();

// Pass
#[test]
fn test_lexical_json_leading_zeros() {
    let input = vec![b'0'];
    let opts = lexical::ParseIntegerOptions::new();
    let (num, len) =
        parse_partial_with_options::<u64, _, { JSON_LEADING_0 }>(input, &opts).unwrap();
    assert_eq!(num, 0);
    assert_eq!(len, 1);
}

Additional Context

Add any other context about the problem here.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions