#[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);
}
}
_ => {}
}
}
}