TinyString

TinyString is a lightweight Go library that provides comprehensive string manipulation, type conversion, formatting, and error handling with a fluid API, specifically designed for small devices and web applications using TinyGo as the target compiler.
Key Features
- 🚀 Fluid and chainable API - Easy to use and readable operations
- � Complete string toolkit - Transformations, conversions, formatting, and error handling
- 🧵 Concurrency safe - Thread-safe operations for concurrent environments
- 📦 Zero dependencies - No
fmt
, strings
, strconv
, or errors
imports
- 🎯 TinyGo optimized - Manual implementations for minimal binary size
- 🌐 WebAssembly-first - Designed for modern web deployment
- 🔄 Universal type support - Works with strings, numbers, booleans, and slices
- ⚡ Performance focused - Predictable allocations and custom optimizations
Why TinyString?
Go's WebAssembly potential is incredible, but traditional applications face a critical challenge: massive binary sizes that make web deployment impractical.
The Problem
Every Go project needs string manipulation, type conversion, and error handling - but importing standard library packages (fmt
, strings
, strconv
, errors
) creates significant binary bloat that hurts:
- 🌐 Web app performance - Slow loading times and poor user experience
- � Edge deployment - Resource constraints on small devices
- 🚀 Distribution efficiency - Large binaries for simple operations
The Solution
TinyString replaces multiple standard library packages with lightweight, manual implementations that deliver:
- 🏆 Up to smaller binaries - Dramatic size reduction for WebAssembly
- ✅ Full TinyGo compatibility - No compilation issues or warnings
- 🎯 Predictable performance - No hidden allocations or overhead
- 🔧 Familiar API - Drop-in replacement for standard library functions
Installation
go get github.com/cdvelop/tinystring
Usage
import "github.com/cdvelop/tinystring"
// Quick start - Basic conversion and transformation
text := tinystring.Convert("Hóla Múndo").RemoveTilde().ToLower().String()
// out: "hola mundo"
// Working with different data types
numText := tinystring.Convert(42).String() // out: "42"
boolText := tinystring.Convert(true).String() // out: "true"
// Memory-efficient approach using string pointers
original := "Él Múrcielago Rápido"
tinystring.Convert(&original).RemoveTilde().CamelCaseLower().Apply()
// original is now: "elMurcielagoRapido"
📚 Standard Library Equivalents
🔤 strings Package
Replace common strings
package functions with TinyString equivalents:
Go Standard |
TinyString Equivalent |
strings.ToLower() |
Convert(s).ToLower().String() |
strings.ToUpper() |
Convert(s).ToUpper().String() |
strings.Contains() |
Contains(s, substr) |
strings.Replace() |
Convert(s).Replace(old, new).String() |
strings.Split() |
Split(s, sep) |
strings.Join() |
Convert(slice).Join(sep).String() |
strings.TrimSpace() |
Convert(s).Trim().String() |
strings.TrimPrefix() |
Convert(s).TrimPrefix(prefix).String() |
strings.TrimSuffix() |
Convert(s).TrimSuffix(suffix).String() |
strings.Repeat() |
Convert(s).Repeat(n).String() |
// Case conversions
tinystring.Convert("HELLO").ToLower().String() // out: "hello"
tinystring.Convert("world").ToUpper().String() // out: "WORLD"
tinystring.Convert("hello world").Capitalize().String() // out: "Hello World"
// Advanced case styles
tinystring.Convert("hello world").CamelCaseLower().String() // out: "helloWorld"
tinystring.Convert("hello world").CamelCaseUpper().String() // out: "HelloWorld"
tinystring.Convert("hello world").ToSnakeCaseLower().String() // out: "hello_world"
tinystring.Convert("hello world").ToSnakeCaseUpper().String() // out: "HELLO_WORLD"
String Search & Operations
// Search and count
found := tinystring.Contains("hello world", "world") // out: true
count := tinystring.CountOccurrences("abracadabra", "abra") // out: 2
// Replace operations
tinystring.Convert("hello world").Replace("world", "Go").String() // out: "hello Go"
tinystring.Convert("test 123 test").Replace(123, 456).String() // out: "test 456 test"
String Splitting & Joining
// Split strings
parts := tinystring.Split("apple,banana,cherry", ",")
// out: []string{"apple", "banana", "cherry"}
parts := tinystring.Split("hello\tworld\nnew") // Handles whitespace
// out: []string{"hello", "world", "new"}
// Join slices
tinystring.Convert([]string{"Hello", "World"}).Join().String() // out: "Hello World"
tinystring.Convert([]string{"a", "b", "c"}).Join("-").String() // out: "a-b-c"
String Trimming & Cleaning
// Trim operations
tinystring.Convert(" hello ").Trim().String() // out: "hello"
tinystring.Convert("prefix-data").TrimPrefix("prefix-").String() // out: "data"
tinystring.Convert("file.txt").TrimSuffix(".txt").String() // out: "file"
// Repeat strings
tinystring.Convert("Go").Repeat(3).String() // out: "GoGoGo"
🔢 strconv Package
Replace strconv
package functions for type conversions:
Go Standard |
TinyString Equivalent |
strconv.Itoa() |
Convert(i).String() |
strconv.Atoi() |
Convert(s).ToInt() |
strconv.ParseFloat() |
Convert(s).ToFloat() |
strconv.ParseBool() |
Convert(s).ToBool() |
strconv.FormatFloat() |
Convert(f).RoundDecimals(n).String() |
strconv.Quote() |
Convert(s).Quote().String() |
Type Conversions
// String to numbers
result, err := tinystring.Convert("123").ToInt() // out: 123, nil
result, err := tinystring.Convert("456").ToUint() // out: 456, nil
result, err := tinystring.Convert("3.14").ToFloat() // out: 3.14, nil
// Numbers to string
tinystring.Convert(42).String() // out: "42"
tinystring.Convert(3.14159).String() // out: "3.14159"
// Boolean conversions
result, err := tinystring.Convert("true").ToBool() // out: true, nil
result, err := tinystring.Convert(42).ToBool() // out: true, nil (non-zero = true)
result, err := tinystring.Convert(0).ToBool() // out: false, nil
// String quoting
tinystring.Convert("hello").Quote().String() // out: "\"hello\""
tinystring.Convert("say \"hello\"").Quote().String() // out: "\"say \\\"hello\\\"\""
// Decimal rounding
tinystring.Convert(3.154).RoundDecimals(2).String() // out: "3.16" (ceiling)
tinystring.Convert(3.154).RoundDecimals(2).Down().String() // out: "3.15" (floor)
// Number formatting with thousands separator
tinystring.Convert(2189009.00).FormatNumber().String() // out: "2.189.009"
🖨️ fmt Package
Replace fmt
package functions for formatting:
Go Standard |
TinyString Equivalent |
fmt.Sprintf() |
Format(format, args...) |
fmt.Sprint() |
Convert(v).String() |
// Printf-style formatting
result := tinystring.Format("Hello %s, you have %d messages", "John", 5)
// out: "Hello John, you have 5 messages"
// Multiple format specifiers
result := tinystring.Format("Number: %d, Float: %.2f, Bool: %v", 42, 3.14159, true)
// out: "Number: 42, Float: 3.14, Bool: true"
// Advanced formatting (hex, binary, octal)
result := tinystring.Format("Hex: %x, Binary: %b, Octal: %o", 255, 10, 8)
// out: "Hex: ff, Binary: 1010, Octal: 10"
❌ errors Package
Replace errors
package functions for error handling:
Go Standard |
TinyString Equivalent |
errors.New() |
Err(message) |
fmt.Errorf() |
Errorf(format, args...) |
Error Creation
// Simple error creation
err := tinystring.Err("invalid input").Error()
// out: "invalid input"
// Multiple error messages
err := tinystring.Err("invalid format", "expected number").Error()
// out: "invalid format expected number"
// Formatted errors (like fmt.Errorf)
err := tinystring.Errorf("invalid value: %s at position %d", "abc", 5).Error()
// out: "invalid value: abc at position 5"
// Error with validation
result, err := tinystring.Convert("invalid").ToInt()
if err != nil {
// Handle conversion error
}
🚀 TinyString Exclusive Features
Features not available in Go's standard library:
🌍 Unicode & Localization
// Remove accents and diacritics
tinystring.Convert("café naïve résumé").RemoveTilde().String() // out: "cafe naive resume"
tinystring.Convert("Ñoño niño").RemoveTilde().String() // out: "Nono nino"
✂️ Smart Truncation
// Basic truncation with ellipsis
tinystring.Convert("Hello, World!").Truncate(10).String() // out: "Hello, ..."
// Name truncation for UI display
tinystring.Convert("Jeronimo Dominguez").TruncateName(3, 15).String()
// out: "Jer. Dominguez"
// Advanced name handling
tinystring.Convert("Juan Carlos Rodriguez").TruncateName(3, 20).String()
// out: "Jua. Car. Rodriguez"
🔧 Advanced Utilities
// Key-value parsing
value, err := tinystring.ParseKeyValue("user:admin") // out: "admin", nil
value, err := tinystring.ParseKeyValue("count=42", "=") // out: "42", nil
// Snake case with custom separators
tinystring.Convert("hello world").ToSnakeCaseLower("-").String() // out: "hello-world"
tinystring.Convert("hello world").ToSnakeCaseUpper("_").String() // out: "HELLO_WORLD"
Memory Optimization
// ✅ Efficient: Modify original string directly
original := "Él Múrcielago Rápido"
tinystring.Convert(&original).RemoveTilde().ToLower().Apply()
// original is now modified in-place
// ❌ Less efficient: Creates new string
original := "Él Múrcielago Rápido"
result := tinystring.Convert(original).RemoveTilde().ToLower().String()
Chaining Operations
// Combine multiple operations efficiently
result := tinystring.Convert(" HÓLA MÚNDO ")
.Trim()
.RemoveTilde()
.ToLower()
.Replace(" ", "_")
.String()
// out: "hola_mundo"
🔄 Output Methods: String() vs Apply()
Choose between two approaches for finalizing operations:
// ✅ String() - Returns result, keeps original unchanged
originalText := "Él Múrcielago Rápido"
result := tinystring.Convert(&originalText).RemoveTilde().ToLower().String()
// result: "el murcielago rapido"
// originalText: "Él Múrcielago Rápido" (unchanged)
// ✅ Apply() - Modifies original string directly (memory efficient)
originalText := "Él Múrcielago Rápido"
tinystring.Convert(&originalText).RemoveTilde().ToLower().Apply()
// originalText: "el murcielago rapido" (modified in-place)
Binary Size Comparison
Standard Library Example | TinyString Example
Last updated: 2025-06-15 19:29:31
Build Type |
Parameters |
Standard Library
go build |
TinyString
tinygo build |
Size Reduction |
Performance |
🖥️ Default Native |
-ldflags="-s -w" |
1.6 MB |
978.0 KB |
-611.0 KB |
✅ 38.5% |
🌐 Default WASM |
(default -opt=z) |
879.1 KB |
210.4 KB |
-668.8 KB |
🏆 76.1% |
🌐 Ultra WASM |
-no-debug -panic=trap -scheduler=none -gc=leaking -target wasm |
200.6 KB |
25.8 KB |
-174.8 KB |
🏆 87.1% |
🌐 Speed WASM |
-opt=2 -target wasm |
1.3 MB |
273.9 KB |
-1016.8 KB |
🏆 78.8% |
🌐 Debug WASM |
-opt=0 -target wasm |
3.0 MB |
642.1 KB |
-2.4 MB |
🏆 79.1% |
- 🏆 Peak Reduction: 87.1% (Best optimization)
- ✅ Average WebAssembly Reduction: 80.3%
- ✅ Average Native Reduction: 38.5%
- 📦 Total Size Savings: 4.8 MB across all builds
- ❌ Poor (<5% reduction)
- ➖ Fair (5-15% reduction)
- ✅ Good (15-70% reduction)
- 🏆 Outstanding (>70% reduction)
Memory Usage Comparison
Standard Library Example | TinyString Example
Last updated: 2025-06-15 19:29:59
Performance benchmarks comparing memory allocation patterns between standard Go library and TinyString:
🧪 Benchmark Category |
📚 Library |
💾 Memory/Op |
🔢 Allocs/Op |
⏱️ Time/Op |
📈 Memory Trend |
🎯 Alloc Trend |
🏆 Performance |
📝 String Processing |
📊 Standard |
1.2 KB |
48 |
3.0μs |
- |
- |
- |
|
🚀 TinyString |
2.3 KB |
46 |
9.0μs |
❌ 96.7% more |
➖ 4.2% less |
❌ Poor |
🔢 Number Processing |
📊 Standard |
1.2 KB |
132 |
4.1μs |
- |
- |
- |
|
🚀 TinyString |
2.6 KB |
120 |
3.8μs |
❌ 121.3% more |
✅ 9.1% less |
❌ Poor |
🔄 Mixed Operations |
📊 Standard |
546 B |
44 |
2.1μs |
- |
- |
- |
|
🚀 TinyString |
1.2 KB |
46 |
3.4μs |
❌ 125.6% more |
➖ 4.5% more |
❌ Poor |
📝 String Processing (Pointer Optimization) |
📊 Standard |
1.2 KB |
48 |
3.0μs |
- |
- |
- |
|
🚀 TinyString |
2.2 KB |
38 |
8.8μs |
❌ 86.0% more |
🏆 20.8% less |
⚠️ Caution |
- 💾 Memory Efficiency: ❌ Poor (Significant overhead) (107.4% average change)
- 🔢 Allocation Efficiency: ✅ Good (Allocation efficient) (-7.4% average change)
- 📊 Benchmarks Analyzed: 4 categories
- 🎯 Optimization Focus: Binary size reduction vs runtime efficiency
⚖️ Trade-offs Analysis
The benchmarks reveal important trade-offs between binary size and runtime performance:
📦 Binary Size Benefits ✅
- 🏆 16-84% smaller compiled binaries
- 🌐 Superior WebAssembly compression ratios
- 🚀 Faster deployment and distribution
- 💾 Lower storage requirements
🧠 Runtime Memory Considerations ⚠️
- 📈 Higher allocation overhead during execution
- 🗑️ Increased GC pressure due to allocation patterns
- ⚡ Trade-off optimizes for distribution size over runtime efficiency
- 🔄 Different optimization strategy than standard library
🎯 Optimization Recommendations
🎯 Use Case |
💡 Recommendation |
🔧 Best For |
🌐 WebAssembly Apps |
✅ TinyString |
Size-critical web deployment |
📱 Embedded Systems |
✅ TinyString |
Resource-constrained devices |
☁️ Edge Computing |
✅ TinyString |
Fast startup and deployment |
🏢 Memory-Intensive Server |
⚠️ Standard Library |
High-throughput applications |
🔄 High-Frequency Processing |
⚠️ Standard Library |
Performance-critical workloads |
- 🏆 Excellent (Better performance)
- ✅ Good (Acceptable trade-off)
- ⚠️ Caution (Higher resource usage)
- ❌ Poor (Significant overhead)
Contributing
This project is currently being self-financed and developed independently. The development, testing, maintenance, and improvements are funded entirely out of my personal resources and time.
If you find this project useful and would like to support its continued development, you can make a donation here with PayPal. Your support helps cover:
- 💻 Development time and effort
- 🧪 Testing and quality assurance
- 📚 Documentation improvements
- 🔧 Bug fixes and feature enhancements
- 🌐 Community support and maintenance
Any contribution, however small, is greatly appreciated and directly impacts the project's future development. 🙌
License
MIT License