coenttb/swift-builders
A Swift package with result builders for Array, Dictionary, Set, String, and Markdown.
Overview
swift-builders provides Swift result builders for declarative collection and content construction. Each builder supports conditionals, loops, and optional handling with compile-time type safety.
import ArrayBuilder
import DictionaryBuilder
import StringBuilder
import SetBuilder
// Build complex arrays declaratively
let menuItems = Array<String> {
"Home"
"About"
if user.isAuthenticated {
"Dashboard"
"Profile"
}
for feature in enabledFeatures {
feature.menuTitle
}
}
// Generate configuration strings
let config = String {
"# Server Configuration"
"Host: \(serverHost)"
"Port: \(serverPort)"
if sslEnabled {
"SSL: Enabled"
"Certificate: \(certPath)"
}
}
// Create unique collections
let permissions = Set<Permission> {
.read
.write
userRole.defaultPermissions
if user.isAdmin {
[.admin, .delete]
}
}
// Build type-safe dictionaries
let configuration = Dictionary<String, String> {
("host", serverHost)
("port", "\(serverPort)")
if sslEnabled {
("ssl", "true")
("cert_path", certPath)
}
existingConfig // merge another dictionary
}Features
- Five specialized builders: Array, Dictionary, Set, String, and Markdown
- Control flow support: if/else, switch, for-in, and optional handling
- Type-safe construction: Full generic type inference and compile-time validation
- Zero runtime overhead: All builder logic resolved at compile time
- 112 test cases: Covering basic functionality, control flow, edge cases, and performance
- Swift 5.10+ compatible: Supports Swift 6.0 strict concurrency
Installation
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/coenttb/swift-builders.git", from: "0.0.1")
]Quick Start
import ArrayBuilder
struct NavigationMenu {
let user: User
var items: [String] {
Array {
"Home"
"About"
if user.isAuthenticated {
"Dashboard"
"Settings"
}
if user.isAdmin {
"Admin Panel"
}
}
}
}
// Simple and clean
let menu = NavigationMenu(user: currentUser)
print(menu.items) // ["Home", "About", "Dashboard", "Settings"]Usage
ArrayBuilder
import ArrayBuilder
// Type-safe array construction
let items = Array<String> {
"Always included"
if condition { "Conditional item" }
for item in collection { item.name }
}
// Perfect for UI data sources
let tableRows = Array<TableRow> {
HeaderRow()
ContentRows(from: data)
if showFooter { FooterRow() }
}StringBuilder
import StringBuilder
// Configuration files
let config = String {
"# Application Config"
"version: \(appVersion)"
if isProduction {
"environment: production"
"debug: false"
} else {
"environment: development"
"debug: true"
}
}
// Log messages
let logEntry = String {
"[\(timestamp)]"
"[\(level.uppercased())]"
message
if let error = error {
"Error: \(error.localizedDescription)"
}
}MarkdownBuilder
import MarkdownBuilder
// Standard formatting (single newlines)
let readme = String(markdown: {
"# Project Title"
"Brief description here"
for feature in features {
"- \(feature.name): \(feature.description)"
}
})
// Paragraph formatting (double newlines for sections)
let documentation = String(markdownWithParagraphs: {
"# Getting Started"
""
"This guide will help you get started."
""
"## Installation"
""
for step in installSteps {
"1. \(step)"
}
})DictionaryBuilder
import DictionaryBuilder
// Configuration dictionaries
let serverConfig = Dictionary<String, String> {
("host", "localhost")
("port", "8080")
if enableSSL {
("ssl", "true")
("cert_path", "/path/to/cert.pem")
}
existingConfig // merge existing dictionary
}
// Using KeyValuePair for better readability
let apiConfig = Dictionary<String, Any> {
KeyValuePair("timeout", 30)
KeyValuePair("retries", 3)
KeyValuePair("base_url", baseURL)
if isDebugMode {
KeyValuePair("debug", true)
KeyValuePair("verbose", true)
}
}
// Dynamic configuration
let appSettings = Dictionary<String, String> {
("app_name", appName)
("version", appVersion)
for (key, value) in environmentVars {
(key.lowercased(), value)
}
if user.isPremium {
("tier", "premium")
("features", premiumFeatures.joined(separator: ","))
}
}SetBuilder
import SetBuilder
// Permission systems
let userPermissions = Set<Permission> {
.read
.write
rolePermissions
if user.isAdmin {
[.admin, .delete, .create]
}
}
// Tag collections
let articleTags = Set<String> {
"swift"
"programming"
category.defaultTags
if article.isFeatured {
"featured"
}
}Examples
API Response Building
import ArrayBuilder
struct APIResponse {
let users: [User]
let includeInactive: Bool
var responseData: [UserData] {
Array {
// Always include active users
users.filter(\.isActive).map(\.data)
// Conditionally include inactive users
if includeInactive {
users.filter { !$0.isActive }.map(\.data)
}
// Add system users for admin responses
if currentUser.isAdmin {
SystemUser.all.map(\.data)
}
}
}
}Email Template Generation
import StringBuilder
import MarkdownBuilder
struct WelcomeEmail {
let user: User
let features: [Feature]
var subject: String {
String {
"Welcome to \(AppConfig.name),"
user.firstName
}
}
var body: String {
String(markdown: {
"# Welcome, \(user.firstName)!"
""
"Thank you for joining \(AppConfig.name). Here's what you can do:"
""
for feature in features {
"- **\(feature.name)**: \(feature.description)"
}
""
if user.isPremium {
"## Premium Features"
""
"As a premium member, you also have access to:"
for premium in PremiumFeature.allCases {
"- \(premium.displayName)"
}
}
})
}
}Game Configuration
import SetBuilder
import ArrayBuilder
struct GameSession {
let players: [Player]
let gameMode: GameMode
var availablePowerUps: Set<PowerUp> {
Set {
// Base power-ups for all games
PowerUp.basic
// Mode-specific power-ups
gameMode.defaultPowerUps
// Player-unlocked power-ups
for player in players {
player.unlockedPowerUps
}
// Special event power-ups
if Event.current?.isActive == true {
Event.current!.specialPowerUps
}
}
}
}Server Route Configuration
import ArrayBuilder
struct APIRouter {
let isProduction: Bool
let features: FeatureFlags
var routes: [Route] {
Array {
// Core API routes
Route.health
Route.auth
// Feature-gated routes
if features.userManagement {
Route.users
Route.profiles
}
if features.analytics {
Route.analytics
Route.metrics
}
// Development-only routes
if !isProduction {
Route.debug
Route.testData
}
// Admin routes
if features.adminPanel {
for adminRoute in AdminRoute.allCases {
adminRoute.route
}
}
}
}
}Dynamic Configuration System
import DictionaryBuilder
struct ConfigurationManager {
let environment: Environment
let features: FeatureFlags
let secrets: SecretStore
var databaseConfig: [String: Any] {
Dictionary {
("host", environment.databaseHost)
("port", environment.databasePort)
("database", environment.databaseName)
// Environment-specific settings
if environment.isProduction {
("pool_size", 20)
("timeout", 30)
("ssl_mode", "require")
} else {
("pool_size", 5)
("timeout", 60)
("ssl_mode", "prefer")
}
// Feature flags
if features.enableReadReplicas {
("read_replica_host", environment.readReplicaHost)
("read_replica_port", environment.readReplicaPort)
}
// Conditional authentication
if let credentials = secrets.databaseCredentials {
("username", credentials.username)
("password", credentials.password)
}
// Merge existing configuration
environment.customDatabaseSettings
}
}
var redisConfig: [String: String] {
Dictionary {
("host", environment.redisHost)
("port", "\(environment.redisPort)")
if environment.isProduction {
("cluster_mode", "true")
("max_connections", "100")
}
// Add authentication if available
if let auth = secrets.redisAuth {
("password", auth)
}
// Environment-specific overrides
for (key, value) in environment.redisOverrides {
(key, value)
}
}
}
}Architecture
swift-builders provides five specialized result builders:
swift-builders
├── ArrayBuilder → Generic array construction
├── DictionaryBuilder → Key-value pair construction
├── SetBuilder → Unique element collections
├── StringBuilder → Text content generation
└── MarkdownBuilder → Documentation and markupEach builder is optimized for its specific use case while maintaining consistent APIs.
Testing
Run tests:
swift testThe package includes 112 test cases covering:
- Basic functionality for each builder
- Control flow (conditionals, loops, optionals)
- Edge cases (empty collections, type inference)
- Performance with large datasets
Performance
All builder logic is resolved at compile time with zero runtime overhead. Performance tests verify consistent behavior with collections up to 1000+ elements.
Contributing
Contributions are welcome. For significant changes, please open an issue first to discuss what you would like to change.
License
Licensed under the Apache License 2.0. See LICENSE for details.
Package Metadata
Repository: coenttb/swift-builders
Homepage: https://coenttb.com
Stars: 4
Forks: 0
Open issues: 2
Default branch: main
Primary language: swift
License: Apache-2.0
Topics: array, array-builder, declarative, dictionary, dsl, markdown, result-builders, resultbuilder, set, string, swift, utilities
README: README.md