hpl-toolkit 0.0.5

HPL toolkit
Documentation
use super::{Number, Schema, SchemaValue, ToSchema};
use crate::utils::VecMap;
use anchor_lang::prelude::*;
use std::collections::HashMap;

macro_rules! impl_to_schema_for_unsigned {
    ($($t:ty)+) => {
        $(
            impl ToSchema for $t {
                fn schema() -> Schema {
                    Schema::Number
                }

                fn schema_value(&self) -> SchemaValue {
                    SchemaValue::Number(Number::U64(self.clone().into()))
                }
            }
        )+
    };
}
impl_to_schema_for_unsigned!(u8 u16 u32 u64);

macro_rules! impl_to_schema_for_signed {
    ($($t:ty)+) => {
        $(
            impl ToSchema for $t {
                fn schema() -> Schema {
                    Schema::Number
                }

                fn schema_value(&self) -> SchemaValue {
                    SchemaValue::Number(Number::I64(self.clone().into()))
                }
            }
        )+
    };
}
impl_to_schema_for_signed!(i8 i16 i32 i64);

macro_rules! impl_to_schema_for_float {
    ($($t:ty)+) => {
        $(
            impl ToSchema for $t {
                fn schema() -> Schema {
                    Schema::Number
                }

                fn schema_value(&self) -> SchemaValue {
                    SchemaValue::Number(Number::F64(self.clone().into()))
                }
            }
        )+
    };
}
impl_to_schema_for_float!(f32 f64);

macro_rules! impl_to_schema_for_array {
    ($($n:literal)+) => {
        $(
            impl<T: ToSchema> ToSchema for [T; $n] {
                fn schema() -> Schema {
                    Schema::Array(Box::new(T::schema()))
                }

                fn schema_value(&self) -> SchemaValue {
                    SchemaValue::Array(self.iter().map(|i| i.schema_value()).collect())
                }
            }
        )+
    };
}
impl_to_schema_for_array!(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32);

impl ToSchema for String {
    fn schema() -> Schema {
        Schema::String
    }

    fn schema_value(&self) -> SchemaValue {
        SchemaValue::String(self.clone().trim_matches(char::from(0)).to_string())
    }
}

impl<T: ToSchema> ToSchema for Vec<T> {
    fn schema() -> Schema {
        Schema::Array(Box::new(T::schema()))
    }

    fn schema_value(&self) -> SchemaValue {
        SchemaValue::Array(self.iter().map(|i| i.schema_value()).collect())
    }
}

impl ToSchema for Pubkey {
    fn schema() -> Schema {
        Schema::Pubkey
    }

    fn schema_value(&self) -> SchemaValue {
        SchemaValue::Pubkey(self.clone())
    }
}

impl ToSchema for bool {
    fn schema() -> Schema {
        Schema::Bool
    }

    fn schema_value(&self) -> SchemaValue {
        SchemaValue::Bool(self.clone())
    }
}

impl<T: ToSchema> ToSchema for Option<T> {
    fn schema() -> Schema {
        Schema::Option(Box::new(T::schema()))
    }

    fn schema_value(&self) -> SchemaValue {
        if self.is_some() {
            self.as_ref().unwrap().schema_value()
        } else {
            SchemaValue::Null
        }
    }
}

impl<K: ToString, V: ToSchema> ToSchema for HashMap<K, V> {
    fn schema() -> Schema {
        Schema::VecMap(Box::new(Schema::String), Box::new(V::schema()))
    }

    fn schema_value(&self) -> SchemaValue {
        let mut schema = VecMap::new();
        self.iter().for_each(|(key, value)| {
            schema.insert(key.to_string().schema_value(), value.schema_value());
        });
        SchemaValue::VecMap(schema)
    }
}

impl ToSchema for Vec<(String, String)> {
    fn schema() -> Schema {
        Schema::Array(Box::new(Schema::Array(Box::new(Schema::String))))
    }

    fn schema_value(&self) -> SchemaValue {
        SchemaValue::Array(
            self.iter()
                .map(|(key, value)| {
                    SchemaValue::Array(vec![
                        SchemaValue::String(key.clone()),
                        SchemaValue::String(value.clone()),
                    ])
                })
                .collect(),
        )
    }
}