NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #239 most downloaded on crates.io
Convert strings into any case
Last release 1 months ago
27 Aug 2026
Release timing varies
gaps range from 2 weeks to 2.3 years
Some releases are documented
notes for 8 of 14 stable releases
1 version withdrawn
withdrawn after publishing
6 years old
15 releases · first in 2020
One column per quarter.
Version 0.12.0, add changelog file
Version 0.12.0, add changelog file
This release improves speed and memory efficiency. A couple techniques were used:
split method.split. Built-in boundaries get a custom implementation built on top of this bitmask.| Benchmark | Before | After | Improvement |
|---|---|---|---|
snake_short ("hello_world") |
412 ns | 21.3 ns | −95% |
lower_upper ("lowerUpperUpper") |
1,631 ns | 475 ns | −71% |
acronym ("XMLRequest") |
1,108 ns | 418 ns | −62% |
camel_set ("getTotalLength3D") |
3,844 ns | 643 ns | −83% |
defaults_mixed (9 boundaries) |
8,083 ns | 1,500 ns | −81% |
defaults_long_snake (265 chars) |
52,281 ns | 4,730 ns | −91% |
unicode_cyrillic ("ПЕРСПЕКТИВА24") |
8,334 ns | 741 ns | −91% |
Full pipeline from_to_all (4 words x 14 x 14) |
1,230 µs | 263 µs | −79% |
Improve changelog, simplify Converter::convert implementation
Improve changelog, simplify Converter::convert implementation
The headline change permits trailing, leading, and duplicate delimiters to persist (default) or be removed. Instead of applying a single pattern, Converter supports multiple patterns and will apply them in order. This comes with another pattern Pattern::RemoveEmpty that drops empty words. This allows for opting into what was default behavior in 0.8.0 and before.
New features:
Converter now supports multiple patterns via Converter.patterns: Vec<Pattern>. Patterns are applied in sequence, allowing for composition.Pattern::RemoveEmpty filters out empty words. This is useful when splitting produces empty words from leading, trailing, or duplicate delimiters (e.g., "--a--b" split on hyphens).Casing::remove_empty() is a convenience method that adds Pattern::RemoveEmpty to the patterns vector."--leading-delims".remove_empty().to_case(Case::Camel)
// "leadingDelims"
Breaking changes:
delim_boundary macro is now separatorCasing::is_case. Similar functionality is now implemented in convert-case-extras.delim have been renamed to delimiter:
Converter.delim -> Converter.delimiterConverter::set_delim -> Converter::set_delimiterCase::Custom.delim -> Case::Custom.delimiterCase::delim -> Case::delimiterConverter.pattern is now Converter.patterns with type Vec<Pattern>
Converter just like boundaries: set_patterns, add_pattern, add_patterns, remove_pattern, remove_patterns.Pattern::Noop removed. An empty patterns vector represents no mutation.Boundary::Custom and Pattern::Custom variants are no longer comparable.
PartialEq, Eq, and Hash are no longer derived on Boundary and Pattern, and have been manually implemented.false for equality checks because function pointers cannot be reliably compared. This has been true for all of rust, but the compiler warning is relatively new to the author. This means remove_boundary and remove_pattern will not work for custom variants.Custom variants now hash to the same value.Other changes:
rstest.Since the library is so extensible with its new API, there is no longer a need for some niche or fun transformations to be made available in this libr
Since the library is so extensible with its new API, there is no longer a need for some niche or fun transformations to be made available in this library. Some of the features that are removed are now in a new library convert_case_extras. That library will have a lower threshold on what is included (i.e. more features), and will also serve as a demonstration of what's capable with the convert_case API.
Removed:
Case::Toggle and Pattern::ToggleCase::Alternating and Pattern::AlternatingCase::Random and Pattern::RandomCase::PseudoRandom and Pattern::PseudoRandomrandom feature is removed. The library no longer has any features.Case::deterministic_cases is removedCase::random_cases is removedOther breaking changes:
Boundary::Custom has lost the arg parameter and Boundary::Custom.condition is more simply fn(&[&str]) -> bool.
arg was originally used for building boundaries from delimiters with the Boundary::from_delim function, which is also removed becausedelim_boundary! macro has replaced Boundary::from_delim functionality, without the need of the arg parametersCasing::with_boundaries is now Casing::set_boundaries and Casing::without_boundaries is now Casing::remove_boundaries to align with ConverterThis release is trying to finalize the API for a 1.0.0 release. In hindsight, making Pattern a function and Boundary a struct were poor decisions. Whi
This release is trying to finalize the API for a 1.0.0 release. In hindsight, making Pattern a function and Boundary a struct were poor decisions. While trying to add customized behavior, I made it harder to use. Luckily, by following the convention that was done with Case in 0.8.0, which was providing a struct-variant Case::Custom, I can keep the new customization options while reverting back to the enum pattern the library has had since the beginning.
If you are updating from before 0.7.0, I don't think any changes are necessary. If you're coming from 0.7.0 or higher,
Boundary::UPPER_SNAKE into Boundary::UpperSnakePattern: pattern::lowercase into Pattern::LowercaseMost excitingly, I've introduced a brand new way to use the crate for 99% of use cases, which is the default behavior out of the box to just convert a string to a case, with no modifications to behavior. Instead of
use convert_case::{Case, Casing};
"MyVarName".to_case(Case::Snake);
"my-var name".from_case(Case::Title).to_case(Case::Snake);
You can use the ccase! macro:
use convert_case::ccase;
ccase!(snake, "MyVarName");
ccase!(title -> snake, "my-var name");
This means only one import and its invocation is brief and easy to read. This is now the first thing you see when viewing the docs, which themselves have gotten a huge overhaul and many improvements in this version.
New features:
ccase! macro that performs case conversion on a string without needing to import Case or Casing. It has two forms:
ccase!(snake, "string") is equivalent to "string".to_case(Case::Snake)ccase!(kebab -> snake, "string") is equivalent to "string".from_case(Case::Kebab).to_case(Case::Snake)case! macro returns a Case variant from the snake case version of the variant. For instance, case!(snake) is substituted for Case::Snake and case!(upper_flat) for Case::UpperFlat.Other breaking changes:
Boundary is reverted back to being an enum, but with a Custom variant that gives all the same flexibility that Boundary had as a struct. This aligns with the Case::Custom pattern.
Boundary.match will return true if a set of graphemes matches the boundary conditionBoundary methods for start and len describe how enum variants consume letters when matchedPattern is reverted back to being an enum, but with a Custom variant that allowed you to pass your own fn (&[&str]) -> Vec<String> as input.
Pattern.mutate will perform the associated mutation functionConverter.with_boundaries has been renamed to Converter.set_boundaries.Converter.remove_delim and Converter.remove_pattern. You can use set_delim("") and set_pattern(Pattern::Noop) instead.ToString is no longer a required trait for using is_caseword_pattern module has been removedPattern is no longer an enum. It is now a type alias for fn(&[&str]) -> Vec . The variants of Pattern can now be referenced as functions inside the pa
Pattern is no longer an enum. It is now a type alias for fn(&[&str]) -> Vec<String>. The variants of Pattern can now be referenced as functions inside the pattern module. For upgrading this means changing Pattern::Lowercase to pattern::lowercase, and calling the function directly instead of invoking the mutate method on the enum.
Inside the pattern module is also the type alias Pattern itself.
Other breaking changes:
Case::Ada (capital pattern with underscore delimiter.)Case::Custom variant. It is a struct variant that takes three parameters:
Pattern&static str, and&'static [Boundary].pattern::noop function, Converter attribute pattern is now of type Pattern and not Option<Pattern>Case::deterministic_cases, Case::all_cases, and Case::random_cases now return static arrays instead of vecsOther changes:
Case::split, Case::mutate, and Case::join which expose operations related to the boundaries, pattern, and delimiter of a caseno_std compatibleRemove debug statements for 0.7.1
Remove debug statements for 0.7.1
Boundary is no longer an enum. It now is a struct, and each enum variant corresponds to an associated constant. For upgrading this just means changing
Boundary is no longer an enum. It now is a struct, and each enum variant corresponds to an associated constant. For upgrading this just means changing Boundary::LowerUpper to just Boundary::LOWER_UPPER.
The benefit of this is that you can make your boundary conditions now, by instantiating the Boundary struct, or using Boundary::from_delim(). Now you can split on newlines, periods, double-colons, emojis, or a more complex case like a symbol followed by a digit. You also define which characters, if any, are removed during segmentation, and where the split happens.
Changes from this feature:
Boundary::PascalName enum variants now much referred to as Boundary::CONSTANT_NAME constants.Boundary::defaults(), Boundary::digit_letter(), etc) now are const and return fixed-sized arrays [Boundary; N], not Vec<Boundary>.Boundary::all() was removed, since there's no longer a sense of "all" boundaries, since you can create your own.Boundary::list_from() has been renamed to Boundary::defaults_from() and no longer outputs Boundary::UPPER_LOWER, since this function now only checks default boundaries.Boundary::from_delim().Other breaking changes:
Case::ScreamingSnake to Case::Constant.Case::Sentence (sentence pattern and space delimiter.)Casing trait implemented for Arc<str> and Rc<str> again.Other changes:
str::chars in favor of graphemes from unicode-segmentation.Update docs and version number
Update docs and version number
Nothing published for this version
Fix repo and docs links
Fix repo and docs links
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →