// std/csv - CSV parsing and writing
// Thin wrapper over the csv crate for clean Windjammer APIs
use csv
// Read CSV from string, returns vector of string records
fn parse(data: string) -> Result<Vec<Vec<string>>, csv.Error> {
let mut reader = csv.Reader.from_reader(data.as_bytes())
let mut records = Vec.new()
for result in reader.records() {
let record = result?
let row: Vec<string> = record.map(|field| "${field}").collect()
records.push(row)
}
Ok(records)
}
// Read CSV with headers, returns headers and data separately
fn parse_with_headers(data: string) -> Result<(Vec<string>, Vec<Vec<string>>), csv.Error> {
let mut reader = csv.Reader.from_reader(data.as_bytes())
// Get headers
let headers = reader.headers()?
.map(|h| "${h}")
.collect()
// Get records
let mut records = Vec.new()
for result in reader.records() {
let record = result?
let row: Vec<string> = record.map(|field| "${field}").collect()
records.push(row)
}
Ok((headers, records))
}
// Write CSV from vector of records
fn write(records: &[Vec<string>]) -> Result<string, csv.Error> {
let mut writer = csv.Writer.from_writer(vec![])
for record in records {
writer.write_record(record)?
}
let data = writer.into_inner()?
match String.from_utf8(data) {
Ok(s) => Ok(s),
Err(_) => Err(csv.Error.from(std.io.Error.new(std.io.ErrorKind.InvalidData, "Invalid UTF-8")))
}
}
// Write CSV with headers
fn write_with_headers(headers: &[string], records: &[Vec<string>]) -> Result<string, csv.Error> {
let mut writer = csv.Writer.from_writer(vec![])
// Write headers
writer.write_record(headers)?
// Write records
for record in records {
writer.write_record(record)?
}
let data = writer.into_inner()?
match String.from_utf8(data) {
Ok(s) => Ok(s),
Err(_) => Err(csv.Error.from(std.io.Error.new(std.io.ErrorKind.InvalidData, "Invalid UTF-8")))
}
}
// Parse CSV from bytes
fn parse_bytes(data: &[u8]) -> Result<Vec<Vec<string>>, csv.Error> {
let mut reader = csv.Reader.from_reader(data)
let mut records = Vec.new()
for result in reader.records() {
let record = result?
let row: Vec<string> = record.map(|field| "${field}").collect()
records.push(row)
}
Ok(records)
}
// Create a CSV reader with custom delimiter
fn reader_with_delimiter(data: string, delimiter: u8) -> csv.ReaderBuilder {
csv.ReaderBuilder.new()
.delimiter(delimiter)
.from_reader(data.as_bytes())
}
// Create a CSV writer with custom delimiter
fn writer_with_delimiter(delimiter: u8) -> csv.WriterBuilder {
csv.WriterBuilder.new()
.delimiter(delimiter)
.from_writer(vec![])
}