Expand description
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. It has no
external dependencies, forbids unsafe code, and supports no_std (with
alloc).
It deliberately does not include type inference, configurable dialects,
a streaming reader/writer over std::io, schema validation, or lenient
recovery from malformed input.
§Records
At the lowest level a CSV document is a sequence of records, and each record
is a sequence of UTF-8 string fields. read_str parses text into
Vec<Vec<String>> and CsvWriter turns records back into text.
use reliakit_csv::{read_str, CsvWriter};
let records = read_str("name,city\nAda,London\n").unwrap();
assert_eq!(records, [["name", "city"], ["Ada", "London"]]);
// Serialization is deterministic: a field is quoted only when it must be,
// and every record ends with CRLF.
let mut writer = CsvWriter::new();
writer.write_record(["a", "b,c"]);
assert_eq!(writer.into_string(), "a,\"b,c\"\r\n");§Strictness
The reader rejects input that lenient parsers would accept, so a successful parse is a strong guarantee:
use reliakit_csv::read_str;
// A quote inside an unquoted field is rejected, not absorbed.
assert!(read_str("ab\"c\n").is_err());
// Records must be rectangular: a short row is an error, not a `None` cell.
assert!(read_str("a,b\nc\n").is_err());
// A quoted field that never closes is rejected.
assert!(read_str("\"oops\n").is_err());§Typed encoding
CsvEncode maps your record type to a row of fields (with a header), and
CsvDecode reads a row back, strictly. to_csv_string writes a header
row followed by one row per value; from_csv_str validates the header and
decodes the rest.
use reliakit_csv::{
from_csv_str, to_csv_string, CsvDecode, CsvDecodeError, CsvEncode, CsvField,
};
use std::vec::Vec;
#[derive(Debug, PartialEq)]
struct Row {
id: u32,
name: String,
}
impl CsvEncode for Row {
fn header() -> Vec<&'static str> {
vec!["id", "name"]
}
fn encode_fields(&self, out: &mut Vec<String>) {
out.push(self.id.encode_field());
out.push(self.name.encode_field());
}
}
impl CsvDecode for Row {
fn decode_fields(fields: &[&str]) -> Result<Self, CsvDecodeError> {
if fields.len() != 2 {
return Err(CsvDecodeError::field_count());
}
Ok(Row {
id: u32::decode_field(fields[0]).map_err(|e| e.at_field(0))?,
name: String::decode_field(fields[1]).map_err(|e| e.at_field(1))?,
})
}
}
let rows = vec![Row { id: 1, name: "Ada".into() }];
let text = to_csv_string(&rows);
assert_eq!(text, "id,name\r\n1,Ada\r\n");
assert_eq!(from_csv_str::<Row>(&text).unwrap(), rows);The per-field encode_field/decode_field calls above come from
CsvField, which is implemented for the integer types, bool, String,
and Option<T>.
§Limits
read_str applies conservative CsvLimits by default. Use
read_str_with_limits to choose a profile or tune individual limits:
use reliakit_csv::{read_str_with_limits, CsvLimits};
let limits = CsvLimits::conservative().with_max_fields_per_record(2);
assert!(read_str_with_limits("a,b,c\n", &limits).is_err());§Feature flags
std(default) enablesstd::error::Errorfor the error types. The crate is otherwiseno_stdand always usesalloc.
Structs§
- CsvDecode
Error - An error from decoding a CSV record into a typed value.
- CsvError
- An error produced while reading CSV.
- CsvLimits
- Bounds applied by
read_strto defend against adversarial input. - CsvWriter
- Builds CSV text one record at a time.
Enums§
- CsvDecode
Error Kind - The kind of a typed-CSV decoding error.
- CsvError
Kind - The category of a CSV reading failure.
- CsvFrom
StrError - The error type of
from_csv_str: either the input was not valid CSV, or a record did not match the target type. - CsvLimit
Kind - A resource limit that was exceeded while reading.
Traits§
- CsvDecode
- A record type that can be read from a CSV row.
- CsvEncode
- A record type that can be written as a CSV row.
- CsvField
- A scalar value that maps to and from a single CSV field.
Functions§
- from_
csv_ str - Reads CSV text into typed records, validating the header row.
- from_
csv_ str_ headerless - Reads headerless CSV text into typed records, decoding every record.
- from_
csv_ str_ headerless_ with_ limits - Reads headerless CSV text into typed records, with explicit limits.
- from_
csv_ str_ with_ limits - Reads CSV text into typed records, validating the header, with explicit limits.
- read_
str - Parses CSV text into records, using conservative
CsvLimits. - read_
str_ with_ limits - Parses CSV text into records with explicit
CsvLimits. - to_
csv_ string - Encodes a slice of records to CSV text, with a leading header row.
- to_
csv_ string_ headerless - Encodes a slice of records to CSV text with no header row.