use std::io;
use fallible_streaming_iterator::FallibleStreamingIterator;
use super::{
CsvEncoder, DbnEncodable, DbnEncoder, DynWriter, EncodeDbn, EncodeRecord, EncodeRecordRef,
EncodeRecordTextExt, JsonEncoder,
};
use crate::{
decode::{DbnMetadata, DecodeRecordRef},
Compression, Encoding, Error, Metadata, RecordRef, Result, Schema,
};
pub struct DynEncoder<'a, W>(DynEncoderImpl<'a, W>)
where
W: io::Write;
#[allow(clippy::large_enum_variant)]
enum DynEncoderImpl<'a, W>
where
W: io::Write,
{
Dbn(DbnEncoder<DynWriter<'a, W>>),
Csv(CsvEncoder<DynWriter<'a, W>>),
Json(JsonEncoder<DynWriter<'a, W>>),
}
pub struct DynEncoderBuilder<'m, W>
where
W: io::Write,
{
writer: W,
encoding: Encoding,
compression: Compression,
metadata: &'m Metadata,
write_header: bool,
should_pretty_print: bool,
use_pretty_px: bool,
use_pretty_ts: bool,
with_symbol: bool,
delimiter: u8,
}
impl<'m, W> DynEncoderBuilder<'m, W>
where
W: io::Write,
{
pub fn new(
writer: W,
encoding: Encoding,
compression: Compression,
metadata: &'m Metadata,
) -> Self {
Self {
writer,
encoding,
compression,
metadata,
write_header: true,
should_pretty_print: false,
use_pretty_px: false,
use_pretty_ts: false,
with_symbol: false,
delimiter: b',',
}
}
pub fn write_header(mut self, write_header: bool) -> Self {
self.write_header = write_header;
self
}
pub fn all_pretty(self, all_pretty: bool) -> Self {
self.should_pretty_print(all_pretty)
.use_pretty_px(all_pretty)
.use_pretty_ts(all_pretty)
}
pub fn should_pretty_print(mut self, should_pretty_print: bool) -> Self {
self.should_pretty_print = should_pretty_print;
self
}
pub fn use_pretty_px(mut self, use_pretty_px: bool) -> Self {
self.use_pretty_px = use_pretty_px;
self
}
pub fn use_pretty_ts(mut self, use_pretty_ts: bool) -> Self {
self.use_pretty_ts = use_pretty_ts;
self
}
pub fn with_symbol(mut self, with_symbol: bool) -> Self {
self.with_symbol = with_symbol;
self
}
pub fn delimiter(mut self, delimiter: u8) -> Self {
self.delimiter = delimiter;
self
}
pub fn build<'a>(self) -> crate::Result<DynEncoder<'a, W>> {
let writer = DynWriter::new(self.writer, self.compression)?;
Ok(DynEncoder(match self.encoding {
Encoding::Dbn => DynEncoderImpl::Dbn(DbnEncoder::new(writer, self.metadata)?),
Encoding::Csv => DynEncoderImpl::Csv(
CsvEncoder::builder(writer)
.version(self.metadata.version)
.use_pretty_px(self.use_pretty_px)
.use_pretty_ts(self.use_pretty_ts)
.delimiter(self.delimiter)
.write_header(self.write_header)
.ts_out(self.metadata.ts_out)
.schema(self.metadata.schema)
.with_symbol(self.with_symbol)
.build()?,
),
Encoding::Json => DynEncoderImpl::Json(
JsonEncoder::builder(writer)
.should_pretty_print(self.should_pretty_print)
.use_pretty_px(self.use_pretty_px)
.use_pretty_ts(self.use_pretty_ts)
.build(),
),
}))
}
}
impl<W> DynEncoder<'_, W>
where
W: io::Write,
{
pub fn new(
writer: W,
encoding: Encoding,
compression: Compression,
metadata: &Metadata,
should_pretty_print: bool,
use_pretty_px: bool,
use_pretty_ts: bool,
) -> Result<Self> {
Self::builder(writer, encoding, compression, metadata)
.should_pretty_print(should_pretty_print)
.use_pretty_px(use_pretty_px)
.use_pretty_ts(use_pretty_ts)
.build()
}
pub fn builder(
writer: W,
encoding: Encoding,
compression: Compression,
metadata: &Metadata,
) -> DynEncoderBuilder<'_, W> {
DynEncoderBuilder::new(writer, encoding, compression, metadata)
}
pub fn encode_header<R: DbnEncodable>(&mut self, with_symbol: bool) -> Result<()> {
match &mut self.0 {
DynEncoderImpl::Csv(encoder) => encoder.encode_header::<R>(with_symbol),
_ => Ok(()),
}
}
pub fn encode_header_for_schema(
&mut self,
version: u8,
schema: Schema,
ts_out: bool,
with_symbol: bool,
) -> Result<()> {
match &mut self.0 {
DynEncoderImpl::Csv(encoder) => {
encoder.encode_header_for_schema(version, schema, ts_out, with_symbol)
}
_ => Ok(()),
}
}
}
impl<W> EncodeRecord for DynEncoder<'_, W>
where
W: io::Write,
{
fn encode_record<R: DbnEncodable>(&mut self, record: &R) -> Result<()> {
self.0.encode_record(record)
}
fn encode_records<R: DbnEncodable>(&mut self, records: &[R]) -> Result<()> {
self.0.encode_records(records)
}
fn flush(&mut self) -> Result<()> {
self.0.flush()
}
}
impl<W> EncodeRecordRef for DynEncoder<'_, W>
where
W: io::Write,
{
fn encode_record_ref(&mut self, record: RecordRef) -> Result<()> {
self.0.encode_record_ref(record)
}
unsafe fn encode_record_ref_ts_out(&mut self, record: RecordRef, ts_out: bool) -> Result<()> {
self.0.encode_record_ref_ts_out(record, ts_out)
}
}
impl<W> EncodeDbn for DynEncoder<'_, W>
where
W: io::Write,
{
fn encode_stream<R: DbnEncodable>(
&mut self,
stream: impl FallibleStreamingIterator<Item = R, Error = Error>,
) -> Result<()> {
self.0.encode_stream(stream)
}
fn encode_decoded<D: DecodeRecordRef + DbnMetadata>(&mut self, decoder: D) -> Result<()> {
self.0.encode_decoded(decoder)
}
}
impl<W> EncodeRecordTextExt for DynEncoder<'_, W>
where
W: io::Write,
{
fn encode_record_with_sym<R: DbnEncodable>(
&mut self,
record: &R,
symbol: Option<&str>,
) -> Result<()> {
self.0.encode_record_with_sym(record, symbol)
}
}
impl<W> EncodeRecord for DynEncoderImpl<'_, W>
where
W: io::Write,
{
fn encode_record<R: DbnEncodable>(&mut self, record: &R) -> Result<()> {
match self {
DynEncoderImpl::Dbn(enc) => enc.encode_record(record),
DynEncoderImpl::Csv(enc) => enc.encode_record(record),
DynEncoderImpl::Json(enc) => enc.encode_record(record),
}
}
fn encode_records<R: DbnEncodable>(&mut self, records: &[R]) -> Result<()> {
match self {
DynEncoderImpl::Dbn(encoder) => encoder.encode_records(records),
DynEncoderImpl::Csv(encoder) => encoder.encode_records(records),
DynEncoderImpl::Json(encoder) => encoder.encode_records(records),
}
}
fn flush(&mut self) -> Result<()> {
match self {
DynEncoderImpl::Dbn(enc) => enc.flush(),
DynEncoderImpl::Csv(enc) => enc.flush(),
DynEncoderImpl::Json(enc) => enc.flush(),
}
}
}
impl<W> EncodeRecordRef for DynEncoderImpl<'_, W>
where
W: io::Write,
{
fn encode_record_ref(&mut self, record: RecordRef) -> Result<()> {
match self {
DynEncoderImpl::Dbn(enc) => enc.encode_record_ref(record),
DynEncoderImpl::Csv(enc) => enc.encode_record_ref(record),
DynEncoderImpl::Json(enc) => enc.encode_record_ref(record),
}
}
unsafe fn encode_record_ref_ts_out(&mut self, record: RecordRef, ts_out: bool) -> Result<()> {
match self {
DynEncoderImpl::Dbn(enc) => enc.encode_record_ref_ts_out(record, ts_out),
DynEncoderImpl::Csv(enc) => enc.encode_record_ref_ts_out(record, ts_out),
DynEncoderImpl::Json(enc) => enc.encode_record_ref_ts_out(record, ts_out),
}
}
}
impl<W> EncodeDbn for DynEncoderImpl<'_, W>
where
W: io::Write,
{
fn encode_stream<R: DbnEncodable>(
&mut self,
stream: impl FallibleStreamingIterator<Item = R, Error = Error>,
) -> Result<()> {
match self {
DynEncoderImpl::Dbn(encoder) => encoder.encode_stream(stream),
DynEncoderImpl::Csv(encoder) => encoder.encode_stream(stream),
DynEncoderImpl::Json(encoder) => encoder.encode_stream(stream),
}
}
fn encode_decoded<D: DecodeRecordRef + DbnMetadata>(&mut self, decoder: D) -> Result<()> {
match self {
DynEncoderImpl::Dbn(encoder) => encoder.encode_decoded(decoder),
DynEncoderImpl::Csv(encoder) => encoder.encode_decoded(decoder),
DynEncoderImpl::Json(encoder) => encoder.encode_decoded(decoder),
}
}
}
impl<W> EncodeRecordTextExt for DynEncoderImpl<'_, W>
where
W: io::Write,
{
fn encode_record_with_sym<R: DbnEncodable>(
&mut self,
record: &R,
symbol: Option<&str>,
) -> Result<()> {
match self {
Self::Dbn(encoder) => encoder.encode_record(record),
Self::Csv(encoder) => encoder.encode_record_with_sym(record, symbol),
Self::Json(encoder) => encoder.encode_record_with_sym(record, symbol),
}
}
}