Skip to content

Commit

Permalink
Merge pull request #204 from Alexhuszagh/docsrs
Browse files Browse the repository at this point in the history
Overhaul our documentation.
  • Loading branch information
Alexhuszagh authored Jan 9, 2025
2 parents c6c5052 + a95a78f commit 42babea
Show file tree
Hide file tree
Showing 85 changed files with 12,488 additions and 4,533 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/Docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Docs

on:
[workflow_dispatch]

jobs:
docs:
name: Test Docs Combinations
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install latest nightly
uses: dtolnay/rust-toolchain@nightly
- run: cargo --version
- run: python --version
- run: cargo check
- run: cargo build
- run: RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --no-default-features
- run: RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --no-default-features --features=format
- run: RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --no-default-features --features=radix
- run: RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --no-default-features --features=format,radix
- run: RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --no-default-features --features=write-integers,write-floats
- run: RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --no-default-features --features=parse-integers,parse-floats
- run: RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --no-default-features --all-features
# validate all the generated docs.rs docs
- run: RUSTDOCFLAGS="-D warnings --cfg docsrs" cargo doc --features=format,radix
- run: python scripts/docs.py
15 changes: 14 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Additional trait impls for `f16` and `bf16` to better match Rust's interface.
- Added `Options::buffer_size_const` for integer and float writers.
- Added `build_checked` and `build_unchecked` to our `NumberFormatBuilder` API.
- Added `build_checked` to our `Options` API.
- Added `has_digit_separator` to `NumberFormat`.
- Re-export `NumberFormat` to our other crates.

### Changed

- Lowered the MSRV from 1.63.0 to 1.61.0 and adds support for most testing on 1.61.0.
- Lowered the MSRV from 1.63.0 to 1.61.0 and adds support for most testing on 1.60.0.
- Reduced the required buffer size for integer and float writers when using `buffer_size` and `buffer_size_const` for decimal numbers.
- Deprecated `NumberFormatBuilder::build` due to a lack of validation.
- Deprecated `Options::set_*` in our write float API since options should be considered immutable.
- Removed `static_assertions` dependency.

### Fixed

- Bug where the `radix` feature wasn't enabling `power-of-two` in `lexical-core` or `lexical`.

## [1.0.5] 2024-12-08

Expand Down
59 changes: 33 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ where
let value: T = lexical_core::parse(value.as_bytes())?;
let mut buffer = [b'0'; lexical_core::BUFFER_SIZE];
let bytes = lexical_core::write(value * multiplier, &mut buffer);
Ok(std::str::from_utf8(bytes).unwrap())
Ok(String::from_utf8(bytes).unwrap())
}
```

Expand All @@ -93,7 +93,9 @@ let (x, count): (i32, usize) = lexical_core::parse_partial(b"123 456")?;

## no_std

`lexical-core` does not depend on a standard library, nor a system allocator. To use `lexical-core` in a `no_std` environment, add the following to `Cargo.toml`:
`lexical-core` does not depend on a standard library, nor a system allocator. To use `lexical-core` in a [`no_std`] environment, add the following to `Cargo.toml`:

[`no_std`]: <https://docs.rust-embedded.org/book/intro/no-std.html>

```toml
[dependencies.lexical-core]
Expand All @@ -103,7 +105,7 @@ default-features = false
features = ["write-integers", "write-floats", "parse-integers", "parse-floats"]
```

And get started using lexical:
And get started using `lexical-core`:

```rust
// A constant for the maximum number of bytes a formatter will write.
Expand Down Expand Up @@ -136,9 +138,9 @@ Lexical is highly customizable, and contains numerous other optional features:

- **std**: &ensp; Enable use of the Rust standard library (enabled by default).
- **power-of-two**: &ensp; Enable conversions to and from non-decimal strings.
<blockquote>With power_of_two enabled, the radixes <code>{2, 4, 8, 10, 16, and 32}</code> are valid, otherwise, only 10 is valid. This enables common conversions to/from hexadecimal integers/floats, without requiring large pre-computed tables for other radixes.</blockquote>
<blockquote>With power_of_two enabled, the radixes <code>{2, 4, 8, 10, 16, and 32}</code> are valid, otherwise, only <code>10</code> is valid. This enables common conversions to/from hexadecimal integers/floats, without requiring large pre-computed tables for other radixes.</blockquote>
- **radix**: &ensp; Allow conversions to and from non-decimal strings.
<blockquote>With radix enabled, any radix from 2 to 36 (inclusive) is valid, otherwise, only 10 is valid.</blockquote>
<blockquote>With radix enabled, any radix from <code>2</code> to <code>36</code> (inclusive) is valid, otherwise, only <code>10</code> is valid.</blockquote>
- **format**: &ensp; Customize acceptable number formats for number parsing and writing.
<blockquote>With format enabled, the number format is dictated through bitflags and masks packed into a <code>u128</code>. These dictate the valid syntax of parsed and written numbers, including enabling digit separators, requiring integer or fraction digits, and toggling case-sensitive exponent characters.</blockquote>
- **compact**: &ensp; Optimize for binary size at the expense of performance.
Expand All @@ -154,7 +156,7 @@ Lexical also places a heavy focus on code bloat: with algorithms both optimized

Lexical is extensively customizable to support parsing numbers from a wide variety of programming languages, such as `1_2_3`. However, lexical takes the concept of "you don't pay for what you don't use" seriously: enabling the `format` feature does not affect the performance of parsing regular numbers: only those with digit separators.

> **WARNING:** When changing the number of significant digits written, disabling the use of exponent notation, or changing exponent notation thresholds, `BUFFER_SIZE` may be insufficient to hold the resulting output. `WriteOptions::buffer_size` will provide a correct upper bound on the number of bytes written. If a buffer of insufficient length is provided, lexical-core will panic.
> **WARNING:** When changing the number of significant digits written, disabling the use of exponent notation, or changing exponent notation thresholds, `BUFFER_SIZE` may be insufficient to hold the resulting output. `WriteOptions::buffer_size_const` will provide a correct upper bound on the number of bytes written. If a buffer of insufficient length is provided, `lexical-core` will panic.
Every language has competing specifications for valid numerical input, meaning a number parser for Rust will incorrectly accept or reject input for different programming or data languages. For example:

Expand All @@ -165,9 +167,9 @@ let f: f64 = lexical_core::parse(b"3.e7")?; // 3e7

// Let's only accept JSON floats.
const JSON: u128 = lexical_core::format::JSON;
let options = ParseFloatOptions::new();
let f: f64 = lexical_core::parse_with_options::<JSON>(b"3.0e7", &options)?; // 3e7
let f: f64 = lexical_core::parse_with_options::<JSON>(b"3.e7", &options)?; // Errors!
const OPTIONS: ParseFloatOptions = ParseFloatOptions::new();
let f: f64 = lexical_core::parse_with_options::<_, JSON>(b"3.0e7", &OPTIONS)?; // 3e7
let f: f64 = lexical_core::parse_with_options::<_, JSON>(b"3.e7", &OPTIONS)?; // Errors!
```

Due the high variability in the syntax of numbers in different programming and data languages, we provide 2 different APIs to simplify converting numbers with different syntax requirements.
Expand Down Expand Up @@ -196,24 +198,30 @@ When the `format` feature is enabled, numerous other syntax and digit separator

Many pre-defined constants therefore exist to simplify common use-cases,
including:

- JSON, XML, TOML, YAML, SQLite, and many more.
- Rust, Python, C#, FORTRAN, COBOL literals and strings, and many more.
- [`JSON`], [`XML`], [`TOML`], [`YAML`], [`SQLite`], and many more.
- [`Rust`], [`Python`], [`C#`], [`FORTRAN`], [`COBOL`] literals and strings, and many more.

