br-fields 2.2.5

This is a shortcut tool related to database fields
Documentation
# AGENTS.md - br-fields

> Database field standardization library for Rust. Generates SQL DDL for SQLite, MySQL, and PostgreSQL.

## Quick Reference

```bash
# Build
cargo build
cargo build --release

# Test
cargo test                           # Run all tests
cargo test str                       # Run tests matching "str"
cargo test int::                     # Run tests in int module
cargo test -- --nocapture            # Show println! output
cargo test <test_name> -- --exact    # Run single test by exact name

# Lint & Format
cargo clippy --all-targets --all-features -- -D warnings
cargo fmt                            # Format code
cargo fmt -- --check                 # Check formatting without changes

# Pre-publish validation
cargo package --list                 # Check package contents
cargo publish --dry-run              # Validate before publishing
```

## Project Structure

```
br-fields/
├── Cargo.toml          # Package manifest (edition 2021)
├── src/
│   ├── lib.rs          # Main: Field trait, FieldMode enum, field() & verify()
│   ├── str.rs          # String types: Str, Pass, Key, Tel, Email, Code, BarCode, QrCode, Ident, Color
│   ├── int.rs          # Integer types: Int, Switch
│   ├── float.rs        # Float type
│   ├── text.rs         # Text types: Text, Editor, Json, Array, Object, Url
│   ├── datetime.rs     # DateTime types: Year, Datetime, Time, Date, Timestamp
│   ├── select.rs       # Selection types: Radio, Select
│   ├── dict.rs         # Dictionary reference type
│   ├── files.rs        # File attachment type
│   ├── location.rs     # Geolocation type
│   └── table.rs        # Table reference types: Table, Tree
└── tests/
    └── test.rs         # Integration tests
```

## Code Style Guidelines

### Imports
```rust
// Standard library first (if any)
use std::sync::atomic::{AtomicU16, Ordering};

// External crates
use chrono::{DateTime, Local};
use json::{object, JsonValue};
use lazy_static::lazy_static;
use regex::Regex;

// Internal crate imports
use crate::Field;
use crate::datetime::Datetime;
```

### Naming Conventions
- **Structs**: PascalCase (`BarCode`, `Timestamp`, `JsonValue`)
- **Functions/Methods**: snake_case (`timestamp_to_datetime`, `random_pass`)
- **Fields**: snake_case (`field`, `require`, `def`, `mode`)
- **Modules**: snake_case (`datetime`, `select`, `str`)
- **Constants**: SCREAMING_SNAKE_CASE (`SEQ`, `CN_RE`)

### Struct Definition Pattern
```rust
/// Chinese description of the struct
///
/// * field_name description
/// * another_field description
#[derive(Debug, Clone)]  // Add derives as needed
pub struct FieldType {
    pub require: bool,
    pub field: String,
    pub mode: String,
    pub title: String,
    pub def: String,        // Default value
    pub length: usize,
    pub show: bool,
    pub describe: String,
    pub example: JsonValue,
}
```

### Constructor Pattern
```rust
impl FieldType {
    pub fn new(require: bool, field: &str, title: &str, default: &str) -> Self {
        Self {
            require,
            field: field.to_string(),
            mode: "typename".to_string(),
            title: title.to_string(),
            def: default.to_string(),
            length: 0,
            show: true,
            describe: "".to_string(),
            example: JsonValue::Null,
        }
    }
}
```

### Builder Pattern Methods
```rust
// Consuming self (for chaining during construction)
pub fn length(mut self, length: i32) -> Self {
    self.length = length;
    self
}

// Borrowing self (for modification after construction)
pub fn table_name(&mut self, name: &str) -> &mut Self {
    self.table_name = name.to_string();
    self
}
```

### Field Trait Implementation
```rust
impl Field for FieldType {
    fn sql(&mut self, model: &str) -> String {
        let not_null = if self.require { " not null" } else { "" };
        match model {
            "sqlite" => format!("{} varchar({}){} default '{}'", 
                self.field, self.length, not_null, self.def),
            "pgsql" => format!(r#""{}" varchar({}){} default '{}'"#,
                self.field, self.length, not_null, self.def),
            _ => {  // MySQL default
                let sql = format!("`{}` varchar({}){} default '{}'",
                    self.field, self.length, not_null, self.def);
                format!("{} comment '{}|{}|{}|{}'", sql, self.mode, self.require, self.title, self.def)
            }
        }
    }
    
    fn hide(&mut self) -> &mut Self {
        self.show = false;
        self
    }
    
    fn describe(&mut self, text: &str) -> &mut Self {
        self.describe = text.to_string();
        self
    }
    
    fn field(&mut self) -> JsonValue {
        let mut field = object! {};
        field.insert("require", JsonValue::from(self.require)).unwrap();
        field.insert("field", JsonValue::from(self.field.clone())).unwrap();
        // ... add all fields
        field
    }
    
    fn swagger(&mut self) -> JsonValue {
        object! {
            "type": self.mode.clone(),
         ": self.example.clone(),
        }
    }
    
    fn example(&mut self, data: JsonValue) -> &mut Self {
        self.example = data.clone();
        self
    }
}
```

### Error Handling
- Use `.unwrap()` for JSON operations (this codebase assumes valid data)
- No explicit Result/Option error propagation in field methods
- Validation logic returns data as-is in default `verify()` implementation

### Regex with lazy_static
```rust
lazy_static! {
    static ref EMAIL_RE: Regex = 
        Regex::new(r"(?i)^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$").unwrap();
}
```

### Documentation Style
- Use Chinese for doc comments (this is a Chinese-language project)
- Use `///` for public API documentation
- List parameters with `* param_name description` format

### Test Pattern
```rust
#[cfg(test)]
mod tests {
    #[test]
    fn test_name() {
        let res = module::Type::new(true, "field", "title", "").sql("sqlite");
        assert_eq!("expected output", res);
        
        // Use println! for debugging (run with --nocapture)
        println!("{res}");
    }
}
```

## Database Support

The library generates SQL for three database types:
- `"sqlite"` - SQLite syntax (unquoted field names)
- `"pgsql"` - PostgreSQL syntax (double-quoted field names)
- `"mysql"` or default - MySQL syntax (backtick-quoted, with comments)

## Dependencies

| Crate | Purpose |
|-------|---------|
| `json` | JSON serialization/deserialization |
| `chrono` | Date/time handling |
| `log` | Logging facade |
| `rand` | Random number generation |
| `lazy_static` | Lazy static initialization |
| `regex` | Regular expression matching |

## Common Patterns

### Adding a New Field Type
1. Create struct with standard fields (require, field, mode, title, def, show, describe, example)
2. Implement `new()` constructor
3. Add builder methods as needed
4. Implement `Field` trait with `sql()`, `hide()`, `describe()`, `field()`, `swagger()`, `example()`
5. Add to `FieldMode` enum in `lib.rs`
6. Add match arm in `field()` and `verify()` functions in `lib.rs`
7. Add tests in `tests/test.rs`

### SQL Generation Pattern
- SQLite: Simple field names, basic types
- PostgreSQL: Double-quoted identifiers, PostgreSQL-specific types
- MySQL: Backtick-quoted identifiers, includes metadata in comments