use std::{
any::{type_name, Any},
sync::Arc,
};
pub use p3_air::BaseAirWithPublicValues;
use p3_air::{Air, BaseAir};
use crate::{
air_builders::{debug::DebugConstraintBuilder, symbolic::SymbolicRapBuilder},
config::StarkProtocolConfig,
};
pub trait PartitionedBaseAir<F>: BaseAir<F> {
fn cached_main_widths(&self) -> Vec<usize> {
vec![]
}
fn common_main_width(&self) -> usize {
self.width()
}
}
pub type AirRef<SC> = Arc<dyn AnyAir<SC>>;
pub trait AnyAir<SC: StarkProtocolConfig>:
Air<SymbolicRapBuilder<SC::F>> + for<'a> Air<DebugConstraintBuilder<'a, SC>> + BaseAirWithPublicValues<SC::F>
+ PartitionedBaseAir<SC::F>
+ Send + Sync
{
fn as_any(&self) -> &dyn Any;
fn name(&self) -> String;
}
impl<SC, T> AnyAir<SC> for T
where
SC: StarkProtocolConfig,
T: Air<SymbolicRapBuilder<SC::F>>
+ for<'a> Air<DebugConstraintBuilder<'a, SC>>
+ BaseAirWithPublicValues<SC::F>
+ PartitionedBaseAir<SC::F>
+ Send
+ Sync
+ 'static,
{
fn as_any(&self) -> &dyn Any {
self
}
fn name(&self) -> String {
get_air_name(self)
}
}
pub fn get_air_name<T>(_rap: &T) -> String {
let full_name = type_name::<T>().to_string();
if let Some((main_part, generics_part)) = full_name.split_once('<') {
let main_type = main_part.split("::").last().unwrap_or("");
let generics: Vec<String> = generics_part
.trim_end_matches('>')
.split(", ")
.map(|generic| {
generic.split("::").last().unwrap_or("").to_string()
})
.collect();
format!("{}<{}>", main_type, generics.join(", "))
} else {
full_name.split("::").last().unwrap_or("").to_string()
}
}