Skip to content

string_value of DeriveActiveEnum errors on underscores, spaces and Non-Unicode UAX#31 chars #1373

@denwong47

Description

@denwong47

Description

This Issue accompanies a PR that fixes it. PR Link to follow in comments below.

When using DeriveActiveEnum, struct ActiveEnum will try to reformat the string_value into an identifier for an Enum. Its does this by:

  • if string_value starts with a number, prepend it with an underscore;
  • otherwise, camel_case it.

This causes a few problems:

  • the identifier will be an empty string if
    • string_value is an empty string, or
    • contains only non-XID_Start/XID_Continue characters, e.g. "$" or multiples of them
    • contains only characters that camel_case will remove: e.g. "_" or " "
  • two string_value s that differ only by the above characters will become conflicting identifiers:
    • string_value of "fooBar" and "foo_bar" in the same enum will result conflicting identifiers of FooBar.
  • if string_value leads with a digit, camel_case will NOT be applied, hence string_value = "0spaced word" will cause an error.

Steps to Reproduce

Scenario 1 - non-empty string_value results in empty identifier

use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(
    rs_type = "String",
    db_type = "String(None)",
    enum_name = "conflicting_string_values"
)]
pub enum ConflictingStringValues {
    #[sea_orm(string_value = "$")]
    Member1,
}

Scenario 2 - distinct string_value s result in conflict

use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(
    rs_type = "String",
    db_type = "String(None)",
    enum_name = "conflicting_string_values"
)]
pub enum ConflictingStringValues {
    #[sea_orm(string_value = "aB")]
    Member1,
    #[sea_orm(string_value = "a_b")]
    Member2,
}

Scenario 3 - string_value with leading numeric and includes spaces

use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(
    rs_type = "String",
    db_type = "String(None)",
    enum_name = "conflicting_string_values"
)]
pub enum ConflictingStringValues {
    #[sea_orm(string_value = "0 123")]
    Member1,
}

Expected Behavior

Compiles successfully with an Member1 matching string_value mapped.

Actual Behavior

Scenario 1

proc_macro panicked:
message: "" is not a valid identifier

Scenario 2

error[E0428]:
the name AB is defined multiple times

Scenario 3

proc_macro panicked:
message: "_0 123" is not a valid identifier

Reproduces How Often

Always reproducible.

Versions

sea-orm-macros 0.10.3

Additional Information

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions