Skip to content

Commit

Permalink
feat(rpc/generator): automatically remove enum prefix/suffixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nils-mathieu committed Oct 24, 2023
1 parent 21c1f17 commit 068b98d
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
7 changes: 7 additions & 0 deletions crates/starknet-types-rpc/generator/example-fixes.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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"
84 changes: 82 additions & 2 deletions crates/starknet-types-rpc/generator/src/openrpc/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<model::Schema>) -> Vec<EnumVariant> {
let variants: Vec<_> = vars
let mut variants: Vec<_> = vars
.into_iter()
.map(|s| {
// Find an appropriate name for the enum variant.
Expand Down Expand Up @@ -266,6 +266,8 @@ fn parse_enum_variants(ctx: &mut ParsingContext, vars: Vec<model::Schema>) -> Ve
})
.collect();

fix_enum_names(&mut variants);

variants
}

Expand Down Expand Up @@ -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);
Expand All @@ -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]+$" {
Expand All @@ -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<Item = &'a str>) -> usize {
let first = words.clone().next().unwrap_or("");

let mut prefix = 0;
while prefix < first.len() {
let mut prev: Option<char> = 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<Item = &'a str>) -> usize {
let first = words.clone().next().unwrap_or("");

let mut suffix = 0;
while suffix < first.len() {
let mut prev: Option<char> = 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
}

0 comments on commit 068b98d

Please sign in to comment.