diff --git a/crates/starknet-types-rpc/generator/example-fixes.toml b/crates/starknet-types-rpc/generator/example-fixes.toml index 10f7852..57c9981 100644 --- a/crates/starknet-types-rpc/generator/example-fixes.toml +++ b/crates/starknet-types-rpc/generator/example-fixes.toml @@ -5,6 +5,9 @@ removed-symbols = [ "#/components/schemas/DECLARE_TXN_V0/DECLARE_TXN_V0/version", "#/components/schemas/DECLARE_TXN_V1/DECLARE_TXN_V1/version", "#/components/schemas/DECLARE_TXN_V2/DECLARE_TXN_V2/version", + + # Duplicates + "#/methods/starknet_getClassAt/result/ANONYMOUS", ] [tagged-enums] @@ -13,3 +16,7 @@ removed-symbols = [ [renamed-symbols] # Anonymous Structs "#/components/schemas/BLOCK_BODY_WITH_TXS/transactions/ANONYMOUS/ANONYMOUS" = "TxnWithHash" + +# Enums +"#/methods/starknet_getClass/result/ANONYMOUS/ContractClass" = "ContractClass" +"#/methods/starknet_getClass/result/ANONYMOUS/DeprecatedContractClass" = "Deprecated" diff --git a/crates/starknet-types-rpc/generator/src/openrpc/parse.rs b/crates/starknet-types-rpc/generator/src/openrpc/parse.rs index 0c8d8a5..892e361 100644 --- a/crates/starknet-types-rpc/generator/src/openrpc/parse.rs +++ b/crates/starknet-types-rpc/generator/src/openrpc/parse.rs @@ -237,7 +237,7 @@ fn parse_type(ctx: &mut ParsingContext, name: &str, schema: model::Schema) -> Ty /// Parses the variants of an enum. fn parse_enum_variants(ctx: &mut ParsingContext, vars: Vec) -> Vec { - let variants: Vec<_> = vars + let mut variants: Vec<_> = vars .into_iter() .map(|s| { // Find an appropriate name for the enum variant. @@ -266,6 +266,8 @@ fn parse_enum_variants(ctx: &mut ParsingContext, vars: Vec) -> Ve }) .collect(); + fix_enum_names(&mut variants); + variants } @@ -341,7 +343,7 @@ fn parse_flatten_struct( /// Parses a set of constraints for a JSON string to turn it into a string definition. fn parse_string_constraints(ctx: &mut ParsingContext, c: model::StringConstraints) -> TypeKind { if let Some(e) = c.enumeration { - let variants: Vec<_> = e + let mut variants: Vec<_> = e .into_iter() .map(|s| { ctx.push_level(&s); @@ -357,6 +359,8 @@ fn parse_string_constraints(ctx: &mut ParsingContext, c: model::StringConstraint }) .collect(); + fix_enum_names(&mut variants); + TypeKind::Enum(variants) } else if let Some(format) = c.format { if &*format == "^0x[a-fA-F0-9]+$" { @@ -371,3 +375,79 @@ fn parse_string_constraints(ctx: &mut ParsingContext, c: model::StringConstraint TypeKind::Newtype(TypeRef::String) } } + +/// Fixes the names of the provided enum variants, removing an eventual common prefix and suffix. +fn fix_enum_names(variants: &mut [EnumVariant]) { + let common_prefix = common_prefix(variants.iter().map(|v| v.name.as_str())); + let common_suffix = common_suffix(variants.iter().map(|v| v.name.as_str())); + + for variant in variants { + variant.name = variant.name[common_prefix..variant.name.len() - common_suffix].into(); + } +} + +/// Identifies a common prefix among the provided strings. +/// +/// Prefixes are computed on a word-boundary. +/// +/// The size of the prefix is returned. +fn common_prefix<'a>(words: impl Clone + Iterator) -> usize { + let first = words.clone().next().unwrap_or(""); + + let mut prefix = 0; + while prefix < first.len() { + let mut prev: Option = None; + let prev_prefix = prefix; + for c in first[prefix..].chars() { + match (prev, c) { + (Some(prev), c) if !prev.is_uppercase() && c.is_uppercase() => { + break; + } + (_, c) => prev = Some(c), + } + prefix += c.len_utf8(); + } + + for word in words.clone() { + if !word.starts_with(&first[..prefix]) { + return prev_prefix; + } + } + } + + // All of them are equal? Don't find any prefix. + 0 +} + +/// Identifies a common suffix among the provided strings. +/// +/// Suffixes are computed on a word-boundary. +/// +/// The length of the suffix is returned. +fn common_suffix<'a>(words: impl Clone + Iterator) -> usize { + let first = words.clone().next().unwrap_or(""); + + let mut suffix = 0; + while suffix < first.len() { + let mut prev: Option = None; + let prev_suffix = suffix; + for c in first[..first.len() - suffix].chars().rev() { + match (prev, c) { + (Some(prev), c) if !c.is_uppercase() && prev.is_uppercase() => { + break; + } + (_, c) => prev = Some(c), + } + suffix += c.len_utf8(); + } + + for word in words.clone() { + if !word.ends_with(&first[first.len() - suffix..]) { + return prev_suffix; + } + } + } + + // All of them are equal? Don't find any suffix. + 0 +}