RFC-4180 compliant CSV and TSV parser, serializer, and data processor for Alya.
- ⚡ High Performance: Native parsing and stringification reaching over 1M ops/sec.
- 📜 RFC-4180 Compliant: Handles commas inside quotes, CRLF/LF line endings, escaped double quotes (
""), and multiline fields. - 📑 Header-to-Map Records: Automatically maps header rows into structured dictionary records (
[ {"name": "Alice", "role": "Dev"} ]). - 🔄 Custom Delimiters: Built-in support for CSV (
,), TSV (\t), Semicolon (;), and custom delimiters. - 📁 File I/O: Direct helpers to read and write rows or records to files.
csv/
├── alya.toml # Package manifest
├── src/
│ ├── lib.alya # Public API facade
│ ├── types.alya # CsvOptions configuration struct & constructors
│ ├── core/
│ │ ├── parser.alya # State-machine RFC-4180 CSV / TSV parser & record mapper
│ │ └── writer.alya # CSV / TSV serializer & field escaping
│ └── io/
│ └── file.alya # File read / write operations
├── examples/
│ └── demo.alya # Comprehensive runnable demo
├── tests/
│ └── test_basic.alya # 47 RFC-4180 automated test cases
└── benches/
└── bench_basic.alya # Micro-benchmarks
Add csv to the [dependencies] section in your alya.toml:
[dependencies]
csv = { git = "https://github.com/alya-lang/csv", branch = "main" }Or install it directly using the Alya package CLI:
alya add csv --git https://github.com/alya-lang/csv --branch main
alya install| Feature | Default | Description |
|---|---|---|
io |
✅ | File I/O (read_file_rows/read_file_records/write_file_rows/write_file_records). Without it only in-memory parse/stringify remain. |
# Full build (default)
alya install
alya test
# Slim build without file I/O
alya install --no-default-features
alya test --no-default-featuresimport "csv"
function main()
let raw = "name,role,city\nAlice,Engineer,\"New York, NY\"\nBob,Lead,London"
# Parse into 2D row array
let rows = csv::parse_csv(raw)
say "First person: " + rows[1][0] # Alice
# Serialize back to CSV
let output = csv::stringify_csv(rows)
say output
end
main()
import "csv"
function main()
let raw = "id,product,price\n101,Laptop,1200\n102,Mouse,25"
let records = csv::parse_csv_records(raw)
let i = 0
while i < len(records)
let item = records[i]
say "Item: " + item["product"] + " -> $" + item["price"]
i += 1
end
# Serialize records with specific column order
let headers = ["id", "product", "price"]
let csv_text = csv::stringify_csv_records(records, headers)
say csv_text
end
main()
import "csv"
function main()
let path = "./inventory.csv"
let rows = [
["sku", "name", "qty"],
["A01", "Keyboard", "50"],
["B02", "Monitor", "20"]
]
# Write rows to file
csv::write_file_rows(path, rows)
# Read rows back
let loaded = csv::read_file_rows(path)
say "Total rows: " + str(len(loaded))
end
main()
| Function | Arguments | Returns | Description |
|---|---|---|---|
options() |
- | CsvOptions |
Returns default CSV options (, delimiter, CRLF disabled, trim disabled). |
tsv_options() |
- | CsvOptions |
Returns TSV options (\t delimiter). |
custom_options(delimiter) |
delimiter: string |
CsvOptions |
Returns options with a custom delimiter character. |
| Function | Arguments | Returns | Description |
|---|---|---|---|
parse_csv(text, opts = null) |
text: string, opts: CsvOptions |
array |
Parses CSV text into a 2D array of rows. |
parse_tsv(text, opts = null) |
text: string, opts: CsvOptions |
array |
Parses TSV text into a 2D array of rows. |
parse_csv_records(text, opts = null) |
text: string, opts: CsvOptions |
array |
Parses CSV text into a list of Map records using the header row. |
parse_tsv_records(text, opts = null) |
text: string, opts: CsvOptions |
array |
Parses TSV text into a list of Map records using the header row. |
| Function | Arguments | Returns | Description |
|---|---|---|---|
stringify_csv(rows, opts = null) |
rows: array, opts: CsvOptions |
string |
Serializes a 2D array of rows into CSV text. |
stringify_tsv(rows, opts = null) |
rows: array, opts: CsvOptions |
string |
Serializes a 2D array of rows into TSV text. |
stringify_csv_records(records, headers = null, opts = null) |
records: array, headers: array, opts: CsvOptions |
string |
Serializes Map records into CSV text with headers. |
stringify_tsv_records(records, headers = null, opts = null) |
records: array, headers: array, opts: CsvOptions |
string |
Serializes Map records into TSV text with headers. |
| Function | Arguments | Returns | Description |
|---|---|---|---|
read_file_rows(path, opts = null) |
path: string, opts: CsvOptions |
array |
Reads and parses rows directly from a CSV file. |
read_file_records(path, opts = null) |
path: string, opts: CsvOptions |
array |
Reads and parses Map records directly from a CSV file. |
write_file_rows(path, rows, opts = null) |
path: string, rows: array, opts: CsvOptions |
int |
Serializes rows and writes to a CSV file. |
write_file_records(path, records, headers = null, opts = null) |
path: string, records: array, headers: array, opts: CsvOptions |
int |
Serializes Map records and writes to a CSV file. |
Run the test suite using alya:
alya test
# or
alya run tests/test_basic.alyaRun the benchmark suite:
alya run benches/bench_basic.alyaRun the example demo:
alya run examples/demo.alyaCheck code formatting:
alya fmt . --checkRun static code linter:
alya lint . --checkContributions are welcome! Please follow these steps:
- Fork the repository and clone it locally
- Install dependencies:
alya install
- Create your feature branch (
git checkout -b feature/my-feature) - Verify tests and formatting before opening a PR:
alya test alya fmt . --check
- Commit your changes (
git commit -m "feat: add feature") and open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.