Initial version
This commit is contained in:
303
README.md
303
README.md
@@ -1,3 +1,302 @@
|
||||
# EonaCat.FastBin
|
||||
# EonaCat.FastBin
|
||||
|
||||
A blazingly fast, enterprise-grade binary serialization library for .NET with built-in networking capabilities.
|
||||
A blazingly fast, enterprise-grade binary serialization library for .NET with built-in networking capabilities.
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- **⚡ Ultra-fast** - Binary format optimized for speed, outperforms JSON and MessagePack
|
||||
- **🔄 Complete object graph support** - Handles nested objects, circular references, and polymorphism
|
||||
- **📦 Zero configuration** - Works with any type out of the box
|
||||
- **🌐 Built-in networking** - TCP client/server with RPC support included
|
||||
- **🎯 Type-safe** - Strongly-typed API with full generic support
|
||||
- **🔒 Thread-safe** - Safe for concurrent serialization/deserialization
|
||||
- **📱 Cross-platform** - .NET Standard 2.1 compatible
|
||||
|
||||
## 📊 Performance
|
||||
|
||||
EonaCat.FastBin uses several optimization techniques to achieve superior performance:
|
||||
|
||||
- **Binary format** - No text parsing overhead
|
||||
- **7-bit integer encoding** - Compact representation of small numbers
|
||||
- **Type caching** - Reflection performed only once per type
|
||||
- **Reference tracking** - Objects serialized once, referenced thereafter
|
||||
- **Zero-copy operations** - Direct memory access where possible
|
||||
|
||||
## 🎯 Quick Start
|
||||
|
||||
### Basic Serialization
|
||||
|
||||
```csharp
|
||||
using EonaCat.FastBin;
|
||||
|
||||
// Serialize any object
|
||||
var user = new User { Id = 1, Name = "Brasser", Email = "brasser@example.com" };
|
||||
byte[] data = EonaCat.FastBin.Serialize(user);
|
||||
|
||||
// Deserialize back
|
||||
var restored = EonaCat.FastBin.Deserialize<User>(data);
|
||||
```
|
||||
|
||||
### Complex Objects
|
||||
|
||||
```csharp
|
||||
// Works with nested objects
|
||||
var order = new Order
|
||||
{
|
||||
OrderId = Guid.NewGuid(),
|
||||
TotalAmount = 299.99m,
|
||||
Items = new List<OrderItem>
|
||||
{
|
||||
new OrderItem { ProductName = "Laptop", Quantity = 1, Price = 299.99m }
|
||||
}
|
||||
};
|
||||
|
||||
byte[] data = EonaCat.FastBin.Serialize(order);
|
||||
var restored = EonaCat.FastBin.Deserialize<Order>(data);
|
||||
```
|
||||
|
||||
### Collections
|
||||
|
||||
```csharp
|
||||
// Lists
|
||||
var users = new List<User> { user1, user2, user3 };
|
||||
byte[] data = EonaCat.FastBin.Serialize(users);
|
||||
|
||||
// Dictionaries
|
||||
var userMap = new Dictionary<int, User>
|
||||
{
|
||||
[1] = user1,
|
||||
[2] = user2
|
||||
};
|
||||
byte[] data2 = EonaCat.FastBin.Serialize(userMap);
|
||||
|
||||
// Arrays
|
||||
var userArray = new User[] { user1, user2 };
|
||||
byte[] data3 = EonaCat.FastBin.Serialize(userArray);
|
||||
```
|
||||
|
||||
### Circular References
|
||||
|
||||
```csharp
|
||||
// Self-referencing objects work automatically
|
||||
var manager = new User { Id = 1, Name = "Manager" };
|
||||
var employee = new User { Id = 2, Name = "Brasser", Manager = manager };
|
||||
manager.Manager = manager; // Circular reference
|
||||
|
||||
byte[] data = EonaCat.FastBin.Serialize(employee);
|
||||
var restored = EonaCat.FastBin.Deserialize<User>(data);
|
||||
|
||||
// Reference integrity maintained
|
||||
Console.WriteLine(ReferenceEquals(restored.Manager, restored.Manager.Manager)); // True
|
||||
```
|
||||
|
||||
### Polymorphism
|
||||
|
||||
```csharp
|
||||
// Handles polymorphic types automatically
|
||||
object[] items = new object[]
|
||||
{
|
||||
"A string",
|
||||
42,
|
||||
new User { Id = 1, Name = "Brasser" },
|
||||
new Order { OrderId = Guid.NewGuid() }
|
||||
};
|
||||
|
||||
byte[] data = EonaCat.FastBin.Serialize(items);
|
||||
var restored = EonaCat.FastBin.Deserialize<object[]>(data);
|
||||
|
||||
// Types preserved correctly
|
||||
Console.WriteLine(restored[0].GetType()); // System.String
|
||||
Console.WriteLine(restored[2].GetType()); // User
|
||||
```
|
||||
|
||||
## 🌐 Networking
|
||||
|
||||
### Server Setup
|
||||
|
||||
```csharp
|
||||
var server = new FastServer();
|
||||
|
||||
// Register handlers
|
||||
server.RegisterHandler<GetUserRequest, User>("GetUser", request =>
|
||||
{
|
||||
// Your business logic here
|
||||
return database.GetUser(request.UserId);
|
||||
});
|
||||
|
||||
server.RegisterHandler<CreateOrderRequest, CreateOrderResponse>("CreateOrder", async request =>
|
||||
{
|
||||
// Async handlers supported
|
||||
var order = await orderService.CreateOrderAsync(request);
|
||||
return new CreateOrderResponse { OrderId = order.Id, Message = "Success" };
|
||||
});
|
||||
|
||||
// Start server
|
||||
await server.StartAsync(5000);
|
||||
```
|
||||
|
||||
### Client Usage
|
||||
|
||||
```csharp
|
||||
using (var client = new FastClient())
|
||||
{
|
||||
await client.ConnectAsync("localhost", 5000);
|
||||
|
||||
// Make RPC calls
|
||||
var user = await client.CallAsync<GetUserRequest, User>(
|
||||
"GetUser",
|
||||
new GetUserRequest { UserId = 123 }
|
||||
);
|
||||
|
||||
var response = await client.CallAsync<CreateOrderRequest, CreateOrderResponse>(
|
||||
"CreateOrder",
|
||||
new CreateOrderRequest
|
||||
{
|
||||
UserId = 123,
|
||||
Items = orderItems
|
||||
}
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 Supported Types
|
||||
|
||||
### Primitives
|
||||
- All numeric types: `byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `float`, `double`, `decimal`
|
||||
- `bool`, `char`, `string`
|
||||
- `DateTime`, `Guid`
|
||||
- Enums
|
||||
|
||||
### Collections
|
||||
- Arrays: `T[]`
|
||||
- Lists: `List<T>`, `IList`, `IList<T>`
|
||||
- Dictionaries: `Dictionary<K,V>`, `IDictionary`, `IDictionary<K,V>`
|
||||
|
||||
### Complex Types
|
||||
- Classes (public and non-public fields)
|
||||
- Structs
|
||||
- Nested objects
|
||||
- Generic types
|
||||
- Polymorphic types
|
||||
- Self-referencing objects
|
||||
- Circular references
|
||||
|
||||
## 🔧 Advanced Usage
|
||||
|
||||
### Custom Domain Models
|
||||
|
||||
```csharp
|
||||
public class Customer
|
||||
{
|
||||
public int Id;
|
||||
public string Name;
|
||||
public string Email;
|
||||
public DateTime CreatedAt;
|
||||
public Address ShippingAddress;
|
||||
public List<Order> Orders;
|
||||
public Customer ReferredBy; // Self-reference supported
|
||||
}
|
||||
|
||||
public class Address
|
||||
{
|
||||
public string Street;
|
||||
public string City;
|
||||
public string ZipCode;
|
||||
public string Country;
|
||||
}
|
||||
```
|
||||
|
||||
No attributes or special configuration needed - just define your classes normally!
|
||||
|
||||
### Error Handling (Networking)
|
||||
|
||||
```csharp
|
||||
try
|
||||
{
|
||||
var result = await client.CallAsync<Request, Response>("Route", request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle network errors, deserialization errors, or handler exceptions
|
||||
Console.WriteLine($"RPC failed: {ex.Message}");
|
||||
}
|
||||
```
|
||||
|
||||
### Server Shutdown
|
||||
|
||||
```csharp
|
||||
// Graceful shutdown
|
||||
server.Stop();
|
||||
```
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
### Binary Format
|
||||
|
||||
EonaCat.FastBin uses a compact binary format with the following features:
|
||||
|
||||
1. **Type markers** - Single byte to identify data type
|
||||
2. **7-bit encoding** - Variable-length integers for efficiency
|
||||
3. **Reference tracking** - Objects assigned IDs, referenced by ID on subsequent encounters
|
||||
4. **Type polymorphism** - Actual type stored when different from declared type
|
||||
5. **Field ordering** - Consistent ordering by name for versioning
|
||||
|
||||
### Networking Protocol
|
||||
|
||||
1. **Message framing** - 4-byte length prefix
|
||||
2. **Request/Response** - Structured messages with route and data
|
||||
3. **Error handling** - Exceptions marshaled back to client
|
||||
4. **Type safety** - Generic request/response types
|
||||
|
||||
## ⚠️ Limitations & Considerations
|
||||
|
||||
- **Private fields** - Serializes all fields (public and private)
|
||||
- **Properties** - Only backing fields are serialized
|
||||
- **Versioning** - Adding/removing fields requires redeployment (no built-in versioning)
|
||||
- **Security** - No encryption built-in (use TLS/SSL at transport layer)
|
||||
- **Large objects** - Keep network messages under 2GB (int.MaxValue)
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
The included example application demonstrates:
|
||||
|
||||
1. ✅ Basic serialization of primitives and collections
|
||||
2. ✅ Complex nested object graphs
|
||||
3. ✅ Self-referencing and circular references
|
||||
4. ✅ Polymorphic type handling
|
||||
5. ✅ Client-server RPC communication
|
||||
|
||||
## 🔄 Migration Guide
|
||||
|
||||
### From JSON.NET
|
||||
|
||||
```csharp
|
||||
// Before (JSON.NET)
|
||||
string json = JsonConvert.SerializeObject(obj);
|
||||
var restored = JsonConvert.DeserializeObject<T>(json);
|
||||
|
||||
// After (EonaCat.FastBin)
|
||||
byte[] data = FastBin.Serialize(obj);
|
||||
var restored = FastBin.Deserialize<T>(data);
|
||||
```
|
||||
|
||||
### From MessagePack
|
||||
|
||||
```csharp
|
||||
// Before (MessagePack)
|
||||
byte[] data = MessagePackSerializer.Serialize(obj);
|
||||
var restored = MessagePackSerializer.Deserialize<T>(data);
|
||||
|
||||
// After (EonaCat.FastBin) - Same API!
|
||||
byte[] data = FastBin.Serialize(obj);
|
||||
var restored = FastBin.Deserialize<T>(data);
|
||||
```
|
||||
|
||||
## 📝 Best Practices
|
||||
|
||||
1. **Reuse clients** - Create one `FastClient` per connection, reuse for multiple calls
|
||||
2. **Dispose properly** - Always dispose clients: `using (var client = new FastClient())`
|
||||
3. **Handler registration** - Register all handlers before calling `StartAsync()`
|
||||
4. **Error handling** - Always wrap RPC calls in try-catch
|
||||
5. **Thread safety** - `FastBin` class is thread-safe, instances are not
|
||||
6. **Network timeout** - Implement timeouts at the TCP socket level if needed
|
||||
Reference in New Issue
Block a user