use crate::{
base::{RsCore, OAM},
conn::AmConnCore,
protocol::parts::{HdbValue, ResultSetMetadata},
HdbError, HdbResult,
};
use serde_db::de::DeserializableRow;
use std::sync::Arc;
#[derive(Debug)]
pub struct Row {
metadata: Arc<ResultSetMetadata>,
value_iter: <Vec<HdbValue<'static>> as IntoIterator>::IntoIter,
}
impl Row {
pub(crate) fn new(metadata: Arc<ResultSetMetadata>, values: Vec<HdbValue<'static>>) -> Self {
Self {
metadata,
value_iter: values.into_iter(),
}
}
pub fn try_into<'de, T>(self) -> HdbResult<T>
where
T: serde::de::Deserialize<'de>,
{
trace!("Row::into_typed()");
Ok(DeserializableRow::try_into(self)?)
}
pub fn next_value(&mut self) -> Option<HdbValue<'static>> {
self.value_iter.next()
}
pub fn next_try_into<'de, T>(&mut self) -> HdbResult<T>
where
T: serde::de::Deserialize<'de>,
{
self.next_value()
.ok_or_else(|| HdbError::Usage("no more value"))?
.try_into()
}
pub fn len(&self) -> usize {
trace!("Row::len()");
self.value_iter.len()
}
pub fn is_empty(&self) -> bool {
self.value_iter.as_slice().is_empty()
}
pub fn into_single_value(mut self) -> HdbResult<HdbValue<'static>> {
if self.len() > 1 {
Err(HdbError::Usage("Row has more than one field"))
} else {
Ok(self
.next_value()
.ok_or_else(|| HdbError::Usage("Row is empty"))?)
}
}
pub fn metadata(&self) -> &ResultSetMetadata {
trace!("Row::metadata()");
&(self.metadata)
}
#[cfg(feature = "sync")]
pub(crate) fn parse_sync(
md: Arc<ResultSetMetadata>,
o_am_rscore: &OAM<RsCore>,
am_conn_core: &AmConnCore,
rdr: &mut std::io::Cursor<Vec<u8>>,
) -> HdbResult<Self> {
let mut values = Vec::<HdbValue>::new();
let md0 = Arc::as_ref(&md);
for col_md in &**md0 {
let value = HdbValue::parse_sync(
col_md.type_id(),
col_md.is_array_type(),
col_md.scale(),
col_md.is_nullable(),
am_conn_core,
o_am_rscore,
rdr,
)?;
values.push(value);
}
let row = Self::new(md, values);
Ok(row)
}
#[cfg(feature = "async")]
pub(crate) async fn parse_async(
md: Arc<ResultSetMetadata>,
o_am_rscore: &OAM<RsCore>,
am_conn_core: &AmConnCore,
rdr: &mut std::io::Cursor<Vec<u8>>,
) -> HdbResult<Self> {
let mut values = Vec::<HdbValue>::new();
let md0 = Arc::as_ref(&md);
for col_md in &**md0 {
let value = HdbValue::parse_async(
col_md.type_id(),
col_md.is_array_type(),
col_md.scale(),
col_md.is_nullable(),
am_conn_core,
o_am_rscore,
rdr,
)
.await?;
values.push(value);
}
let row = Self::new(md, values);
Ok(row)
}
}
impl std::ops::Index<usize> for Row {
type Output = HdbValue<'static>;
fn index(&self, idx: usize) -> &HdbValue<'static> {
&self.value_iter.as_slice()[idx]
}
}
impl std::ops::IndexMut<usize> for Row {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
&mut self.value_iter.as_mut_slice()[idx]
}
}
impl Iterator for Row {
type Item = HdbValue<'static>;
fn next(&mut self) -> Option<HdbValue<'static>> {
self.next_value()
}
}
impl std::fmt::Display for Row {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
for v in self.value_iter.as_slice() {
write!(fmt, "{v}, ")?;
}
Ok(())
}
}