use std::any::type_name;
use indexmap::IndexMap;
use crate::{AkitaDataError, AkitaValue, ConversionError, FromAkitaValue, IntoAkitaValue};
impl<N, V> FromAkitaValue for (N, V)
where
N: FromAkitaValue,
V: FromAkitaValue,
{
fn from_value_opt(value: &AkitaValue) -> Result<Self, AkitaDataError> {
match value {
AkitaValue::List(elements) => {
if elements.len() != 2 {
return Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!(
"Expected tuple with 2 elements, got {} elements",
elements.len()
)}));
}
let n = match N::from_value_opt(&elements[0]) {
Ok(val) => val,
Err(e) => {
return Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!(
"Failed to convert first element to {}: {}",
type_name::<N>(),
e
)}))
}
};
let v = match V::from_value_opt(&elements[1]) {
Ok(val) => val,
Err(e) => {
return Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!(
"Failed to convert second element to {}: {}",
type_name::<V>(),
e
)}))
}
};
Ok((n, v))
}
AkitaValue::Object(map) if map.len() == 2 => {
let n = match map.get_index(0) {
Some((_, val)) => match N::from_value_opt(val) {
Ok(val) => val,
Err(e) => {
return Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!(
"Failed to convert key '_1' to {}: {}",
type_name::<N>(),
e
)}))
}
},
None => {
return Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: "Missing key 0 in object for tuple conversion".to_string()
}));
}
};
let v = match map.get_index(1) {
Some((_, val)) => match V::from_value_opt(val) {
Ok(val) => val,
Err(e) => {
return Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!(
"Failed to convert key 1 to {}: {}",
type_name::<V>(),
e
)}))
}
},
None => {
return Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!("{}", "Missing key 1 in object for tuple conversion".to_string())
}));
}
};
Ok((n, v))
}
_ => Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!(
"Cannot convert {:?} to tuple ({}, {})",
value,
type_name::<N>(),
type_name::<V>()
)})),
}
}
}
impl<N, V> IntoAkitaValue for (N, V)
where
N: IntoAkitaValue,
V: IntoAkitaValue,
{
fn into_value(&self) -> AkitaValue {
AkitaValue::List(vec![
self.0.into_value(),
self.1.into_value(),
])
}
}
impl<N, V> IntoAkitaValue for &mut (N, V)
where
N: IntoAkitaValue + Clone,
V: IntoAkitaValue + Clone,
{
fn into_value(&self) -> AkitaValue {
AkitaValue::List(vec![
self.0.clone().into_value(),
self.1.clone().into_value(),
])
}
}
impl<N, V> IntoAkitaValue for [(N, V)]
where
N: IntoAkitaValue + Clone,
V: IntoAkitaValue + Clone,
{
fn into_value(&self) -> AkitaValue {
AkitaValue::List(
self.iter()
.map(|(n, v)| AkitaValue::List(vec![n.clone().into_value(), v.clone().into_value()]))
.collect()
)
}
}
impl<N, V> IntoAkitaValue for Vec<(N, V)>
where
N: IntoAkitaValue + Clone,
V: IntoAkitaValue + Clone,
{
fn into_value(&self) -> AkitaValue {
AkitaValue::List(
self.iter()
.map(|(n, v)| AkitaValue::List(vec![n.clone().into_value(), v.clone().into_value()]))
.collect()
)
}
}
pub type KeyValue<K, V> = (K, V);
pub fn try_into_key_value<K, V>(value: &AkitaValue) -> Result<(K, V), AkitaDataError>
where
K: FromAkitaValue,
V: FromAkitaValue,
{
<(K, V)>::from_value_opt(value)
}
pub fn from_key_value<K, V>(key: K, value: V) -> AkitaValue
where
K: IntoAkitaValue,
V: IntoAkitaValue,
{
AkitaValue::List(vec![key.into_value(), value.into_value()])
}
pub fn object_to_tuples<K, V>(value: &AkitaValue) -> Result<Vec<(K, V)>, AkitaDataError>
where
K: FromAkitaValue + From<String>,
V: FromAkitaValue,
{
match value {
AkitaValue::Object(map) => {
let mut result = Vec::with_capacity(map.len());
for (key, val) in map {
let k = K::from(key.clone());
let v = V::from_value_opt(val)?;
result.push((k, v));
}
Ok(result)
}
_ => Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!("Cannot convert {:?} to key-value pairs", value)
}))
}
}
pub fn tuples_to_object<K, V, I>(pairs: I) -> AkitaValue
where
K: Into<String> + Clone,
V: IntoAkitaValue + Clone,
I: IntoIterator<Item = (K, V)>,
{
let mut map = IndexMap::new();
for (key, value) in pairs.into_iter() {
map.insert(key.into(), value.into_value());
}
AkitaValue::Object(map)
}
impl IntoAkitaValue for (String, AkitaValue) {
fn into_value(&self) -> AkitaValue {
AkitaValue::List(vec![
self.0.clone().into_value(),
self.1.clone(),
])
}
}
impl<A, B, C> FromAkitaValue for (A, B, C)
where
A: FromAkitaValue,
B: FromAkitaValue,
C: FromAkitaValue,
{
fn from_value_opt(value: &AkitaValue) -> Result<Self, AkitaDataError> {
match value {
AkitaValue::List(elements) if elements.len() == 3 => {
Ok((
A::from_value_opt(&elements[0])?,
B::from_value_opt(&elements[1])?,
C::from_value_opt(&elements[2])?,
))
}
_ => Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!("Cannot convert {:?} to 3-tuple", value)
})),
}
}
}
impl<A, B, C> IntoAkitaValue for (A, B, C)
where
A: IntoAkitaValue,
B: IntoAkitaValue,
C: IntoAkitaValue,
{
fn into_value(&self) -> AkitaValue {
AkitaValue::List(vec![
self.0.into_value(),
self.1.into_value(),
self.2.into_value(),
])
}
}
impl<A, B, C, D> FromAkitaValue for (A, B, C, D)
where
A: FromAkitaValue,
B: FromAkitaValue,
C: FromAkitaValue,
D: FromAkitaValue,
{
fn from_value_opt(value: &AkitaValue) -> Result<Self, AkitaDataError> {
match value {
AkitaValue::List(elements) if elements.len() == 4 => {
Ok((
A::from_value_opt(&elements[0])?,
B::from_value_opt(&elements[1])?,
C::from_value_opt(&elements[2])?,
D::from_value_opt(&elements[3])?,
))
}
_ => Err(AkitaDataError::ConversionError(ConversionError::ConversionError {
message: format!("Cannot convert {:?} to 4-tuple", value)
})),
}
}
}
impl<A, B, C, D> IntoAkitaValue for (A, B, C, D)
where
A: IntoAkitaValue,
B: IntoAkitaValue,
C: IntoAkitaValue,
D: IntoAkitaValue,
{
fn into_value(&self) -> AkitaValue {
AkitaValue::List(vec![
self.0.into_value(),
self.1.into_value(),
self.2.into_value(),
self.3.into_value(),
])
}
}