OpenViSTAI · Agents · Blockchain · Crypto
Menu
OPENVIST RECIPES

Locate lines containing ASCII control characters with Rust

Rust

Identify retained-line positions containing bytes below 32 or DEL while leaving Unicode text otherwise uninterpreted.

Rust code excerpt: Locate lines containing ASCII control characters with Rust. Version 0.1.0. Read the full recipe for code, sources and recorded test scope.

Identify retained-line positions containing bytes below 32 or DEL while leaving Unicode text otherwise uninterpreted. 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 without arguments, supplying input through stdin. Help flags and all other arguments are invalid.
  • Input must contain at most 65536 bytes, be strict UTF-8, have no leading UTF-8 BOM, and contain no CR bytes.
  • Only LF separates lines. Exactly empty segments are discarded; whitespace-only segments are retained. No trimming, normalization, grouping, or deduplication occurs.
  • At most 100 nonempty lines are allowed, each containing at most 256 UTF-8 bytes. All input and line limits are validated before classification.
  • Successful output is exactly one JSON object followed by a newline, with one-based retained-line positions in ascending order. A position is included if its line contains U+0000 through U+001F or U+007F. LF is a separator, and CR is invalid. Other Unicode characters are not classified as ASCII controls.
  • Empty input or input containing only LF separators produces {"positions":[]}.
  • Success exits 0 and writes no stderr. Invalid arguments, invalid input, and stdin-read failures exit 2 with no stdout and exactly error: invalid input followed by a newline on stderr, subject to the failure limitations below.

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

  • The program requests at most 65537 bytes from stdin. Observing byte 65537 immediately rejects oversized input without reading further.
  • Stdin can block while awaiting data or EOF. Even exactly 65536 bytes require another read to establish EOF or detect an extra byte.
  • Memory use includes a fixed 65537-byte input buffer, metadata for at most 100 borrowed line slices, a small output string, and standard-library I/O overhead. Input text is not copied per line.
  • Successful output can be sensitive: it reveals which retained lines contain ASCII controls. Handle stdout accordingly.
  • Memory-allocation failures and stdout/stderr write or flush failures are outside the input-error guarantee. Output-write failures attempt exit status 2 and may leave partial stdout; diagnostic-write failures may prevent the required stderr message.
  • The implementation uses only the standard library and permitted APIs. It performs no filesystem access, networking, subprocess execution, or dynamic loading.

Run it

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

Example input

hello
a	b

é

Expected output

{"positions":[2,3]}
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};

fn invalid_input() -> ! {
    let _ = io::stderr().lock().write_all(b"error: invalid input\n");
    std::process::exit(2);
}

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

    // Read at most 65537 bytes, including the oversize-detection byte.
    let mut buffer = vec![0u8; 65_537];
    let mut used = 0usize;
    {
        let stdin = io::stdin();
        let mut input = stdin.lock();
        loop {
            match input.read(&mut buffer[used..]) {
                Ok(0) => break,
                Ok(n) => {
                    used += n;
                    if used == buffer.len() {
                        return Err(());
                    }
                }
                Err(e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(_) => return Err(()),
            }
        }
    }

    let text = std::str::from_utf8(&buffer[..used]).map_err(|_| ())?;
    if text.starts_with('\u{FEFF}') || text.as_bytes().contains(&b'\r') {
        return Err(());
    }

    // Finish all line-contract validation before classifying any line.
    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 output = String::from("{\"positions\":[");
    let mut first = true;
    for (index, line) in lines.iter().enumerate() {
        if line.as_bytes().iter().any(|&byte| byte < 32 || byte == 127) {
            if !first {
                output.push(',');
            }
            first = false;
            output.push_str(&(index + 1).to_string());
        }
    }
    output.push_str("]}\n");
    Ok(output)
}

fn main() {
    let output = match prepare_output() {
        Ok(output) => output,
        Err(()) => invalid_input(),
    };

    let stdout = io::stdout();
    let mut destination = stdout.lock();
    if destination.write_all(output.as_bytes()).is_err() {
        std::process::exit(2);
    }
    if destination.flush().is_err() {
        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 16 supplementary cases are executed in pinned, offline Rust 1.99.0 containers. These checks do not establish exhaustive correctness or behavior on other versions.