use crate::language::DsvLanguage;
use core::range::Range;
use oak_core::source::{SourceBuffer, ToSource};
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DsvRoot<const LANG: DsvLanguage> {
pub records: Vec<DsvRecord<LANG>>,
}
impl<const LANG: DsvLanguage> ToSource for DsvRoot<LANG> {
fn to_source(&self, buffer: &mut SourceBuffer) {
for (i, record) in self.records.iter().enumerate() {
if i > 0 {
buffer.push("\n");
}
record.to_source(buffer);
}
}
}
impl<const LANG: DsvLanguage> DsvRoot<LANG> {
pub fn new(records: Vec<DsvRecord<LANG>>) -> Self {
Self { records }
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DsvRecord<const LANG: DsvLanguage> {
pub fields: Vec<DsvField<LANG>>,
#[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
pub span: Range<usize>,
}
impl<const LANG: DsvLanguage> ToSource for DsvRecord<LANG> {
fn to_source(&self, buffer: &mut SourceBuffer) {
for (i, field) in self.fields.iter().enumerate() {
if i > 0 {
buffer.push_char(LANG.field_separator);
}
field.to_source(buffer);
}
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DsvField<const LANG: DsvLanguage> {
pub value: String,
pub is_quoted: bool,
#[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
pub span: Range<usize>,
}
impl<const LANG: DsvLanguage> ToSource for DsvField<LANG> {
fn to_source(&self, buffer: &mut SourceBuffer) {
if self.is_quoted {
buffer.push_char(LANG.quote_char);
let escaped = self.value.replace(LANG.quote_char, &format!("{}{}", LANG.quote_char, LANG.quote_char));
buffer.push(&escaped);
buffer.push_char(LANG.quote_char);
}
else {
buffer.push(&self.value);
}
}
}