use std::{
collections::{BTreeMap, HashMap},
str::FromStr,
};
use serde::{Deserialize, Serialize};
use crate::internal::error::{fail, Error, Result};
pub const STRATEGY_KEY: &str = "SERDE_ARROW:strategy";
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(into = "String", try_from = "String")]
#[non_exhaustive]
pub enum Strategy {
InconsistentTypes,
TupleAsStruct,
MapAsStruct,
UnknownVariant,
}
impl std::fmt::Display for Strategy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InconsistentTypes => write!(f, "InconsistentTypes"),
Self::TupleAsStruct => write!(f, "TupleAsStruct"),
Self::MapAsStruct => write!(f, "MapAsStruct"),
Self::UnknownVariant => write!(f, "UnknownVariant"),
}
}
}
impl From<Strategy> for String {
fn from(strategy: Strategy) -> String {
strategy.to_string()
}
}
impl TryFrom<String> for Strategy {
type Error = Error;
fn try_from(s: String) -> Result<Strategy> {
s.parse()
}
}
impl FromStr for Strategy {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"InconsistentTypes" => Ok(Self::InconsistentTypes),
"TupleAsStruct" => Ok(Self::TupleAsStruct),
"MapAsStruct" => Ok(Self::MapAsStruct),
"UnknownVariant" => Ok(Self::UnknownVariant),
_ => fail!("Unknown strategy {s}"),
}
}
}
impl From<Strategy> for BTreeMap<String, String> {
fn from(value: Strategy) -> Self {
let mut res = BTreeMap::new();
res.insert(STRATEGY_KEY.to_string(), value.to_string());
res
}
}
impl From<Strategy> for HashMap<String, String> {
fn from(value: Strategy) -> Self {
let mut res = HashMap::new();
res.insert(STRATEGY_KEY.to_string(), value.to_string());
res
}
}
pub fn get_strategy_from_metadata(metadata: &HashMap<String, String>) -> Result<Option<Strategy>> {
let Some(strategy) = metadata.get(STRATEGY_KEY) else {
return Ok(None);
};
Ok(Some(strategy.parse()?))
}