reliakit-csv
Strict, bounded, and deterministic CSV for reliability-sensitive Rust.
reliakit-csv reads and writes a strict subset of RFC 4180. It is built for
systems that process untrusted CSV or need predictable output: it rejects
malformed quoting, enforces a rectangular shape (every record has the same number
of fields), applies explicit resource limits, reports errors with a location, and
serializes deterministically.
The crate has no dependencies, is no_std-friendly (with alloc), and forbids
unsafe code.
What This Crate Does
read_str/read_str_with_limits— parse text intoVec<Vec<String>>, strictly and within bounds.CsvWriter— build CSV text one record at a time; a field is quoted only when it must be, and every record ends with\r\n.CsvField— encode/decode a single field for the integer types,bool,String, andOption<T>(an empty field isNone).CsvEncode/CsvDecode— map your record type to and from a row, with a header.to_csv_string/from_csv_strwrite and read a header row;*_headerlessvariants skip it.
What This Crate Does Not Do
It does not infer column types, support configurable dialects (the delimiter is
, and the quote is "), stream over std::io, validate against a schema, or
recover leniently from malformed input. A successful read is a strong guarantee,
not a best effort.
When To Use
- You parse CSV from an untrusted or semi-trusted source and want malformed input rejected, not silently repaired.
- You generate CSV that must be byte-for-byte reproducible (fixtures, exports, cache keys, diffs).
- You want a small, zero-dependency,
no_std-friendly reader/writer.
When Not To Use
- You need a configurable dialect (other delimiters, optional quoting modes) or lenient parsing of messy real-world files. Use a fuller-featured CSV crate.
- You need streaming over very large files without holding the input in memory.
Installation
[]
= "0.1"
For no_std with allocation:
[]
= { = "0.1", = false, = ["alloc"] }
Example
use ;
// Read rows of strings, strictly.
let rows = read_str.unwrap;
assert_eq!;
// Write deterministically: a field is quoted only when it must be.
let mut writer = new;
writer.write_record;
assert_eq!;
Typed records with a header:
use ;
let rows = vec!;
let text = to_csv_string;
assert_eq!;
assert_eq!;
Format
A strict subset of RFC 4180:
- UTF-8 text; the delimiter is
,and the quote character is". - The writer quotes a field only if it contains
,,",\r, or\n, doubles an embedded", and terminates every record with\r\n. - The reader accepts
\nand\r\nas record terminators and rejects a bare\r, a"inside an unquoted field, text after a closing quote, and an unterminated quoted field. - Records are rectangular: every record must have the same number of fields as the first, or the read fails.
- The wire format is fixed and covered by exact-output tests; it will not change
in a backward-incompatible way within
0.1.
Feature Flags
| Flag | Default | Description |
|---|---|---|
std |
yes | Enables the standard library (std::error::Error); implies alloc |
alloc |
no | The crate always needs alloc for owned strings and records |
Safety
This crate is #![forbid(unsafe_code)].
Minimum Supported Rust Version
Rust 1.85 and newer. No nightly features are used.
Status
Pre-1.0. The API is small and the wire format is fixed; the crate may receive
backward-compatible refinements before a 1.0 release.
License
Licensed under the MIT License. See LICENSE.