serverkit 0.5.5

A portable Rust HTTP application layer for Workers and native servers
Documentation
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Case {
    Lower,
    Upper,
    Camel,
    Pascal,
    Snake,
    ScreamingSnake,
    Kebab,
    ScreamingKebab,
}

impl Case {
    const fn index(self) -> usize {
        match self {
            Self::Lower => 0,
            Self::Upper => 1,
            Self::Camel => 2,
            Self::Pascal => 3,
            Self::Snake => 4,
            Self::ScreamingSnake => 5,
            Self::Kebab => 6,
            Self::ScreamingKebab => 7,
        }
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JsonName {
    serialize: &'static str,
    deserialize: &'static str,
    serialize_uses_config: bool,
    deserialize_uses_config: bool,
    configured: [&'static str; 8],
}

impl JsonName {
    pub const fn new(
        serialize: &'static str,
        deserialize: &'static str,
        serialize_uses_config: bool,
        deserialize_uses_config: bool,
        configured: [&'static str; 8],
    ) -> Self {
        Self {
            serialize,
            deserialize,
            serialize_uses_config,
            deserialize_uses_config,
            configured,
        }
    }

    pub(crate) fn serialize(&self, case: Option<Case>) -> &'static str {
        match case.filter(|_| self.serialize_uses_config) {
            Some(case) => self.configured[case.index()],
            None => self.serialize,
        }
    }

    #[cfg(feature = "json")]
    pub(crate) fn deserialize(&self, case: Option<Case>) -> &'static str {
        match case.filter(|_| self.deserialize_uses_config) {
            Some(case) => self.configured[case.index()],
            None => self.deserialize,
        }
    }

    #[cfg(feature = "json")]
    pub(crate) const fn serde_deserialize(&self) -> &'static str {
        self.deserialize
    }

    #[cfg(feature = "json")]
    pub(crate) const fn serde_serialize(&self) -> &'static str {
        self.serialize
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, PartialEq)]
pub struct JsonField {
    name: JsonName,
    shape: JsonShape,
}

impl JsonField {
    pub fn new(name: JsonName, shape: JsonShape) -> Self {
        Self { name, shape }
    }

    #[cfg(feature = "json")]
    pub(crate) fn name(&self) -> &JsonName {
        &self.name
    }

    #[cfg(feature = "json")]
    pub(crate) fn shape(&self) -> &JsonShape {
        &self.shape
    }

    #[cfg(feature = "json")]
    pub(crate) fn serialize_name(&self, case: Case) -> &'static str {
        self.name.serialize(Some(case))
    }

    #[cfg(feature = "json")]
    pub(crate) fn deserialize_name(&self, case: Case) -> &'static str {
        self.name.deserialize(Some(case))
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, PartialEq)]
pub struct JsonVariant {
    name: JsonName,
    shape: JsonShape,
}

impl JsonVariant {
    pub fn new(name: JsonName, shape: JsonShape) -> Self {
        Self { name, shape }
    }

    #[cfg(feature = "json")]
    pub(crate) fn name(&self) -> &JsonName {
        &self.name
    }

    #[cfg(feature = "json")]
    pub(crate) fn shape(&self) -> &JsonShape {
        &self.shape
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, PartialEq)]
pub struct JsonShape(JsonShapeKind);

#[derive(Debug, Clone, PartialEq)]
enum JsonShapeKind {
    Value,
    Object(Vec<JsonField>),
    Array(Box<JsonShape>),
    Enum(Vec<JsonName>),
    Variants(Vec<JsonVariant>),
}

impl JsonShape {
    pub fn value() -> Self {
        Self(JsonShapeKind::Value)
    }

    pub fn object(fields: Vec<JsonField>) -> Self {
        Self(JsonShapeKind::Object(fields))
    }

    pub fn array(items: Self) -> Self {
        Self(JsonShapeKind::Array(Box::new(items)))
    }

    pub fn enumeration(variants: Vec<JsonName>) -> Self {
        Self(JsonShapeKind::Enum(variants))
    }

    pub fn variants(variants: Vec<JsonVariant>) -> Self {
        Self(JsonShapeKind::Variants(variants))
    }

    #[cfg(feature = "json")]
    pub(crate) fn fields(&self) -> Option<&[JsonField]> {
        match &self.0 {
            JsonShapeKind::Object(fields) => Some(fields),
            _ => None,
        }
    }

    #[cfg(feature = "json")]
    pub(crate) fn items(&self) -> Option<&Self> {
        match &self.0 {
            JsonShapeKind::Array(items) => Some(items),
            _ => None,
        }
    }

    #[cfg(feature = "json")]
    pub(crate) fn variant(&self, index: u32) -> Option<&JsonVariant> {
        match &self.0 {
            JsonShapeKind::Variants(variants) => variants.get(index as usize),
            _ => None,
        }
    }

    #[cfg(feature = "json")]
    pub(crate) fn variants_slice(&self) -> Option<&[JsonVariant]> {
        match &self.0 {
            JsonShapeKind::Variants(variants) => Some(variants),
            _ => None,
        }
    }

    pub(crate) fn decorate(&self, metadata: &mut crate::SchemaMetadata) {
        match (&self.0, metadata.kind_mut()) {
            (JsonShapeKind::Object(json_fields), crate::SchemaKind::Object(schema_fields)) => {
                for (json, schema) in json_fields.iter().zip(schema_fields) {
                    schema.set_json_name(json.name.clone());
                    json.shape.decorate(schema.schema_mut());
                }
            }
            (JsonShapeKind::Array(json_items), crate::SchemaKind::Array(schema_items)) => {
                json_items.decorate(schema_items);
            }
            (JsonShapeKind::Enum(json_variants), crate::SchemaKind::Enum(_)) => {
                metadata.set_json_variants(json_variants.clone());
            }
            (JsonShapeKind::Variants(json_variants), crate::SchemaKind::OneOf(schemas)) => {
                for (json, schema) in json_variants.iter().zip(schemas) {
                    schema.set_json_variant(json.name.clone());
                    json.shape.decorate(schema);
                }
            }
            _ => {}
        }
    }
}