Struct csv::StringRecord
source · pub struct StringRecord(/* private fields */);
Expand description
A single CSV record stored as valid UTF-8 bytes.
A string record permits reading or writing CSV rows that are valid UTF-8.
If string records are used to read CSV data that is not valid UTF-8, then
the CSV reader will return an invalid UTF-8 error. If you do need to read
possibly invalid UTF-8 data, then you should prefer using a
ByteRecord
,
since it makes no assumptions about UTF-8.
If you are using the Serde (de)serialization APIs, then you probably never
need to interact with a ByteRecord
or a StringRecord
. However, there
are some circumstances in which you might need to use a raw record type
while still using Serde. For example, if you need to deserialize possibly
invalid UTF-8 fields, then you’ll need to first read your record into a
ByteRecord
, and then use ByteRecord::deserialize
to run Serde. Another
reason for using the raw record deserialization APIs is if you’re using
Serde to read into borrowed data such as a &'a str
or a &'a [u8]
.
Two StringRecord
s are compared on the basis of their field data. Any
position information associated with the records is ignored.
Implementations§
source§impl StringRecord
impl StringRecord
sourcepub fn new() -> StringRecord
pub fn new() -> StringRecord
Create a new empty StringRecord
.
Note that you may find the StringRecord::from
constructor more
convenient, which is provided by an impl on the From
trait.
Example: create an empty record
use csv::StringRecord;
let record = StringRecord::new();
assert_eq!(record.len(), 0);
Example: initialize a record from a Vec
use csv::StringRecord;
let record = StringRecord::from(vec!["a", "b", "c"]);
assert_eq!(record.len(), 3);
sourcepub fn with_capacity(buffer: usize, fields: usize) -> StringRecord
pub fn with_capacity(buffer: usize, fields: usize) -> StringRecord
Create a new empty StringRecord
with the given capacity.
buffer
refers to the capacity of the buffer used to store the
actual row contents. fields
refers to the number of fields one
might expect to store.
sourcepub fn from_byte_record(
record: ByteRecord
) -> Result<StringRecord, FromUtf8Error>
pub fn from_byte_record( record: ByteRecord ) -> Result<StringRecord, FromUtf8Error>
Create a new StringRecord
from a ByteRecord
.
Note that this does UTF-8 validation. If the given ByteRecord
does
not contain valid UTF-8, then this returns an error. The error includes
the UTF-8 error and the original ByteRecord
.
Example: valid UTF-8
use std::error::Error;
use csv::{ByteRecord, StringRecord};
fn example() -> Result<(), Box<dyn Error>> {
let byte_record = ByteRecord::from(vec!["a", "b", "c"]);
let str_record = StringRecord::from_byte_record(byte_record)?;
assert_eq!(str_record.len(), 3);
Ok(())
}
Example: invalid UTF-8
use csv::{ByteRecord, StringRecord};
let byte_record = ByteRecord::from(vec![
&b"quux"[..], &b"foo\xFFbar"[..], &b"c"[..],
]);
let err = StringRecord::from_byte_record(byte_record).unwrap_err();
assert_eq!(err.utf8_error().field(), 1);
assert_eq!(err.utf8_error().valid_up_to(), 3);
sourcepub fn from_byte_record_lossy(record: ByteRecord) -> StringRecord
pub fn from_byte_record_lossy(record: ByteRecord) -> StringRecord
Lossily create a new StringRecord
from a ByteRecord
.
This is like StringRecord::from_byte_record
, except all invalid UTF-8
sequences are replaced with the U+FFFD REPLACEMENT CHARACTER
, which
looks like this: �.
Example: valid UTF-8
use csv::{ByteRecord, StringRecord};
let byte_record = ByteRecord::from(vec!["a", "b", "c"]);
let str_record = StringRecord::from_byte_record_lossy(byte_record);
assert_eq!(str_record.len(), 3);
Example: invalid UTF-8
use csv::{ByteRecord, StringRecord};
let byte_record = ByteRecord::from(vec![
&b"quux"[..], &b"foo\xFFbar"[..], &b"c"[..],
]);
let str_record = StringRecord::from_byte_record_lossy(byte_record);
assert_eq!(&str_record[0], "quux");
assert_eq!(&str_record[1], "foo�bar");
assert_eq!(&str_record[2], "c");
sourcepub fn deserialize<'de, D: Deserialize<'de>>(
&'de self,
headers: Option<&'de StringRecord>
) -> Result<D>
pub fn deserialize<'de, D: Deserialize<'de>>( &'de self, headers: Option<&'de StringRecord> ) -> Result<D>
Deserialize this record.
The D
type parameter refers to the type that this record should be
deserialized into. The 'de
lifetime refers to the lifetime of the
StringRecord
. The 'de
lifetime permits deserializing into structs
that borrow field data from this record.
An optional headers
parameter permits deserializing into a struct
based on its field names (corresponding to header values) rather than
the order in which the fields are defined.
Example: without headers
This shows how to deserialize a single row into a struct based on the
order in which fields occur. This example also shows how to borrow
fields from the StringRecord
, which results in zero allocation
deserialization.
use std::error::Error;
use csv::StringRecord;
#[derive(serde::Deserialize)]
struct Row<'a> {
city: &'a str,
country: &'a str,
population: u64,
}
fn example() -> Result<(), Box<dyn Error>> {
let record = StringRecord::from(vec![
"Boston", "United States", "4628910",
]);
let row: Row = record.deserialize(None)?;
assert_eq!(row.city, "Boston");
assert_eq!(row.country, "United States");
assert_eq!(row.population, 4628910);
Ok(())
}
Example: with headers
This example is like the previous one, but shows how to deserialize into a struct based on the struct’s field names. For this to work, you must provide a header row.
This example also shows that you can deserialize into owned data
types (e.g., String
) instead of borrowed data types (e.g., &str
).
use std::error::Error;
use csv::StringRecord;
#[derive(serde::Deserialize)]
struct Row {
city: String,
country: String,
population: u64,
}
fn example() -> Result<(), Box<dyn Error>> {
// Notice that the fields are not in the same order
// as the fields in the struct!
let header = StringRecord::from(vec![
"country", "city", "population",
]);
let record = StringRecord::from(vec![
"United States", "Boston", "4628910",
]);
let row: Row = record.deserialize(Some(&header))?;
assert_eq!(row.city, "Boston");
assert_eq!(row.country, "United States");
assert_eq!(row.population, 4628910);
Ok(())
}
sourcepub fn iter(&self) -> StringRecordIter<'_> ⓘ
pub fn iter(&self) -> StringRecordIter<'_> ⓘ
Returns an iterator over all fields in this record.
Example
This example shows how to iterate over each field in a StringRecord
.
use csv::StringRecord;
let record = StringRecord::from(vec!["a", "b", "c"]);
for field in record.iter() {
assert!(field == "a" || field == "b" || field == "c");
}
sourcepub fn get(&self, i: usize) -> Option<&str>
pub fn get(&self, i: usize) -> Option<&str>
Return the field at index i
.
If no field at index i
exists, then this returns None
.
Example
use csv::StringRecord;
let record = StringRecord::from(vec!["a", "b", "c"]);
assert_eq!(record.get(1), Some("b"));
assert_eq!(record.get(3), None);
sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if and only if this record is empty.
Example
use csv::StringRecord;
assert!(StringRecord::new().is_empty());
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of fields in this record.
Example
use csv::StringRecord;
let record = StringRecord::from(vec!["a", "b", "c"]);
assert_eq!(record.len(), 3);
sourcepub fn truncate(&mut self, n: usize)
pub fn truncate(&mut self, n: usize)
Truncate this record to n
fields.
If n
is greater than the number of fields in this record, then this
has no effect.
Example
use csv::StringRecord;
let mut record = StringRecord::from(vec!["a", "b", "c"]);
assert_eq!(record.len(), 3);
record.truncate(1);
assert_eq!(record.len(), 1);
assert_eq!(record, vec!["a"]);
sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clear this record so that it has zero fields.
Note that it is not necessary to clear the record to reuse it with the CSV reader.
Example
use csv::StringRecord;
let mut record = StringRecord::from(vec!["a", "b", "c"]);
assert_eq!(record.len(), 3);
record.clear();
assert_eq!(record.len(), 0);
sourcepub fn trim(&mut self)
pub fn trim(&mut self)
Trim the fields of this record so that leading and trailing whitespace is removed.
This method uses the Unicode definition of whitespace.
Example
use csv::StringRecord;
let mut record = StringRecord::from(vec![
" ", "\u{3000}\tfoo ", "bar ", "b a z",
]);
record.trim();
assert_eq!(record, vec!["", "foo", "bar", "b a z"]);
sourcepub fn push_field(&mut self, field: &str)
pub fn push_field(&mut self, field: &str)
Add a new field to this record.
Example
use csv::StringRecord;
let mut record = StringRecord::new();
record.push_field("foo");
assert_eq!(&record[0], "foo");
sourcepub fn position(&self) -> Option<&Position>
pub fn position(&self) -> Option<&Position>
Return the position of this record, if available.
Example
use std::error::Error;
use csv::{StringRecord, ReaderBuilder};
fn example() -> Result<(), Box<dyn Error>> {
let mut record = StringRecord::new();
let mut rdr = ReaderBuilder::new()
.has_headers(false)
.from_reader("a,b,c\nx,y,z".as_bytes());
assert!(rdr.read_record(&mut record)?);
{
let pos = record.position().expect("a record position");
assert_eq!(pos.byte(), 0);
assert_eq!(pos.line(), 1);
assert_eq!(pos.record(), 0);
}
assert!(rdr.read_record(&mut record)?);
{
let pos = record.position().expect("a record position");
assert_eq!(pos.byte(), 6);
assert_eq!(pos.line(), 2);
assert_eq!(pos.record(), 1);
}
// Finish the CSV reader for good measure.
assert!(!rdr.read_record(&mut record)?);
Ok(())
}
sourcepub fn set_position(&mut self, pos: Option<Position>)
pub fn set_position(&mut self, pos: Option<Position>)
Set the position of this record.
Example
use csv::{StringRecord, Position};
let mut record = StringRecord::from(vec!["a", "b", "c"]);
let mut pos = Position::new();
pos.set_byte(100);
pos.set_line(4);
pos.set_record(2);
record.set_position(Some(pos.clone()));
assert_eq!(record.position(), Some(&pos));
sourcepub fn range(&self, i: usize) -> Option<Range<usize>>
pub fn range(&self, i: usize) -> Option<Range<usize>>
Return the start and end position of a field in this record.
If no such field exists at the given index, then return None
.
The range returned can be used with the slice returned by as_slice
.
Namely, the range returned is guaranteed to start and end at valid
UTF-8 sequence boundaries.
Example
use csv::StringRecord;
let record = StringRecord::from(vec!["foo", "quux", "z"]);
let range = record.range(1).expect("a record range");
assert_eq!(&record.as_slice()[range], "quux");
sourcepub fn as_slice(&self) -> &str
pub fn as_slice(&self) -> &str
Return the entire row as a single string slice. The slice returned
stores all fields contiguously. The boundaries of each field can be
determined via the range
method.
Example
use csv::StringRecord;
let record = StringRecord::from(vec!["foo", "quux", "z"]);
assert_eq!(record.as_slice(), "fooquuxz");
sourcepub fn as_byte_record(&self) -> &ByteRecord
pub fn as_byte_record(&self) -> &ByteRecord
Return a reference to this record’s raw
ByteRecord
.
Example
use csv::StringRecord;
let str_record = StringRecord::from(vec!["a", "b", "c"]);
let byte_record = str_record.as_byte_record();
assert_eq!(&byte_record[2], b"c");
sourcepub fn into_byte_record(self) -> ByteRecord
pub fn into_byte_record(self) -> ByteRecord
Convert this StringRecord
into a
ByteRecord
.
Example
use csv::StringRecord;
let str_record = StringRecord::from(vec!["a", "b", "c"]);
let byte_record = str_record.into_byte_record();
assert_eq!(&byte_record[2], b"c");
Note that this can also be achieved using the From
impl:
use csv::{ByteRecord, StringRecord};
// Using ByteRecord::from...
let str_record = StringRecord::from(vec!["a", "b", "c"]);
assert_eq!(ByteRecord::from(str_record).len(), 3);
// Using StringRecord::into...
let str_record = StringRecord::from(vec!["a", "b", "c"]);
let byte_record: ByteRecord = str_record.into();
assert_eq!(byte_record.len(), 3);
Trait Implementations§
source§impl Clone for StringRecord
impl Clone for StringRecord
source§fn clone(&self) -> StringRecord
fn clone(&self) -> StringRecord
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moresource§impl Debug for StringRecord
impl Debug for StringRecord
source§impl Default for StringRecord
impl Default for StringRecord
source§fn default() -> StringRecord
fn default() -> StringRecord
source§impl<T: AsRef<str>> Extend<T> for StringRecord
impl<T: AsRef<str>> Extend<T> for StringRecord
source§fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)source§impl<'a, T: AsRef<str>> From<&'a [T]> for StringRecord
impl<'a, T: AsRef<str>> From<&'a [T]> for StringRecord
source§fn from(xs: &'a [T]) -> StringRecord
fn from(xs: &'a [T]) -> StringRecord
source§impl From<StringRecord> for ByteRecord
impl From<StringRecord> for ByteRecord
source§fn from(record: StringRecord) -> ByteRecord
fn from(record: StringRecord) -> ByteRecord
source§impl<T: AsRef<str>> From<Vec<T, Global>> for StringRecord
impl<T: AsRef<str>> From<Vec<T, Global>> for StringRecord
source§fn from(xs: Vec<T>) -> StringRecord
fn from(xs: Vec<T>) -> StringRecord
source§impl<T: AsRef<str>> FromIterator<T> for StringRecord
impl<T: AsRef<str>> FromIterator<T> for StringRecord
source§fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> StringRecord
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> StringRecord
source§impl Index<usize> for StringRecord
impl Index<usize> for StringRecord
source§impl<'a> IntoIterator for &'a StringRecord
impl<'a> IntoIterator for &'a StringRecord
source§impl PartialEq<StringRecord> for StringRecord
impl PartialEq<StringRecord> for StringRecord
source§fn eq(&self, other: &StringRecord) -> bool
fn eq(&self, other: &StringRecord) -> bool
self
and other
values to be equal, and is used
by ==
.