Upgrade dependencies and refactor serialization in build.rs

- Updated `bincode` to version 2.0.1, modifying serialization calls to use the new API with `serde` support.
- Added new dependencies in `Cargo.lock`, including `alloca`, `atomic-waker`, and `aws-lc-rs`, ensuring compatibility with the latest features.
- Refactored file creation and serialization logic in `build.rs` for improved clarity and performance.
- Updated various dependencies in `Cargo.toml` to their latest versions, enhancing overall project stability and functionality.
This commit is contained in:
Joe 2026-02-06 18:57:29 -06:00
parent 0a4496a6c9
commit 71ea25fe0e
47 changed files with 933 additions and 517 deletions

View file

@ -9,8 +9,10 @@ use std::{
sync::{Arc, Mutex},
};
use bytes::Bytes;
use futures::{sink::SinkExt, stream::StreamExt};
use hyper::{body, Body, Method, Request, Response, StatusCode};
use http_body_util::{BodyExt, Full};
use hyper::{body::Incoming, Method, Request, Response, StatusCode};
use hyper_tungstenite::{is_upgrade_request, tungstenite::Message, upgrade, HyperWebsocket};
use opener::OpenError;
use rbx_dom_weak::{
@ -116,7 +118,10 @@ fn variant_to_json(variant: &Variant) -> Option<serde_json::Value> {
}
}
pub async fn call(serve_session: Arc<ServeSession>, mut request: Request<Body>) -> Response<Body> {
pub async fn call(
serve_session: Arc<ServeSession>,
mut request: Request<Incoming>,
) -> Response<Full<Bytes>> {
let service = ApiService::new(serve_session);
match (request.method(), request.uri().path()) {
@ -253,7 +258,7 @@ impl ApiService {
}
/// Get a summary of information about the server
async fn handle_api_rojo(&self) -> Response<Body> {
async fn handle_api_rojo(&self) -> Response<Full<Bytes>> {
let tree = self.serve_session.tree();
let root_instance_id = tree.get_root_id();
@ -281,7 +286,7 @@ impl ApiService {
}
/// Handle WebSocket upgrade for real-time message streaming
async fn handle_api_socket(&self, request: &mut Request<Body>) -> Response<Body> {
async fn handle_api_socket(&self, request: &mut Request<Incoming>) -> Response<Full<Bytes>> {
let argument = &request.uri().path()["/api/socket/".len()..];
let input_cursor: u32 = match argument.parse() {
Ok(v) => v,
@ -318,11 +323,11 @@ impl ApiService {
response
}
async fn handle_api_write(&self, request: Request<Body>) -> Response<Body> {
async fn handle_api_write(&self, request: Request<Incoming>) -> Response<Full<Bytes>> {
let session_id = self.serve_session.session_id();
let tree_mutation_sender = self.serve_session.tree_mutation_sender();
let body = body::to_bytes(request.into_body()).await.unwrap();
let body = request.into_body().collect().await.unwrap().to_bytes();
let request: WriteRequest = match deserialize_msgpack(&body) {
Ok(request) => request,
@ -2411,7 +2416,7 @@ impl ApiService {
}
}
async fn handle_api_read(&self, request: Request<Body>) -> Response<Body> {
async fn handle_api_read(&self, request: Request<Incoming>) -> Response<Full<Bytes>> {
let argument = &request.uri().path()["/api/read/".len()..];
let requested_ids: Result<Vec<Ref>, _> = argument.split(',').map(Ref::from_str).collect();
@ -2496,7 +2501,7 @@ impl ApiService {
/// The returned model is a folder that contains ObjectValues with names
/// that correspond to the requested Instances. These values have their
/// `Value` property set to point to the requested Instance.
async fn handle_api_serialize(&self, request: Request<Body>) -> Response<Body> {
async fn handle_api_serialize(&self, request: Request<Incoming>) -> Response<Full<Bytes>> {
let argument = &request.uri().path()["/api/serialize/".len()..];
let requested_ids: Result<Vec<Ref>, _> = argument.split(',').map(Ref::from_str).collect();
@ -2558,7 +2563,7 @@ impl ApiService {
/// provided IDs. Used because the plugin does not store a RojoTree,
/// and referent properties need to be updated after the serialize
/// endpoint is used.
async fn handle_api_ref_patch(&self, request: Request<Body>) -> Response<Body> {
async fn handle_api_ref_patch(&self, request: Request<Incoming>) -> Response<Full<Bytes>> {
let argument = &request.uri().path()["/api/ref-patch/".len()..];
let requested_ids: Result<Vec<Ref>, _> = argument.split(',').map(Ref::from_str).collect();
@ -2613,7 +2618,7 @@ impl ApiService {
}
/// Open a script with the given ID in the user's default text editor.
async fn handle_api_open(&self, request: Request<Body>) -> Response<Body> {
async fn handle_api_open(&self, request: Request<Incoming>) -> Response<Full<Bytes>> {
let argument = &request.uri().path()["/api/open/".len()..];
let requested_id = match Ref::from_str(argument) {
Ok(id) => id,
@ -2786,7 +2791,7 @@ async fn handle_websocket_subscription(
log::debug!("Sending batch of messages over WebSocket subscription");
if websocket.send(Message::Binary(msgpack_message)).await.is_err() {
if websocket.send(Message::Binary(msgpack_message.into())).await.is_err() {
// Client disconnected
log::debug!("WebSocket subscription closed by client");
break;

View file

@ -12,11 +12,12 @@ use std::convert::Infallible;
use std::net::SocketAddr;
use std::sync::Arc;
use hyper::{
server::Server,
service::{make_service_fn, service_fn},
Body, Request,
};
use hyper::body::Incoming;
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper::Request;
use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;
use tokio::runtime::Runtime;
use crate::serve_session::ServeSession;
@ -33,29 +34,37 @@ impl LiveServer {
pub fn start(self, address: SocketAddr) {
let serve_session = Arc::clone(&self.serve_session);
let make_service = make_service_fn(move |_conn| {
let serve_session = Arc::clone(&serve_session);
let rt = Runtime::new().unwrap();
rt.block_on(async move {
let listener = TcpListener::bind(address).await.unwrap();
async {
let service = move |req: Request<Body>| {
let serve_session = Arc::clone(&serve_session);
loop {
let (stream, _) = listener.accept().await.unwrap();
let io = TokioIo::new(stream);
let serve_session = Arc::clone(&serve_session);
async move {
if req.uri().path().starts_with("/api") {
Ok::<_, Infallible>(api::call(serve_session, req).await)
} else {
Ok::<_, Infallible>(ui::call(serve_session, req).await)
tokio::spawn(async move {
let service = service_fn(move |req: Request<Incoming>| {
let serve_session = Arc::clone(&serve_session);
async move {
if req.uri().path().starts_with("/api") {
Ok::<_, Infallible>(api::call(serve_session, req).await)
} else {
Ok::<_, Infallible>(ui::call(serve_session, req).await)
}
}
}
};
});
Ok::<_, Infallible>(service_fn(service))
if let Err(err) = http1::Builder::new()
.serve_connection(io, service)
.with_upgrades()
.await
{
log::error!("Error serving connection: {err}");
}
});
}
});
let rt = Runtime::new().unwrap();
let _guard = rt.enter();
let server = Server::bind(&address).serve(make_service);
rt.block_on(server).unwrap();
}
}

View file

@ -6,7 +6,9 @@
use std::{borrow::Cow, sync::Arc, time::Duration};
use hyper::{header, Body, Method, Request, Response, StatusCode};
use bytes::Bytes;
use http_body_util::Full;
use hyper::{body::Incoming, header, Method, Request, Response, StatusCode};
use rbx_dom_weak::types::{Ref, Variant};
use ritz::{html, Fragment, HtmlContent, HtmlSelfClosingTag};
@ -20,7 +22,10 @@ use crate::{
},
};
pub async fn call(serve_session: Arc<ServeSession>, request: Request<Body>) -> Response<Body> {
pub async fn call(
serve_session: Arc<ServeSession>,
request: Request<Incoming>,
) -> Response<Full<Bytes>> {
let service = UiService::new(serve_session);
match (request.method(), request.uri().path()) {
@ -44,21 +49,21 @@ impl UiService {
UiService { serve_session }
}
fn handle_logo(&self) -> Response<Body> {
fn handle_logo(&self) -> Response<Full<Bytes>> {
Response::builder()
.header(header::CONTENT_TYPE, "image/png")
.body(Body::from(assets::logo()))
.body(Full::new(Bytes::from(assets::logo())))
.unwrap()
}
fn handle_icon(&self) -> Response<Body> {
fn handle_icon(&self) -> Response<Full<Bytes>> {
Response::builder()
.header(header::CONTENT_TYPE, "image/png")
.body(Body::from(assets::icon()))
.body(Full::new(Bytes::from(assets::icon())))
.unwrap()
}
fn handle_home(&self) -> Response<Body> {
fn handle_home(&self) -> Response<Full<Bytes>> {
let page = self.normal_page(html! {
<div class="button-list">
{ Self::button("Rojo Documentation", "https://rojo.space/docs") }
@ -68,11 +73,11 @@ impl UiService {
Response::builder()
.header(header::CONTENT_TYPE, "text/html")
.body(Body::from(format!("<!DOCTYPE html>{}", page)))
.body(Full::new(Bytes::from(format!("<!DOCTYPE html>{}", page))))
.unwrap()
}
fn handle_show_instances(&self) -> Response<Body> {
fn handle_show_instances(&self) -> Response<Full<Bytes>> {
let tree = self.serve_session.tree();
let root_id = tree.get_root_id();
@ -82,7 +87,7 @@ impl UiService {
Response::builder()
.header(header::CONTENT_TYPE, "text/html")
.body(Body::from(format!("<!DOCTYPE html>{}", page)))
.body(Full::new(Bytes::from(format!("<!DOCTYPE html>{}", page))))
.unwrap()
}

View file

@ -1,11 +1,13 @@
use hyper::{header::CONTENT_TYPE, Body, Response, StatusCode};
use bytes::Bytes;
use http_body_util::Full;
use hyper::{header::CONTENT_TYPE, Response, StatusCode};
use serde::{Deserialize, Serialize};
pub fn msgpack_ok<T: Serialize>(value: T) -> Response<Body> {
pub fn msgpack_ok<T: Serialize>(value: T) -> Response<Full<Bytes>> {
msgpack(value, StatusCode::OK)
}
pub fn msgpack<T: Serialize>(value: T, code: StatusCode) -> Response<Body> {
pub fn msgpack<T: Serialize>(value: T, code: StatusCode) -> Response<Full<Bytes>> {
let mut serialized = Vec::new();
let mut serializer = rmp_serde::Serializer::new(&mut serialized)
.with_human_readable()
@ -15,14 +17,14 @@ pub fn msgpack<T: Serialize>(value: T, code: StatusCode) -> Response<Body> {
return Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header(CONTENT_TYPE, "text/plain")
.body(Body::from(err.to_string()))
.body(Full::new(Bytes::from(err.to_string())))
.unwrap();
};
Response::builder()
.status(code)
.header(CONTENT_TYPE, "application/msgpack")
.body(Body::from(serialized))
.body(Full::new(Bytes::from(serialized)))
.unwrap()
}
@ -45,14 +47,14 @@ pub fn deserialize_msgpack<'a, T: Deserialize<'a>>(
T::deserialize(&mut deserializer)
}
pub fn json<T: Serialize>(value: T, code: StatusCode) -> Response<Body> {
pub fn json<T: Serialize>(value: T, code: StatusCode) -> Response<Full<Bytes>> {
let serialized = match serde_json::to_string(&value) {
Ok(v) => v,
Err(err) => {
return Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header(CONTENT_TYPE, "text/plain")
.body(Body::from(err.to_string()))
.body(Full::new(Bytes::from(err.to_string())))
.unwrap();
}
};
@ -60,6 +62,6 @@ pub fn json<T: Serialize>(value: T, code: StatusCode) -> Response<Body> {
Response::builder()
.status(code)
.header(CONTENT_TYPE, "application/json")
.body(Body::from(serialized))
.body(Full::new(Bytes::from(serialized)))
.unwrap()
}