Skip to main content
The bomboni_core crate provides internal utilities and abstractions used throughout the Bomboni library. This crate is primarily used by other Bomboni crates and procedural macros.

String Utilities

The string module provides utilities for string case conversion.

str_to_case

Converts a string to the specified case format.
str_to_case
fn(s: impl AsRef<str>, case: Case) -> String
Converts a string to the specified case using smart boundary detection.Parameters:
  • s - The input string to convert
  • case - The target case format from convert_case::Case
Returns: The converted string
use bomboni_core::string::{str_to_case, Case};

let result = str_to_case("hello_world", Case::Pascal);
assert_eq!(result, "HelloWorld");

let result = str_to_case("HelloWorld", Case::Snake);
assert_eq!(result, "hello_world");

let result = str_to_case("some-kebab-case", Case::Camel);
assert_eq!(result, "someKebabCase");

Case Enum

The Case enum is re-exported from the convert_case crate and supports various case formats:
pub use convert_case::Case;
Available case formats include:
  • Case::Upper - UPPERCASE
  • Case::Lower - lowercase
  • Case::Title - Title Case
  • Case::Camel - camelCase
  • Case::Pascal - PascalCase
  • Case::Snake - snake_case
  • Case::UpperSnake - UPPER_SNAKE_CASE
  • Case::Kebab - kebab-case
  • Case::Cobol - COBOL-CASE
  • Case::Train - Train-Case
  • Case::Flat - flatcase
  • Case::UpperFlat - UPPERFLATCASE
And more. See the convert_case documentation for all available formats.

Syntax Tree Utilities

The syn module provides utilities for working with Rust syntax trees in procedural macros.

format_comment!

Macro for formatting documentation comments in procedural macros.
use bomboni_core::format_comment;

// In a procedural macro
let doc = format_comment!("This is a {} comment", "formatted");
// Produces: #[doc = " This is a formatted comment"]

type_is_phantom

Checks if a type is PhantomData.
type_is_phantom
fn(ty: &Type) -> bool
Returns true if the given type is std::marker::PhantomData.Parameters:
  • ty - A reference to a syn::Type to check
Returns: true if the type is PhantomData, false otherwise
use bomboni_core::syn::type_is_phantom;
use syn::parse_quote;

let ty: syn::Type = parse_quote!(PhantomData<T>);
assert!(type_is_phantom(&ty));

let ty: syn::Type = parse_quote!(String);
assert!(!type_is_phantom(&ty));

type_is_option

Checks if a type is Option.
type_is_option
fn(ty: &Type) -> bool
Returns true if the given type is std::option::Option.Parameters:
  • ty - A reference to a syn::Type to check
Returns: true if the type is Option, false otherwise
use bomboni_core::syn::type_is_option;
use syn::parse_quote;

let ty: syn::Type = parse_quote!(Option<String>);
assert!(type_is_option(&ty));

let ty: syn::Type = parse_quote!(Vec<String>);
assert!(!type_is_option(&ty));

Usage in Procedural Macros

The bomboni_core crate is primarily designed for use in procedural macros within the Bomboni ecosystem. Here’s an example of how these utilities might be used:
use bomboni_core::{format_comment, syn::{type_is_option, type_is_phantom}};
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Data, DeriveInput, Fields};

fn generate_code(input: DeriveInput) -> TokenStream {
    let struct_name = &input.ident;
    
    if let Data::Struct(data) = &input.data {
        if let Fields::Named(fields) = &data.fields {
            let field_checks: Vec<_> = fields.named.iter().map(|f| {
                let field_name = &f.ident;
                let field_type = &f.ty;
                
                if type_is_phantom(field_type) {
                    // Skip PhantomData fields
                    quote! {}
                } else if type_is_option(field_type) {
                    // Handle Option fields specially
                    quote! {
                        if let Some(val) = &self.#field_name {
                            // process optional value
                        }
                    }
                } else {
                    // Handle regular fields
                    quote! {
                        // process field
                    }
                }
            }).collect();
            
            let doc = format_comment!("Generated code for {}", struct_name);
            
            quote! {
                #doc
                impl #struct_name {
                    #(#field_checks)*
                }
            }
        } else {
            quote! {}
        }
    } else {
        quote! {}
    }
}

String Case Conversion Examples

use bomboni_core::string::{str_to_case, Case};

// Snake case to PascalCase
let result = str_to_case("user_profile_data", Case::Pascal);
assert_eq!(result, "UserProfileData");

// PascalCase to snake_case
let result = str_to_case("UserProfileData", Case::Snake);
assert_eq!(result, "user_profile_data");

// Kebab case to camelCase
let result = str_to_case("user-profile-data", Case::Camel);
assert_eq!(result, "userProfileData");

// Mixed format with numbers
let result = str_to_case("API2Response", Case::Snake);
assert_eq!(result, "api2_response");

// Uppercase conversion
let result = str_to_case("hello_world", Case::Upper);
assert_eq!(result, "HELLO WORLD");

Dependencies

The bomboni_core crate depends on:
  • convert_case - For string case conversion
  • syn - For Rust syntax tree manipulation (with full feature)
These dependencies are primarily used for code generation and procedural macro implementation.

Build docs developers (and LLMs) love