VSTP v0.2 introduces a new simplified API that makes it much easier to build networked applications. This guide will help you migrate your existing v0.1 code to take advantage of the new features.
Here are the main breaking changes you need to be aware of when migrating from v0.1 to v0.2:
// Manual frame creation
let frame = Frame::new(FrameType::Data)
.with_payload(data);
// Manual serialization
let payload = serde_json::to_vec(&message)?;
frame.set_payload(payload);
// Manual client management
let client = VstpTcpClient::connect("127.0.0.1:8080").await?;
client.send(frame).await?;
let response = client.recv().await?;// Automatic serialization
let client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
client.send(message).await?;
let response: MyMessage = client.receive().await?;// v0.1
VstpError::Timeout("ACK timeout".to_string())
// v0.2
VstpError::Timeout| v0.1 | v0.2 | Notes |
|---|---|---|
| client.send() | client.send_frame() | Low-level API only |
| client.recv() | client.read_frame() | Low-level API only |
| server.accept() | server.run() | New handler-based approach |
v0.2 introduces several new features that make VSTP easier to use:
// New easy-to-use client
use vstp::easy::VstpClient;
// TCP client
let client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
// UDP client
let client = VstpClient::connect_udp("127.0.0.1:8080").await?;
// Send any serializable type
client.send(MyMessage { data: "hello" }).await?;
// Receive with automatic deserialization
let response: MyMessage = client.receive().await?;// New handler-based server
use vstp::easy::VstpServer;
let server = VstpServer::bind_tcp("127.0.0.1:8080").await?;
server.serve(|msg: MyMessage| async move {
println!("Received: {:?}", msg);
Ok(msg) // Echo back
}).await?;// Set custom timeout
let mut client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
client.set_timeout(Duration::from_secs(5));
// All operations now respect the timeout
client.send(message).await?; // Will timeout after 5 seconds// New error types
pub enum VstpError {
// ... existing errors
SerializationError(serde_json::Error),
DeserializationError(serde_json::Error),
InvalidAddress,
UnexpectedFrameType,
}Follow these steps to migrate your application from v0.1 to v0.2:
# Cargo.toml
[dependencies]
vstp = "0.2.1" # Update version
serde = { version = "1.0", features = ["derive"] } # Add if not present// Old imports
use vstp::{VstpTcpClient, VstpTcpServer, Frame, FrameType};
// New imports
use vstp::easy::{VstpClient, VstpServer};
use serde::{Serialize, Deserialize};// Add serialization derives
#[derive(Serialize, Deserialize)]
struct MyMessage {
data: String,
timestamp: u64,
}let client = VstpTcpClient::connect("127.0.0.1:8080").await?;
let payload = serde_json::to_vec(&message)?;
let frame = Frame::new(FrameType::Data)
.with_payload(payload);
client.send(frame).await?;
let response_frame = client.recv().await?;
let response: MyMessage = serde_json::from_slice(
response_frame.payload()
)?;let client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
client.send(message).await?;
let response: MyMessage = client.receive().await?;let server = VstpTcpServer::bind("127.0.0.1:8080").await?;
loop {
let mut client = server.accept().await?;
tokio::spawn(async move {
while let Ok(Some(frame)) = client.recv().await {
let message: MyMessage = serde_json::from_slice(
frame.payload()
)?;
let response = process_message(message).await?;
let response_payload = serde_json::to_vec(&response)?;
let response_frame = Frame::new(FrameType::Data)
.with_payload(response_payload);
client.send(response_frame).await?;
}
});
}let server = VstpServer::bind_tcp("127.0.0.1:8080").await?;
server.serve(|message: MyMessage| async move {
let response = process_message(message).await?;
Ok(response)
}).await?;// Update error handling
match client.receive::<MyMessage>().await {
Ok(message) => {
// Handle message
}
Err(VstpError::Timeout) => {
// Handle timeout
}
Err(VstpError::SerializationError(e)) => {
// Handle serialization error
}
Err(e) => {
// Handle other errors
}
}Here are complete examples showing how to migrate common patterns:
use vstp::{VstpTcpServer, Frame, FrameType};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let server = VstpTcpServer::bind("127.0.0.1:8080").await?;
loop {
let mut client = server.accept().await?;
tokio::spawn(async move {
while let Ok(Some(frame)) = client.recv().await {
let response_frame = Frame::new(FrameType::Data)
.with_payload(frame.payload().to_vec());
client.send(response_frame).await?;
}
Ok::<(), vstp::VstpError>(())
});
}
}use vstp::easy::VstpServer;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct EchoMessage {
content: String,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let server = VstpServer::bind_tcp("127.0.0.1:8080").await?;
server.serve(|msg: EchoMessage| async move {
println!("Echoing: {}", msg.content);
Ok(msg)
}).await?;
Ok(())
}use vstp::{VstpTcpClient, Frame, FrameType};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct ChatMessage {
from: String,
content: String,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = VstpTcpClient::connect("127.0.0.1:8080").await?;
let msg = ChatMessage {
from: "Alice".to_string(),
content: "Hello!".to_string(),
};
let payload = serde_json::to_vec(&msg)?;
let frame = Frame::new(FrameType::Data).with_payload(payload);
client.send(frame).await?;
let response_frame = client.recv().await?
.ok_or("Connection closed")?;
let response: ChatMessage = serde_json::from_slice(
response_frame.payload()
)?;
println!("Received: {}", response.content);
Ok(())
}use vstp::easy::VstpClient;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct ChatMessage {
from: String,
content: String,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
let msg = ChatMessage {
from: "Alice".to_string(),
content: "Hello!".to_string(),
};
client.send(msg.clone()).await?;
let response: ChatMessage = client.receive().await?;
println!("Received: {}", response.content);
Ok(())
}Here are common issues you might encounter during migration and how to resolve them:
Solution: Use the new simplified API:
// Old
let client = VstpTcpClient::connect("127.0.0.1:8080").await?;
// New
let client = VstpClient::connect_tcp("127.0.0.1:8080").await?;Solution: Add serialization derives:
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct MyMessage {
data: String,
}Solution: Update error handling:
// Old
VstpError::Timeout("ACK timeout".to_string())
// New
VstpError::TimeoutSolution: Ensure your message types match between client and server. The new API is more strict about type matching.
Solution: The new API has a default 30-second timeout. Adjust it if needed:
let mut client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
client.set_timeout(Duration::from_secs(60));If you encounter issues during migration, here are some resources: