size-convert 0.1.0

Conversions to and from Rust's machine-dependent integer types, usize and isize
Documentation
Conversions to and from Rust’s [machine-dependent integer types], `usize` and `isize`.

# Conventions and definitions used in this documentation

In this documentation, the letter `n` stands for *either* the letter `u` or the letter `i` in the
name of an integer type. For example, `n32` stands for either `u32` or `i32`, and `nsize` stands for
either `usize` or `isize`.

In this documentation, a “conversion” refers to an *infallible* and *lossless* conversion, unless
otherwise qualified.

# Background and motivation

The only concrete guarantee that Rust makes about `usize` and `isize` is that they are [at least 16
bits wide]. Thus, the only *portable* conversions involving these types are conversions from `n8` or
`n16` to `nsize`. The standard library provides `From` implementations *only* for these portable
conversions. Even if you are building for a 64-bit target, Rust will *not* provide `From<n64> for
nsize` or `From<nsize> for n64`!

In general, Rust’s policy of not providing conditional `From` implementations is reasonable. It
helps you avoid unintentionally writing non-portable code that relies on `From` implementations that
do not exist on all targets.

However, not everyone is interested in writing ultra-portable code that works on [*all* platforms
supported by the Rust compiler][platform support]. For example, you might make a deliberate decision
not to support 16-bit targets, and thus you would like to write code that can assume `nsize` is at
least 32 bits wide. In such a scenario, however, your options for performing conversions between
`nsize` and `n32` are not great:

1. Casting with the `as` operator. The `as` operator may perform many kinds of conversions,
   including silently lossy and dangerous ones.
2. Fallible conversions with the `TryFrom` trait. Such conversions yield a `Result` whose error case
   must be handled, even if they cannot actually fail on any targets that you intend to support.

The common flaw in both of these approaches is that they can be used to attempt *any* kind of
conversion. They are not restricted to working only with the kinds of conversions that should always
be infallible and lossless on the targets that you intend to support.

The `size-convert` crate provides Cargo features that let you declare explicitly which `nsize`
widths you intend to support, and provides appropriate infallible and lossless conversion functions
that correspond to the enabled features.

# Cargo features

This crate provides a set of Cargo features that express constraints on the [target’s pointer
width].

- **`at-least-B`**, where *B* is 32, 64, or 128, expresses the constraint that the target’s pointer
  width is at least *B*. These features enable functions for conversion from `nB` to `nsize`. Higher
  values of *B* imply lower values: for example, `at-least-64` implies `at-least-32`. Note that
  there is no `at-least-16` feature because `nsize` is guaranteed *always* at least 16 bits wide.
- **`at-most-B`** where *B* is 16, 32, 64, or 128, expresses the constraint that the target’s
  pointer width is at most *B*. These features enable functions for conversion from `nsize` to `nB`.
  Lower values of *B* imply higher values: for example, `at-most-32` implies `at-most-64`.
- **`exactly-B`** is shorthand for both `at-least-B` and `at-most-B`.

It is a compile-time error if the actual target pointer width does not satisfy the constraints
expressed by the enabled features.

No features are enabled by default. Without any features enabled, this crate only provides portable
conversion functions.

# Recommendations for use

Think about how portability figures into your software’s requirements. Portability is usually a good
thing, but may come at a cost in terms of code complexity or testing effort. If you decide (after
considering the trade-offs) that your software should not support certain kinds of targets, then you
should ensure that your code will not compile on those targets. This crate can help with that.

All features of this crate reduce portability to some extent, but a few of them only do so
minimally.

- The **`at-least-32`** feature excludes 16-bit targets. As of `rustc` version 1.93.1 (February
  2026), there is only one such target: `msp430-none-elf`, a microcontroller.
- The **`at-most-64`** feature would exclude 128-bit (or wider) targets. As of February 2026,
  `rustc` does not support any such targets, so this feature would only reduce portability to
  hypothetical future targets.

[machine-dependent integer types]:
    https://doc.rust-lang.org/stable/reference/types/numeric.html#machine-dependent-integer-types
[at least 16 bits wide]:
    https://doc.rust-lang.org/stable/reference/types/numeric.html#r-type.numeric.int.size.minimum
[target’s pointer width]:
    https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_pointer_width
[platform support]:
    https://doc.rust-lang.org/rustc/platform-support.html