A low-level, non-FSM, zero-copy CSV parser.
Dual-licensed under MIT or unlicense
https://docs.rs/csvroll
Add this to your Cargo.toml
:
toml
[dependencies]
csvroll = "0.1"
and this to your crate root:
rust
extern crate csvroll;
The parser uses SIMD which is not yet stabilized, so you need to use the nightly channel.
```rust extern crate rollbuf;
use rollbuf::RollBuf; use csvroll::parser::{Parser, Index,}; use csvroll::index_builder::IndexBuilder;
struct TestCase {
input: String,
buf_len: usize,
consume: Vec
let testcases = vec![ TestCase { input: "a\nb\nc,d,e".toowned(), buflen: 7, consume: vec![1, 1, 1, 1], want: vec![ ("a\nb\nc,d".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5 ], vec![1, 2])), ("b\nc,d,e".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5], vec![1])), ("c,d,e".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5], vec![3])), ("".toowned(), Index::fromparts(vec![], vec![])), ], }, TestCase { input: "a\nb\nc,d,e".toowned(), buflen: 7, consume: vec![2, 1, 1], want: vec![ ("a\nb\nc,d".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5 ], vec![1, 2])), ("c,d,e".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5], vec![3])), ("".toowned(), Index::fromparts(vec![], vec![])), ], }, TestCase { input: "a\nb\nc,d,e".toowned(), buflen: 7, consume: vec![1, 0, 1, 1, 1], want: vec![ ("a\nb\nc,d".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5 ], vec![1, 2])), ("b\nc,d,e".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5], vec![1])), ("b\nc,d,e".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5, 6..7], vec![1, 4])), ("c,d,e".toowned(), Index::fromparts(vec![0..1, 2..3, 4..5], vec![3])), ("".toowned(), Index::fromparts(vec![], vec![])), ], }, TestCase { input: "a\nb\nc\n".toowned(), buflen: 4, consume: vec![2, 1, 1], want: vec![ ("a\nb\n".toowned(), Index::fromparts(vec![0..1, 2..3], vec![1, 2])), ("c\n".toowned(), Index::fromparts(vec![0..1], vec![1])), ("".toowned(), Index::fromparts(vec![], vec![])), ], }, TestCase { input: "a\nb\nc,".toowned(), buflen: 4, consume: vec![2, 1, 1], want: vec![ ("a\nb\n".toowned(), Index::fromparts(vec![0..1, 2..3], vec![1, 2])), ("c,".toowned(), Index::fromparts(vec![0..1, 2..2], vec![2])), ("".toowned(), Index::from_parts(vec![], vec![])), ], }, ];
for (i, t) in testcases.intoiter().enumerate() { println!("test case: {}", i); let TestCase { input, buflen, consume, want } = t; let buf = RollBuf::withcapacity(buflen, input.asbytes()); let idxbuilder = IndexBuilder::new(b',', b'\n'); let mut parser = Parser::fromparts(buf, idx_builder);
for (i, (c, w)) in consume.iter().zip(&want).enumerate() {
println!("parse: {}", i);
parser.parse().unwrap();
assert_eq!(parser.output(), (w.0.as_bytes(), &w.1));
parser.consume(*c);
}
}
```