#[cfg(feature = "json-schema")]
pub mod json_schema;
#[cfg(feature = "openapi")]
pub mod openapi;
#[cfg(feature = "graphql")]
pub mod graphql;
#[cfg(feature = "protobuf")]
pub mod protobuf;
#[cfg(feature = "typescript")]
pub mod typescript;
#[cfg(feature = "avro")]
pub mod avro;
pub mod format_ids {
pub const JSON_SCHEMA: &str = "json-schema";
pub const OPENAPI: &str = "openapi";
pub const GRAPHQL: &str = "graphql";
pub const PROTOBUF: &str = "protobuf";
pub const TYPESCRIPT: &str = "typescript";
pub const AVRO: &str = "avro";
}
pub mod utils {
use crate::types::{PrimitiveType, SchemaType};
pub fn type_description(schema_type: &SchemaType) -> String {
match schema_type {
SchemaType::Primitive(p) => primitive_description(p),
SchemaType::Option(inner) => format!("Optional {}", type_description(inner)),
SchemaType::Array(inner) => format!("Array of {}", type_description(inner)),
SchemaType::Set(inner) => format!("Set of {}", type_description(inner)),
SchemaType::Map(inner) => format!("Map with {} values", type_description(inner)),
SchemaType::Tuple(types) => {
let inner: Vec<_> = types.iter().map(|t| type_description(t)).collect();
format!("Tuple of ({})", inner.join(", "))
}
SchemaType::Struct(_) => "Object".to_string(),
SchemaType::Enum(_) => "Enum".to_string(),
SchemaType::Newtype(n) => type_description(&n.inner_type),
SchemaType::Reference(name) => name.clone(),
SchemaType::Unit => "Unit".to_string(),
SchemaType::Any => "Any".to_string(),
}
}
fn primitive_description(p: &PrimitiveType) -> String {
match p {
PrimitiveType::Bool => "Boolean".to_string(),
PrimitiveType::I8 => "8-bit signed integer".to_string(),
PrimitiveType::I16 => "16-bit signed integer".to_string(),
PrimitiveType::I32 => "32-bit signed integer".to_string(),
PrimitiveType::I64 => "64-bit signed integer".to_string(),
PrimitiveType::I128 => "128-bit signed integer".to_string(),
PrimitiveType::Isize => "Pointer-sized signed integer".to_string(),
PrimitiveType::U8 => "8-bit unsigned integer".to_string(),
PrimitiveType::U16 => "16-bit unsigned integer".to_string(),
PrimitiveType::U32 => "32-bit unsigned integer".to_string(),
PrimitiveType::U64 => "64-bit unsigned integer".to_string(),
PrimitiveType::U128 => "128-bit unsigned integer".to_string(),
PrimitiveType::Usize => "Pointer-sized unsigned integer".to_string(),
PrimitiveType::F32 => "32-bit floating point".to_string(),
PrimitiveType::F64 => "64-bit floating point".to_string(),
PrimitiveType::Char => "Unicode character".to_string(),
PrimitiveType::String => "String".to_string(),
PrimitiveType::Bytes => "Binary data".to_string(),
}
}
pub fn escape_string(s: &str) -> String {
s.replace('\\', "\\\\")
.replace('"', "\\\"")
.replace('\n', "\\n")
.replace('\r', "\\r")
.replace('\t', "\\t")
}
pub fn sanitize_identifier(name: &str, format: &str) -> String {
let sanitized: String = name
.chars()
.map(|c| if c.is_alphanumeric() || c == '_' { c } else { '_' })
.collect();
if sanitized.starts_with(|c: char| c.is_ascii_digit()) {
format!("_{}", sanitized)
} else {
match format {
"protobuf" => {
if is_protobuf_reserved(&sanitized) {
format!("{}_", sanitized)
} else {
sanitized
}
}
"typescript" => {
if is_typescript_reserved(&sanitized) {
format!("{}_", sanitized)
} else {
sanitized
}
}
"graphql" => {
let mut chars = sanitized.chars();
match chars.next() {
Some(first) => first.to_uppercase().chain(chars).collect(),
None => sanitized,
}
}
_ => sanitized,
}
}
}
fn is_protobuf_reserved(name: &str) -> bool {
matches!(
name,
"syntax" | "import" | "package" | "option" | "message" | "enum" | "service" | "rpc"
| "returns" | "repeated" | "optional" | "required" | "map" | "oneof" | "reserved"
| "extensions" | "extend" | "group" | "true" | "false"
)
}
fn is_typescript_reserved(name: &str) -> bool {
matches!(
name,
"break" | "case" | "catch" | "class" | "const" | "continue" | "debugger" | "default"
| "delete" | "do" | "else" | "enum" | "export" | "extends" | "false" | "finally"
| "for" | "function" | "if" | "import" | "in" | "instanceof" | "new" | "null"
| "return" | "super" | "switch" | "this" | "throw" | "true" | "try" | "typeof"
| "var" | "void" | "while" | "with" | "yield" | "let" | "static" | "implements"
| "interface" | "package" | "private" | "protected" | "public" | "any" | "boolean"
| "number" | "string" | "symbol" | "type" | "from" | "of" | "namespace" | "module"
| "declare" | "abstract" | "as" | "async" | "await" | "constructor" | "get"
| "set" | "require"
)
}
}