OpenViSTAI · Agents · Blockchain · Crypto
Menu
OPENVIST RECIPES

Locate leading tab indentation in text lines with Rust

Rust

Distinguish a tab at the beginning of a retained line from tabs appearing after another character.

Rust code excerpt: Locate leading tab indentation in text lines with Rust. Version 0.1.0. Read the full recipe for code, sources and recorded test scope.

Distinguish a tab at the beginning of a retained line from tabs appearing after another character. 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: rustc --edition=2021 recipe.rs -o recipe
  • Run recipe with text supplied on stdin. No CLI arguments are accepted, including help flags.
  • The CLI reads at most 65537 bytes and rejects input exceeding 65536 bytes. Input must be strict UTF-8 without a leading UTF-8 BOM or any CR character.
  • Only LF splits lines. Exactly empty segments are discarded; whitespace-only segments remain. There may be at most 100 retained lines, each containing at most 256 UTF-8 bytes. All limits are validated before classification.
  • A retained line qualifies only when its first Unicode scalar is U+0009 (TAB). A space followed by a tab does not qualify. No text is trimmed, normalized, grouped or deduplicated.
  • Success exits 0, emits exactly one JSON object followed by a newline, and emits no stderr. The positions array contains one-based retained-line indices in input order. Empty input or no qualifying lines produces {"positions":[]}.
  • Invalid arguments, invalid input and stdin-read failures exit 2 without stdout and emit exactly error: invalid input followed by a newline on stderr, subject to the output-failure limitation below. Diagnostics never contain input values.
  • The implementation uses only the standard library, stdin, stdout and stderr, plus argument inspection solely to reject arguments and process exit solely to set status.

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

  • Stdin can block while waiting for more data or EOF. The reader stops once it has consumed 65537 bytes; a valid-length stream normally requires EOF before processing finishes.
  • Memory use consists primarily of the bounded input buffer, up to 100 borrowed line references, and a small JSON output buffer. Allocator bookkeeping and allocation capacity may add overhead.
  • Successful output reveals which retained lines begin with tabs and may therefore disclose sensitive structural information. Handle or redirect it appropriately.
  • Memory-allocation failures and output-write failures, including stderr failures, are outside the input-error guarantee. A stdout write or flush failure exits 2 and may leave partial stdout; error diagnostics cannot be guaranteed when stderr itself fails.

Run it

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

Example input

	item
 item
 	item
item	

Expected output

{"positions":[1]}
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() -> ! {
    let stderr = io::stderr();
    let mut err = stderr.lock();
    let _ = err.write_all(b"error: invalid input\n");
    let _ = err.flush();
    std::process::exit(2);
}

fn main() {
    if std::env::args_os().skip(1).next().is_some() {
        invalid();
    }

    let mut input = Vec::with_capacity(65_537);
    {
        let stdin = io::stdin();
        let mut reader = stdin.lock().take(65_537);
        if reader.read_to_end(&mut input).is_err() {
            invalid();
        }
    }
    if input.len() > 65_536 {
        invalid();
    }

    let text = match std::str::from_utf8(&input) {
        Ok(text) => text,
        Err(_) => invalid(),
    };
    if text.starts_with('\u{feff}') || text.contains('\r') {
        invalid();
    }

    // Validate every retained line before performing any classification.
    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 {
            invalid();
        }
        lines.push(line);
    }

    let mut output = String::from("{\"positions\":[");
    let mut first = true;
    for (index, line) in lines.iter().enumerate() {
        // For valid UTF-8, an initial TAB byte is exactly U+0009.
        if line.as_bytes().first() == Some(&b'\t') {
            if !first {
                output.push(',');
            }
            first = false;
            output.push_str(&(index + 1).to_string());
        }
    }
    output.push_str("]}\n");

    let stdout = io::stdout();
    let mut out = stdout.lock();
    if out.write_all(output.as_bytes()).is_err() || out.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.