[`JSON`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.JSON.html
[`XML`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.XML.html
[`TOML`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.TOML.html
[`YAML`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.YAML.html
[`SQLite`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.SQLITE.html
[`Rust`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.RUST_LITERAL.html
[`Python`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.PYTHON_LITERAL.html
[`C#`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.CSHARP_LITERAL.html
[`FORTRAN`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.FORTRAN_LITERAL.html
[`COBOL`]: https://docs.rs/lexical-core/latest/lexical_core/format/constant.COBOL_LITERAL.html

An example of building a custom number format is as follows:

```rust
// this will panic if the format is invalid
const FORMAT: u128 = lexical_core::NumberFormatBuilder::new()
// Disable exponent notation.
.no_exponent_notation(true)
// Disable all special numbers, such as Nan and Inf.
.no_special(true)
.build();

// Due to use in a `const fn`, we can't panic or expect users to unwrap invalid
// formats, so it's up to the caller to verify the format. If an invalid format
// is provided to a parser or writer, the function will error or panic, respectively.
debug_assert!(lexical_core::format_is_valid::<FORMAT>());
.build_strict();
```

### Options API
Expand All @@ -225,7 +233,7 @@ An example of building a custom options struct is as follows:
```rust
use std::num;

let options = lexical_core::WriteFloatOptions::builder()
const OPTIONS: lexical_core::WriteFloatOptions = lexical_core::WriteFloatOptions::builder()
// Only write up to 5 significant digits, IE, `1.23456` becomes `1.2345`.
.max_significant_digits(num::NonZeroUsize::new(5))
// Never write less than 5 significant digits, `1.1` becomes `1.1000`.
Expand All @@ -238,8 +246,7 @@ let options = lexical_core::WriteFloatOptions::builder()
.nan_string(None)
// Write infinity as "Infinity".
.inf_string(Some(b"Infinity"))
.build()
.unwrap();
.build_strict();
```

## Documentation
Expand Down Expand Up @@ -380,17 +387,17 @@ lexical-core should also work on a wide variety of other architectures and ISAs.
The currently supported versions are:
- v1.0.x

Due to security considerations, all other versions are not supported and security advisories exist for them..
Due to security considerations, all other versions are not supported and security advisories exist for them.

**Rustc Compatibility**

- v1.0.x supports 1.63+, including stable, beta, and nightly.

Please report any errors compiling a supported lexical-core version on a compatible Rustc version.
Please report any errors compiling a supported `lexical` version on a compatible Rustc version.

**Versioning**

lexical uses [semantic versioning](https://semver.org/). Removing support for Rustc versions newer than the latest stable Debian or Ubuntu version is considered an incompatible API change, requiring a major version change.
`lexical` uses [semantic versioning](https://semver.org/). Removing support for Rustc versions newer than the latest stable Debian or Ubuntu version is considered an incompatible API change, requiring a major version change.

## Changelog

Expand All @@ -402,6 +409,6 @@ Lexical is dual licensed under the Apache 2.0 license as well as the MIT license

## Contributing

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in lexical by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. Contributing to the repository means abiding by the [code of conduct](https://github.com/Alexhuszagh/rust-lexical/blob/main/CODE_OF_CONDUCT.md).
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in `lexical` by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. Contributing to the repository means abiding by the [code of conduct](https://github.com/Alexhuszagh/rust-lexical/blob/main/CODE_OF_CONDUCT.md).

For the process on how to contribute to lexical, see the [development](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/Development.md) quick-start guide.
For the process on how to contribute to `lexical`, see the [development](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/Development.md) quick-start guide.
4 changes: 2 additions & 2 deletions extras/parse-integer/tests/api_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ proptest! {
#[test]
#[cfg(feature = "power-of-two")]
fn i32_binary_roundtrip_display_proptest(i in i32::MIN..i32::MAX) {
let options = Options::new();
const OPTIONS: Options = Options::new();
const FORMAT: u128 = from_radix(2);
let digits = if i < 0 {
format!("-{:b}", (i as i64).wrapping_neg())
} else {
format!("{:b}", i)
};
let result = i32::from_lexical_with_options::<FORMAT>(digits.as_bytes(), &options);
let result = i32::from_lexical_with_options::<FORMAT>(digits.as_bytes(), &OPTIONS);
prop_assert_eq!(i, result.unwrap());
}

Expand Down
16 changes: 8 additions & 8 deletions extras/write-float/tests/algorithm_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ const DECIMAL: u128 = NumberFormatBuilder::decimal();
default_quickcheck! {
fn f32_quickcheck(f: f32) -> bool {
let mut buffer = [b'\x00'; BUFFER_SIZE];
let options = Options::builder().build().unwrap();
const OPTIONS: Options = Options::builder().build_strict();
let f = f.abs();
if f.is_special() {
true
} else {
let count = algorithm::write_float::<_, DECIMAL>(f, &mut buffer, &options);
let count = algorithm::write_float::<_, DECIMAL>(f, &mut buffer, &OPTIONS);
let actual = unsafe { std::str::from_utf8_unchecked(&buffer[..count]) };
let roundtrip = actual.parse::<f32>();
roundtrip == Ok(f)
Expand All @@ -29,12 +29,12 @@ default_quickcheck! {

fn f64_quickcheck(f: f64) -> bool {
let mut buffer = [b'\x00'; BUFFER_SIZE];
let options = Options::builder().build().unwrap();
const OPTIONS: Options = Options::builder().build_strict();
let f = f.abs();
if f.is_special() {
true
} else {
let count = algorithm::write_float::<_, DECIMAL>(f, &mut buffer, &options);
let count = algorithm::write_float::<_, DECIMAL>(f, &mut buffer, &OPTIONS);
let actual = unsafe { std::str::from_utf8_unchecked(&buffer[..count]) };
let roundtrip = actual.parse::<f64>();
roundtrip == Ok(f)
Expand All @@ -48,10 +48,10 @@ proptest! {
#[test]
fn f32_proptest(f in f32::MIN..f32::MAX) {
let mut buffer = [b'\x00'; BUFFER_SIZE];
let options = Options::builder().build().unwrap();
const OPTIONS: Options = Options::builder().build_strict();
let f = f.abs();
if !f.is_special() {
let count = algorithm::write_float::<_, DECIMAL>(f, &mut buffer, &options);
let count = algorithm::write_float::<_, DECIMAL>(f, &mut buffer, &OPTIONS);
let actual = unsafe { std::str::from_utf8_unchecked(&buffer[..count]) };
let roundtrip = actual.parse::<f32>();
prop_assert_eq!(roundtrip, Ok(f))
Expand All @@ -61,10 +61,10 @@ proptest! {
#[test]
fn f64_proptest(f in f64::MIN..f64::MAX) {
let mut buffer = [b'\x00'; BUFFER_SIZE];
let options = Options::builder().build().unwrap();
const OPTIONS: Options = Options::builder().build_strict();
let f = f.abs();
if !f.is_special() {
let count = algorithm::write_float::<_, DECIMAL>(f, &mut buffer, &options);
let count = algorithm::write_float::<_, DECIMAL>(f, &mut buffer, &OPTIONS);
let actual = unsafe { std::str::from_utf8_unchecked(&buffer[..count]) };
let roundtrip = actual.parse::<f64>();
prop_assert_eq!(roundtrip, Ok(f))
Expand Down
Loading

0 comments on commit 42babea

Please sign in to comment.