OpenViSTAI · Agents · Blockchain · Crypto
Menu
OPENVIST RECIPES

Decode lowercase hexadecimal octet lines with Rust

Rust

Convert two-character hexadecimal tokens into ordered byte values without interpreting them as text.

Rust code excerpt: Decode lowercase hexadecimal octet lines with Rust. Version 0.1.0. Read the full recipe for code, sources and recorded test scope.

Convert two-character hexadecimal tokens into ordered byte values without interpreting them as text. Work only with supplied input; this does not contact external services or modify input.

Before you start

  • Save as recipe.rs and compile with Rust 1.99.0 using: rustc --edition=2021 recipe.rs -o recipe
  • Run ./recipe with input supplied through stdin. No CLI arguments are accepted, including help flags.
  • Reads at most 65537 bytes and rejects input exceeding 65536 bytes. Requires strict UTF-8, rejects a leading UTF-8 BOM, and rejects every CR.
  • Splits only at LF and discards exactly empty segments. Before token classification, enforces at most 100 nonempty lines and at most 256 UTF-8 bytes per retained line. No trimming or normalization occurs.
  • Each retained line must be exactly two lowercase ASCII hexadecimal digits. Preserves order and duplicates, converting tokens into integer byte values without interpreting decoded bytes as text.
  • Empty input or input consisting only of LF characters produces {"bytes":[]}. Successful output is one JSON object followed by a newline, with exit status 0 and no stderr.
  • All input validation completes before successful stdout is written. Invalid arguments, invalid input, and stdin-read failures produce no stdout, exit 2, and write exactly error: invalid input followed by a newline to stderr, subject to the output-failure limitation below.
  • Uses only the standard library and permitted APIs; no Cargo, external crates, filesystem access, networking, or subprocesses.

Build and check

  1. Save the example as recipe.rs.
  2. Compile with Rust 1.99.0 using rustc --edition=2021 recipe.rs -o recipe.
  3. Prepare UTF-8 input.txt following the documented operation-specific conventions.
  4. Run ./recipe < input.txt.
  5. Inspect the JSON result. Exit 2 with exactly error: invalid input followed by a newline on stderr and no stdout identifies rejected input or stdin-read failure. Output-write failures may also exit nonzero, without that diagnostic and potentially after partial stdout; these are outside the input-error guarantee.

Limits to understand

  • Memory use is bounded by the 65537-byte input buffer, up to 100 borrowed line references and 100 decoded bytes, a JSON output buffer of at most 412 bytes, and standard-library buffering and allocation overhead.
  • Reading stdin may block while waiting for data or EOF. Inputs of 65536 bytes or fewer require EOF to establish completion.
  • Successful output contains decoded input values and may be sensitive. Error diagnostics never include input values.
  • Memory-allocation failures and output-write failures are outside the input-error guarantee. Output-write failures may leave partial stdout or prevent the fixed stderr diagnostic from being delivered; detected stdout-write failures exit 2.

Run it

rustc --edition=2021 recipe.rs -o recipe
./recipe < input.txt

Example input

00
ff
7f
00

Expected output

{"bytes":[0,255,127,0]}
INSPECT THE SCRIPT

Inspect, copy and run the documented checks.

This browser preview builds code locally. It does not contact an API or run the code.

Default example ready.

Rust example
use std::io::{self, Read, Write};
use std::str;

fn nibble(byte: u8) -> Result<u8, ()> {
    match byte {
        b'0'..=b'9' => Ok(byte - b'0'),
        b'a'..=b'f' => Ok(byte - b'a' + 10),
        _ => Err(()),
    }
}

fn decode() -> Result<String, ()> {
    if std::env::args_os().skip(1).next().is_some() {
        return Err(());
    }

    let stdin = io::stdin();
    let mut input = Vec::with_capacity(65_537);
    stdin.lock().take(65_537).read_to_end(&mut input).map_err(|_| ())?;
    if input.len() > 65_536 {
        return Err(());
    }

    let text = str::from_utf8(&input).map_err(|_| ())?;
    if text.starts_with('\u{feff}') || text.as_bytes().contains(&b'\r') {
        return Err(());
    }

    // Enforce all retained-line limits before classifying any token.
    let mut lines = Vec::with_capacity(100);
    for line in text.split('\n') {
        if line.is_empty() {
            continue;
        }
        if line.len() > 256 || lines.len() == 100 {
            return Err(());
        }
        lines.push(line);
    }

    let mut values = Vec::with_capacity(lines.len());
    for line in lines {
        let token = line.as_bytes();
        if token.len() != 2 {
            return Err(());
        }
        let high = nibble(token[0])?;
        let low = nibble(token[1])?;
        values.push(high * 16 + low);
    }

    let mut output = String::with_capacity(412);
    output.push_str("{\"bytes\":[");
    for (index, value) in values.iter().enumerate() {
        if index != 0 {
            output.push(',');
        }
        output.push_str(&value.to_string());
    }
    output.push_str("]}\n");
    Ok(output)
}

fn main() {
    match decode() {
        Ok(output) => {
            let stdout = io::stdout();
            if stdout.lock().write_all(output.as_bytes()).is_err() {
                std::process::exit(2);
            }
        }
        Err(()) => {
            let stderr = io::stderr();
            let _ = stderr.lock().write_all(b"error: invalid input\n");
            std::process::exit(2);
        }
    }
}
What to verify after running
  • The example must produce the documented JSON result.
  • Empty stdin must produce the documented empty result.
  • Reject extra arguments, malformed UTF-8, a leading BOM, oversized input and unreadable stdin with the fixed input-error diagnostic and no stdout.

Request or format preview

Illustrative preview. No provider response, price or balance is fetched.

Change a setting to inspect the preview.

Official sources and related profiles

    Code license: MIT. Keep the license notice with your copy.

    Example version 0.1.0 · Documentation reviewed 2026-10-14.

    Six independent CLI fixtures and 17 supplementary cases are executed in pinned, offline Rust 1.99.0 containers. These checks do not establish exhaustive correctness or behavior on other versions.