use schematic_types::*;
use std::fmt;
const KEYWORDS: [&str; 42] = [
"abstract",
"amends",
"as",
"case",
"class",
"const",
"delete",
"else",
"extends",
"external",
"false",
"fixed",
"for",
"function",
"hidden",
"if",
"import",
"in",
"is",
"let",
"local",
"module",
"new",
"nothing",
"null",
"open",
"out",
"outer",
"override",
"protected",
"read",
"record",
"super",
"switch",
"this",
"throw",
"trace",
"true",
"typealias",
"unknown",
"vararg",
"when",
];
pub fn format_float(value: impl fmt::Debug) -> String {
let value = format!("{value:?}");
match value.as_str() {
"NaN" => value,
"inf" => "Infinity".into(),
"-inf" => "-Infinity".into(),
_ if value.contains(['.', 'e', 'E']) => value,
_ => format!("{value}.0"),
}
}
pub fn quote_string(value: &str) -> String {
let mut out = String::with_capacity(value.len() + 2);
out.push('"');
for ch in value.chars() {
match ch {
'"' => out.push_str("\\\""),
'\\' => out.push_str("\\\\"),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
ch if ch.is_control() => out.push_str(&format!("\\u{{{:x}}}", ch as u32)),
ch => out.push(ch),
};
}
out.push('"');
out
}
pub fn quote_identifier(name: &str) -> String {
let mut chars = name.chars();
let legal = chars
.next()
.is_some_and(|ch| ch.is_alphabetic() || ch == '_' || ch == '$')
&& chars.all(|ch| ch.is_alphanumeric() || ch == '_' || ch == '$')
&& name != "_"
&& !KEYWORDS.contains(&name);
if legal {
name.to_owned()
} else {
format!("`{name}`")
}
}
pub fn unwrap_nullable(schema: &Schema) -> &Schema {
if let SchemaType::Union(uni) = &schema.ty
&& uni.has_null()
{
let mut variants = uni
.variants_types
.iter()
.filter(|variant| !variant.is_null());
if let (Some(variant), None) = (variants.next(), variants.next()) {
return unwrap_nullable(variant);
}
}
schema
}
pub fn is_duration(structure: &StructType) -> bool {
let has_field = |name: &str, kind: IntegerKind| {
structure.fields.get(name).is_some_and(|field| {
matches!(&unwrap_nullable(&field.schema).ty, SchemaType::Integer(integer) if integer.kind == kind)
})
};
structure.fields.len() == 2
&& has_field("secs", IntegerKind::U64)
&& has_field("nanos", IntegerKind::U32)
}