Skip to content

← Ground Rules: Values, Types, Control Flow step 3 of 24

Easy Primitives

Check whether integers fit in a byte

For each input value, return whether it can be represented as a u8 without changing its numeric value.

pub fn fits_in_u8(values: &[i64]) -> Vec<bool>

A u8 stores integers from 0 through 255, inclusive. Return one boolean per input, preserving order and duplicates. Do not modify the borrowed slice. Empty input produces an empty vector.

Input Output
[0, 255, 256, -1] [true, true, false, false]
[128, 128] [true, true]
[i64::MIN, i64::MAX] [false, false]
[] []

Repair the range check

The starter already computes the correct booleans, but Clippy flags its manual interval check with manual_range_contains. Warnings are treated as errors. Replace the two comparisons with an inclusive range check, using u8::MIN and u8::MAX converted to i64 for the endpoints.

An inclusive range is written lo..=hi; lo..hi excludes the upper endpoint. The contains method takes a reference to the value being tested.

Integer widths and signedness

Rust's fixed-width integer types state both their width and whether they are signed. For an unsigned type with n bits, the range is 0 through 2^n - 1. For a signed type, it is -2^(n-1) through 2^(n-1) - 1.

Bits Signed Unsigned
8 i8 u8
16 i16 u16
32 i32 u32
64 i64 u64
128 i128 u128

Each has MIN and MAX constants. Using u8::MAX makes the intended target type clear. It does not automatically change if you later choose a different target type; you must update that reference too.

usize and isize have target-dependent widths matching the platform's pointer size. Slice lengths and individual slice indices use usize. This does not mean every index or count in Rust must use it: custom types can support other index types, and APIs can choose other integer types. Strings also have their own indexing restrictions rather than supporting a single integer character index.

Unsuffixed integer literals can get their type from context. When inference leaves an integer literal unconstrained, Rust uses i32 as the fallback.

Convert the bounds without narrowing the input

Every u8 value fits in i64, so i64::from(u8::MAX) is an exact, infallible conversion. Rust does not implicitly widen a u8 variable into an i64. The standard library provides TryFrom for the reverse integer conversion, which may fail.

This complete example shows the distinction:

fn main() {
    let byte = u8::MAX;
    let wide = i64::from(byte);
    assert_eq!(wide, 255);
    assert_eq!(u8::try_from(wide), Ok(byte));
    assert!(u8::try_from(256_i64).is_err());
    assert!(u8::try_from(-1_i64).is_err());
}

Do not cast an input to u8 before checking it. A narrowing integer cast can change its value: 256_i64 as u8 is 0 and -1_i64 as u8 is 255. Both results are bytes, but neither preserves the original number. Keep each input as i64 and compare it with the widened bounds.

Your solution must compile, preserve the output behavior and pass Clippy with warnings treated as errors.