### Client::request Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Client.html Start building a Request with the Method and Url. ```APIDOC ## pub fn request(&self, method: Method, url: U) -> RequestBuilder ### Description Start building a Request with the Method and Url. Returns a RequestBuilder, which allows setting headers and the request body before sending. ``` -------------------------------- ### Demonstrate ambiguous Pin conversion Source: https://docs.rs/server_fn/0.8.2/server_fn/redirect/type.RedirectHook.html An example of an implementation that causes ambiguity when calling Pin::from. ```rust struct Foo; // A type defined in this crate. impl From> for Pin { fn from(_: Box<()>) -> Pin { Pin::new(Foo) } } let foo = Box::new(()); let bar = Pin::from(foo); ``` -------------------------------- ### Server Function Expansion Example Source: https://docs.rs/server_fn/0.8.2/server_fn/trait.ServerFn.html Demonstrates how the #[server] macro expands a function into a struct implementing the ServerFn trait. ```rust #[server] pub async fn my_function(foo: String, bar: usize) -> Result { Ok(foo.len() + bar) } ``` ```rust #[derive(Serialize, Deserialize)] pub struct MyFunction { foo: String, bar: usize } impl ServerFn for MyFunction { async fn run_body() -> Result { Ok(foo.len() + bar) } // etc. } ``` -------------------------------- ### Implement FromReq for Json Source: https://docs.rs/server_fn/0.8.2/server_fn/codec/trait.FromReq.html An example implementation of FromReq for JSON, demonstrating body extraction and deserialization. ```rust impl FromReq for T where // require the Request implement `Req` Request: Req + Send + 'static, // require that the type can be deserialized with `serde` T: DeserializeOwned, E: FromServerFnError, { async fn from_req( req: Request, ) -> Result { // try to convert the body of the request into a `String` let string_data = req.try_into_string().await?; // deserialize the data serde_json::from_str(&string_data) .map_err(|e| ServerFnErrorErr::Args(e.to_string()).into_app_error()) } } ``` -------------------------------- ### Allocate a Box with a custom allocator Source: https://docs.rs/server_fn/0.8.2/server_fn/redirect/type.RedirectHook.html Examples of allocating memory using the nightly allocator API. ```rust #![feature(allocator_api)] use std::alloc::System; let five = Box::new_in(5, System); ``` ```rust #![feature(allocator_api)] use std::alloc::System; ``` -------------------------------- ### Implement IntoReq for Json Source: https://docs.rs/server_fn/0.8.2/server_fn/codec/trait.IntoReq.html Example implementation of IntoReq for JSON serialization, demonstrating the use of ClientReq to create a POST request. ```rust impl IntoReq for T where Request: ClientReq, T: Serialize + Send, { fn into_req( self, path: &str, accepts: &str, ) -> Result { // try to serialize the data let data = serde_json::to_string(&self) .map_err(|e| ServerFnErrorErr::Serialization(e.to_string()).into_app_error())?; // and use it as the body of a POST request Request::try_new_post(path, accepts, Json::CONTENT_TYPE, data) } } ``` -------------------------------- ### FormatType Implementations Source: https://docs.rs/server_fn/0.8.2/server_fn/trait.FormatType.html Examples of implementing FormatType for various encoding types, specifying their respective binary or text formats. ```rust impl FormatType for CborEncoding { const FORMAT_TYPE: Format = Format::Binary } ``` ```rust impl FormatType for JsonEncoding { const FORMAT_TYPE: Format = Format::Text } ``` ```rust impl FormatType for MsgPackEncoding { const FORMAT_TYPE: Format = Format::Binary } ``` ```rust impl FormatType for PostcardEncoding { const FORMAT_TYPE: Format = Format::Binary } ``` ```rust impl FormatType for RkyvEncoding { const FORMAT_TYPE: Format = Format::Binary } ``` ```rust impl FormatType for SerdeLiteEncoding { const FORMAT_TYPE: Format = Format::Text } ``` ```rust impl FormatType for ServerFnErrorEncoding { const FORMAT_TYPE: Format = Format::Text } ``` -------------------------------- ### Using Http Protocol in Server Functions Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Http.html Example of applying the Http protocol with GetUrl and Json encodings to a server function. ```rust use serde::{Serialize, Deserialize}; use server_fn::{Http, ServerFnError, codec::{Json, GetUrl}}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { user: String, message: String, } // The http protocol can be used on any server function that accepts and returns arguments that implement // the [`IntoReq`] and [`FromRes`] traits. // // In this case, the input and output encodings are [`GetUrl`] and [`Json`], respectively which requires // the items to implement [`IntoReq`] and [`FromRes`]. Both of those implementations // require the items to implement [`Serialize`] and [`Deserialize`]. #[server(protocol = Http)] async fn echo_http( input: Message, ) -> Result { Ok(input) } ``` -------------------------------- ### Implementing FromRes for JSON Source: https://docs.rs/server_fn/0.8.2/server_fn/codec/trait.FromRes.html An example implementation of FromRes for JSON, showing how to extract a string from a response and deserialize it. ```rust impl FromRes for T where Response: ClientRes + Send, T: DeserializeOwned + Send, E: FromServerFnError, { async fn from_res( res: Response, ) -> Result { // extracts the request body let data = res.try_into_string().await?; // and tries to deserialize it as JSON serde_json::from_str(&data) .map_err(|e| ServerFnErrorErr::Deserialization(e.to_string()).into_app_error()) } } ``` -------------------------------- ### Axum Server Function Backend Source: https://docs.rs/server_fn/0.8.2/src/server_fn/lib.rs.html Integration setup for Axum, including the server function map and backend implementation. ```rust pub mod axum { use crate::{ error::FromServerFnError, middleware::BoxedService, LazyServerFnMap, Protocol, Server, ServerFn, ServerFnTraitObj, }; use axum::body::Body; use http::{Method, Request, Response, StatusCode}; use std::future::Future; static REGISTERED_SERVER_FUNCTIONS: LazyServerFnMap< Request, Response, > = initialize_server_fn_map!(Request, Response); /// The axum server function backend pub struct AxumServerFnBackend; impl Server for AxumServerFnBackend where Error: FromServerFnError + Send + Sync, InputStreamError: FromServerFnError + Send + Sync, OutputStreamError: FromServerFnError + Send + Sync, { type Request = Request; type Response = Response; #[allow(unused_variables)] fn spawn( future: impl Future + Send + 'static, ) -> Result<(), Error> { #[cfg(feature = "axum")] { tokio::spawn(future); Ok(()) } #[cfg(not(feature = "axum"))] { Err(Error::from_server_fn_error( crate::error::ServerFnErrorErr::Request( "No async runtime available. You need to either \ ``` -------------------------------- ### Client::get Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Client.html Convenience method to make a GET request to a URL. ```APIDOC ## pub fn get(&self, url: U) -> RequestBuilder ### Description Convenience method to make a GET request to a URL. Fails if the supplied URL cannot be parsed. ``` -------------------------------- ### Implement Websocket protocol Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Websocket.html Example of using the Websocket protocol with JSON encoding on a server function that processes a stream of messages. ```rust use server_fn::{ServerFnError, BoxedStream, Websocket, codec::JsonEncoding}; use serde::{Serialize, Deserialize}; #[derive(Clone, Serialize, Deserialize)] pub struct Message { user: String, message: String, } // The websocket protocol can be used on any server function that accepts and returns a [`BoxedStream`] // with items that can be encoded by the input and output encoding generics. // // In this case, the input and output encodings are [`Json`] and [`Json`], respectively which requires // the items to implement [`Serialize`] and [`Deserialize`]. #[server(protocol = Websocket)] async fn echo_websocket( input: BoxedStream, ) -> Result, ServerFnError> { Ok(input.into()) } ``` -------------------------------- ### Implement Layer for Request and Response Source: https://docs.rs/server_fn/0.8.2/server_fn/middleware/trait.Layer.html Example of a trait implementation for a generic middleware layer handling Request and Response types. ```rust impl Layer, Response> for L where L: Layer, Response>> + Sync + Send + 'static, L::Service: Service, Response> + Send + 'static, ``` -------------------------------- ### Implement ContentType for encodings Source: https://docs.rs/server_fn/0.8.2/server_fn/trait.ContentType.html Examples of implementing the ContentType trait for various encoding types. ```rust impl ContentType for CborEncoding { const CONTENT_TYPE: &'static str = "application/cbor" } ``` ```rust impl ContentType for DeleteUrl { const CONTENT_TYPE: &'static str = "application/x-www-form-urlencoded" } ``` ```rust impl ContentType for GetUrl { const CONTENT_TYPE: &'static str = "application/x-www-form-urlencoded" } ``` ```rust impl ContentType for JsonEncoding { const CONTENT_TYPE: &'static str = "application/json" } ``` ```rust impl ContentType for MsgPackEncoding { const CONTENT_TYPE: &'static str = "application/msgpack" } ``` ```rust impl ContentType for MultipartFormData { const CONTENT_TYPE: &'static str = "multipart/form-data" } ``` ```rust impl ContentType for PatchUrl { const CONTENT_TYPE: &'static str = "application/x-www-form-urlencoded" } ``` ```rust impl ContentType for PostUrl { const CONTENT_TYPE: &'static str = "application/x-www-form-urlencoded" } ``` ```rust impl ContentType for PostcardEncoding { const CONTENT_TYPE: &'static str = "application/x-postcard" } ``` ```rust impl ContentType for PutUrl { const CONTENT_TYPE: &'static str = "application/x-www-form-urlencoded" } ``` ```rust impl ContentType for RkyvEncoding { const CONTENT_TYPE: &'static str = "application/rkyv" } ``` ```rust impl ContentType for SerdeLiteEncoding { const CONTENT_TYPE: &'static str = "application/json" } ``` ```rust impl ContentType for Streaming { const CONTENT_TYPE: &'static str = "application/octet-stream" } ``` ```rust impl ContentType for StreamingText { const CONTENT_TYPE: &'static str = "text/plain" } ``` ```rust impl ContentType for ServerFnErrorEncoding { const CONTENT_TYPE: &'static str = "text/plain" } ``` -------------------------------- ### Json Implementation of IntoRes Source: https://docs.rs/server_fn/0.8.2/server_fn/codec/trait.IntoRes.html Example implementation of IntoRes for the Json encoding type, demonstrating serialization and response creation. ```rust impl IntoRes for T where Response: Res, T: Serialize + Send, E: FromServerFnError, { async fn into_res(self) -> Result { // try to serialize the data let data = serde_json::to_string(&self) .map_err(|e| ServerFnErrorErr::Serialization(e.to_string()).into())?; // and use it as the body of a response Response::try_from_string(Json::CONTENT_TYPE, data) } } ``` -------------------------------- ### Convert Box to NonNull Pointer with Allocator Source: https://docs.rs/server_fn/0.8.2/server_fn/redirect/type.RedirectHook.html Shows how to consume a Box into a NonNull pointer and allocator, with examples for automatic and manual memory cleanup. ```rust #![feature(allocator_api, box_vec_non_null)] use std::alloc::System; let x = Box::new_in(String::from("Hello"), System); let (non_null, alloc) = Box::into_non_null_with_allocator(x); let x = unsafe { Box::from_non_null_in(non_null, alloc) }; ``` ```rust #![feature(allocator_api, box_vec_non_null)] use std::alloc::{Allocator, Layout, System}; let x = Box::new_in(String::from("Hello"), System); let (non_null, alloc) = Box::into_non_null_with_allocator(x); unsafe { non_null.drop_in_place(); alloc.deallocate(non_null.cast::(), Layout::new::()); } ``` -------------------------------- ### Managing Vector Length Manually Source: https://docs.rs/server_fn/0.8.2/server_fn/type.MiddlewareSet.html Examples of using set_len for FFI buffer management and the risks of memory leaks when using it on vectors containing complex types. ```rust pub fn get_dictionary(&self) -> Option> { // Per the FFI method's docs, "32768 bytes is always enough". let mut dict = Vec::with_capacity(32_768); let mut dict_length = 0; // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that: // 1. `dict_length` elements were initialized. // 2. `dict_length` <= the capacity (32_768) // which makes `set_len` safe to call. unsafe { // Make the FFI call... let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length); if r == Z_OK { // ...and update the length to what was initialized. dict.set_len(dict_length); Some(dict) } else { None } } } ``` ```rust let mut vec = vec![vec![1, 0, 0], vec![0, 1, 0], vec![0, 0, 1]]; // SAFETY: // 1. `old_len..0` is empty so no elements need to be initialized. // 2. `0 <= capacity` always holds whatever `capacity` is. unsafe { vec.set_len(0); } ``` -------------------------------- ### Client::new Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Client.html Constructs a new Client. Panics if TLS backend or system resolver initialization fails. ```APIDOC ## pub fn new() -> Client ### Description Constructs a new Client. This method panics if a TLS backend cannot be initialized or the resolver cannot load the system configuration. ``` -------------------------------- ### Get length Source: https://docs.rs/server_fn/0.8.2/server_fn/type.MiddlewareSet.html Returns the number of elements in the vector. ```rust let a = vec![1, 2, 3]; assert_eq!(a.len(), 3); ``` -------------------------------- ### Get slice length Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Returns the number of elements in the slice. ```rust let a = [1, 2, 3]; assert_eq!(a.len(), 3); ``` -------------------------------- ### Constructing a Vec with a custom allocator Source: https://docs.rs/server_fn/0.8.2/server_fn/type.MiddlewareSet.html Demonstrates initializing a vector with a specific capacity and allocator, showing how length and capacity behave during push operations. ```rust #![feature(allocator_api)] use std::alloc::System; let mut vec = Vec::with_capacity_in(10, System); // The vector contains no items, even though it has capacity for more assert_eq!(vec.len(), 0); assert!(vec.capacity() >= 10); // These are all done without reallocating... for i in 0..10 { vec.push(i); } assert_eq!(vec.len(), 10); assert!(vec.capacity() >= 10); // ...but this may make the vector reallocate vec.push(11); assert_eq!(vec.len(), 11); assert!(vec.capacity() >= 11); // A vector of a zero-sized type will always over-allocate, since no // allocation is necessary let vec_units = Vec::<(), System>::with_capacity_in(10, System); assert_eq!(vec_units.capacity(), usize::MAX); ``` -------------------------------- ### Form::new Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Form.html Creates a new, empty async Form instance. ```APIDOC ## Form::new() ### Description Creates a new async Form without any content. ### Signature `pub fn new() -> Form` ``` -------------------------------- ### Assert equality for Box Source: https://docs.rs/server_fn/0.8.2/server_fn/redirect/type.RedirectHook.html Example usage of assertion for a boxed value. ```rust // And no allocation occurred assert_eq!(yp, &*y); ``` -------------------------------- ### Get last element Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Returns the last element of the slice, or None if it is empty. ```rust let v = [10, 40, 30]; assert_eq!(Some(&30), v.last()); let w: &[i32] = &[]; assert_eq!(None, w.last()); ``` -------------------------------- ### Get first element Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Returns the first element of the slice, or None if it is empty. ```rust let v = [10, 40, 30]; assert_eq!(Some(&10), v.first()); let w: &[i32] = &[]; assert_eq!(None, w.first()); ``` -------------------------------- ### Iterate over slice Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Returns an iterator that yields all items in the slice from start to end. ```rust let x = &[1, 2, 4]; let mut iterator = x.iter(); assert_eq!(iterator.next(), Some(&1)); assert_eq!(iterator.next(), Some(&2)); assert_eq!(iterator.next(), Some(&4)); assert_eq!(iterator.next(), None); ``` -------------------------------- ### Trim ASCII start Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Removes leading ASCII whitespace bytes from the slice. ```rust assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n"); assert_eq!(b" ".trim_ascii_start(), b""); assert_eq!(b"".trim_ascii_start(), b""); ``` -------------------------------- ### Client::builder Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Client.html Creates a ClientBuilder to configure a Client. ```APIDOC ## pub fn builder() -> ClientBuilder ### Description Creates a ClientBuilder to configure a Client. This is equivalent to ClientBuilder::new(). ``` -------------------------------- ### Get URL Scheme Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Url.html Returns the lower-cased scheme of the URL without the colon delimiter. ```rust use url::Url; let url = Url::parse("file:///tmp/foo")?; assert_eq!(url.scheme(), "file"); ``` -------------------------------- ### Defining and inspecting HTTP methods Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Method.html Demonstrates creating a Method from bytes and checking properties like idempotency and string representation. ```rust use http::Method; assert_eq!(Method::GET, Method::from_bytes(b"GET").unwrap()); assert!(Method::GET.is_idempotent()); assert_eq!(Method::POST.as_str(), "POST"); ``` -------------------------------- ### Implement WebSocket Client Function Execution Source: https://docs.rs/server_fn/0.8.2/src/server_fn/lib.rs.html Opens a WebSocket connection, forwards the input stream to the server, and returns the output stream. ```rust fn run_client( path: &str, input: Input, ) -> impl Future< Output = Result, Error>, > + Send { let input = input.into(); async move { let (stream, sink) = Client::open_websocket(path).await?; // Forward the input stream to the websocket Client::spawn(async move { pin_mut!(input); pin_mut!(sink); while let Some(input) = input.stream.next().await { let result = match input { Ok(input) => { InputEncoding::encode(&input).map_err(|e| { InputStreamError::from_server_fn_error( ServerFnErrorErr::Serialization( e.to_string(), ), ) .ser() }) } Err(err) => Err(err.ser()), }; let result = serialize_result(result); if sink.send(result).await.is_err() { break; } } }); // Return the output stream let stream = stream.map(|request_bytes| { let request_bytes = request_bytes .map(|bytes| deserialize_result::(bytes)) .unwrap_or_else(Err); match request_bytes { Ok(request_bytes) => OutputEncoding::decode(request_bytes) .map_err(|e| { OutputStreamError::from_server_fn_error( ServerFnErrorErr::Deserialization( e.to_string(), ), ) ``` -------------------------------- ### Iterate over chunks from the end with rchunks Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Returns an iterator over chunks of a specified size starting from the end of the slice. ```rust let slice = ['l', 'o', 'r', 'e', 'm']; let mut iter = slice.rchunks(2); assert_eq!(iter.next().unwrap(), &['e', 'm']); assert_eq!(iter.next().unwrap(), &['o', 'r']); assert_eq!(iter.next().unwrap(), &['l']); assert!(iter.next().is_none()); ``` -------------------------------- ### Retrieve host string Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Url.html Returns the string representation of the host, handling punycode or percent encoding as needed. ```rust use url::Url; let url = Url::parse("https://127.0.0.1/index.html")?; assert_eq!(url.host_str(), Some("127.0.0.1")); let url = Url::parse("ftp://rms@example.com")?; assert_eq!(url.host_str(), Some("example.com")); let url = Url::parse("unix:/run/foo.socket")?; assert_eq!(url.host_str(), None); let url = Url::parse("data:text/plain,Stuff")?; assert_eq!(url.host_str(), None); ``` -------------------------------- ### Create and Manage ServerFnTraitObj Source: https://docs.rs/server_fn/0.8.2/src/server_fn/lib.rs.html Methods for initializing, accessing, and boxing server function trait objects. ```rust impl ServerFnTraitObj { /// Converts the relevant parts of a server function into a trait object. pub const fn new< S: ServerFn< Server: crate::Server< S::Error, S::InputStreamError, S::OutputStreamError, Request = Req, Response = Res, >, >, >( handler: fn(Req) -> Pin + Send>>, ) -> Self where Req: crate::Req< S::Error, S::InputStreamError, S::OutputStreamError, WebsocketResponse = Res, > + Send + 'static, Res: crate::TryRes + Send + 'static, { Self { path: S::PATH, method: S::Protocol::METHOD, handler, middleware: S::middlewares, ser: |e| S::Error::from_server_fn_error(e).ser(), } } /// The path of the server function. pub fn path(&self) -> &'static str { self.path } /// The HTTP method the server function expects. pub fn method(&self) -> Method { self.method.clone() } /// The handler for this server function. pub fn handler(&self, req: Req) -> impl Future + Send { (self.handler)(req) } /// The set of middleware that should be applied to this function. pub fn middleware(&self) -> MiddlewareSet { (self.middleware)() } /// Converts the server function into a boxed service. pub fn boxed(self) -> BoxedService where Self: Service, Req: 'static, Res: 'static, { BoxedService::new(self.ser, self) } } ``` -------------------------------- ### Get first chunk Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Returns an array reference to the first N items in the slice, or None if the slice is too short. ```rust let u = [10, 40, 30]; assert_eq!(Some(&[10, 40]), u.first_chunk::<2>()); let v: &[i32] = &[10]; assert_eq!(None, v.first_chunk::<2>()); let w: &[i32] = &[]; assert_eq!(Some(&[]), w.first_chunk::<0>()); ``` -------------------------------- ### Establish WebSocket Connection for Server Functions Source: https://docs.rs/server_fn/0.8.2/src/server_fn/client.rs.html Converts HTTP/HTTPS URLs to WS/WSS and establishes a WebSocket stream using tokio-tungstenite. Maps stream errors to ServerFnError types. ```rust let mut websocket_server_url = get_server_url().to_string(); if let Some(postfix) = websocket_server_url.strip_prefix("http://") { websocket_server_url = format!("ws://{postfix}"); } else if let Some(postfix) = websocket_server_url.strip_prefix("https://") { websocket_server_url = format!("wss://{postfix}"); } let url = format!("{websocket_server_url}{path}"); let (ws_stream, _) = tokio_tungstenite::connect_async(url).await.map_err(|e| { Error::from_server_fn_error(ServerFnErrorErr::Request( e.to_string(), )) })?; let (write, read) = ws_stream.split(); Ok(( read.map(|msg| match msg { Ok(msg) => Ok(msg.into_data()), Err(e) => Err(OutputStreamError::from_server_fn_error( ServerFnErrorErr::Request(e.to_string()), ) .ser()), }), write.with(|msg: Bytes| async move { Ok::< tokio_tungstenite::tungstenite::Message, tokio_tungstenite::tungstenite::Error, >( tokio_tungstenite::tungstenite::Message::Binary(msg) ) }), )) ``` -------------------------------- ### Verify slice prefixes with starts_with Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Checks if a slice starts with a given prefix. Returns true if the prefix is empty. ```rust let v = [10, 40, 30]; assert!(v.starts_with(&[10])); assert!(v.starts_with(&[10, 40])); assert!(v.starts_with(&v)); assert!(!v.starts_with(&[50])); assert!(!v.starts_with(&[10, 50])); ``` ```rust let v = &[10, 40, 30]; assert!(v.starts_with(&[])); let v: &[u8] = &[]; assert!(v.starts_with(&[])); ``` -------------------------------- ### Url::join Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Url.html Parses a string as a URL using the current instance as the base. ```APIDOC ## pub fn join(&self, input: &str) -> Result ### Description Parses a string as a URL, using the current URL instance as the base. This is useful for resolving relative paths. ### Parameters - **input** (&str) - Required - The URL or path string to join with the base. ### Returns - **Result** - Returns the joined Url object or a ParseError. ``` -------------------------------- ### Extract elements based on a predicate Source: https://docs.rs/server_fn/0.8.2/server_fn/type.MiddlewareSet.html Demonstrates the logic equivalent to extract_if and provides examples for splitting or filtering elements. ```rust let mut i = range.start; let end_items = vec.len() - range.end; while i < vec.len() - end_items { if some_predicate(&mut vec[i]) { let val = vec.remove(i); // your code here } else { i += 1; } } ``` ```rust let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; let evens = numbers.extract_if(.., |x| *x % 2 == 0).collect::>(); let odds = numbers; assert_eq!(evens, vec![2, 4, 6, 8, 14]); assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); ``` ```rust let mut items = vec![0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2]; let ones = items.extract_if(7.., |x| *x == 1).collect::>(); assert_eq!(items, vec![0, 0, 0, 0, 0, 0, 0, 2, 2, 2]); assert_eq!(ones.len(), 3); ``` -------------------------------- ### Service::run Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.ServerFnTraitObj.html Converts a request into a response by executing the server function logic. ```APIDOC ## fn run(&mut self, req: Req, _ser: fn(ServerFnErrorErr) -> Bytes) -> Pin + Send>> ### Description Converts a request into a response. This method is part of the Service trait implementation for ServerFnTraitObj. ### Parameters - **req** (Req) - The request object to be processed. - **_ser** (fn(ServerFnErrorErr) -> Bytes) - A function pointer used for error serialization. ### Returns - **Pin + Send>>** - A pinned future that resolves to the response. ``` -------------------------------- ### Request Construction Methods Source: https://docs.rs/server_fn/0.8.2/server_fn/request/browser/struct.Request.html Methods to initialize a new request with a specific HTTP method and URL. ```APIDOC ## Request::get(url: &str) ## Request::post(url: &str) ## Request::put(url: &str) ## Request::delete(url: &str) ## Request::patch(url: &str) ### Description Creates a new Request instance for the specified HTTP method and URL, returning a RequestBuilder. ### Parameters - **url** (&str) - Required - The target URL for the request. ``` -------------------------------- ### Split a slice from the end using a predicate Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Splits a slice into an iterator of subslices starting from the end, excluding the matched elements. ```rust let slice = [11, 22, 33, 0, 44, 55]; let mut iter = slice.rsplit(|num| *num == 0); assert_eq!(iter.next().unwrap(), &[44, 55]); assert_eq!(iter.next().unwrap(), &[11, 22, 33]); assert_eq!(iter.next(), None); ``` ```rust let v = &[0, 1, 1, 2, 3, 5, 8]; let mut it = v.rsplit(|n| *n % 2 == 0); assert_eq!(it.next().unwrap(), &[]); assert_eq!(it.next().unwrap(), &[3, 5]); assert_eq!(it.next().unwrap(), &[1, 1]); assert_eq!(it.next().unwrap(), &[]); assert_eq!(it.next(), None); ``` -------------------------------- ### get_server_fn_service(path: &str, method: &Method) Source: https://docs.rs/server_fn/0.8.2/server_fn/actix/fn.get_server_fn_service.html Retrieves the server function at the specified path and method as a BoxedService. ```APIDOC ## Function: get_server_fn_service ### Description Returns the server function at the given path as a service that can be modified. ### Signature `pub fn get_server_fn_service(path: &str, method: &Method) -> Option>` ### Parameters - **path** (&str) - The path of the server function. - **method** (&Method) - The HTTP method associated with the server function. ### Returns - **Option>** - Returns the service if found, otherwise None. ``` -------------------------------- ### Split slice into chunks from the end with as_rchunks Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Splits a slice into N-element arrays starting from the end, returning a remainder and the chunks. ```rust let slice = ['l', 'o', 'r', 'e', 'm']; let (remainder, chunks) = slice.as_rchunks(); assert_eq!(remainder, &['l']); assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]); ``` -------------------------------- ### Request::new Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Request.html Constructs a new Request instance with the specified HTTP method and URL. ```APIDOC ## Request::new(method: Method, url: Url) ### Description Constructs a new request instance. ### Parameters - **method** (Method) - Required - The HTTP method for the request. - **url** (Url) - Required - The target URL for the request. ``` -------------------------------- ### Define a server function with a custom HTTP protocol Source: https://docs.rs/server_fn/0.8.2/src/server_fn/lib.rs.html Demonstrates using the Http protocol with specific input and output encodings for a server function. ```rust # use server_fn_macro_default::server; use serde::{Serialize, Deserialize}; use server_fn::{Http, ServerFnError, codec::{Json, GetUrl}}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { user: String, message: String, } // The http protocol can be used on any server function that accepts and returns arguments that implement // the [`IntoReq`] and [`FromRes`] traits. // // In this case, the input and output encodings are [`GetUrl`] and [`Json`], respectively which requires // the items to implement [`IntoReq`] and [`FromRes`]. Both of those implementations // require the items to implement [`Serialize`] and [`Deserialize`]. # #[cfg(feature = "browser")] { #[server(protocol = Http)] async fn echo_http( input: Message, ) -> Result { Ok(input) } # } ``` -------------------------------- ### Convert VecDeque to Vec Source: https://docs.rs/server_fn/0.8.2/server_fn/type.MiddlewareSet.html Converts a VecDeque into a Vec, noting that data movement may occur if the buffer is not at the start of the allocation. ```rust use std::collections::VecDeque; // This one is *O*(1). let deque: VecDeque<_> = (1..5).collect(); let ptr = deque.as_slices().0.as_ptr(); let vec = Vec::from(deque); assert_eq!(vec, [1, 2, 3, 4]); assert_eq!(vec.as_ptr(), ptr); // This one needs data rearranging. let mut deque: VecDeque<_> = (1..5).collect(); deque.push_front(9); deque.push_front(8); let ptr = deque.as_slices().1.as_ptr(); let vec = Vec::from(deque); assert_eq!(vec, [8, 9, 1, 2, 3, 4]); assert_eq!(vec.as_ptr(), ptr); ``` -------------------------------- ### Box::try_new_uninit usage Source: https://docs.rs/server_fn/0.8.2/server_fn/redirect/type.RedirectHook.html Attempts to construct a new box with uninitialized contents on the heap. Requires allocator_api feature. ```rust #![feature(allocator_api)] let mut five = Box::::try_new_uninit()?; // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5); ``` -------------------------------- ### Box::new_uninit usage Source: https://docs.rs/server_fn/0.8.2/server_fn/redirect/type.RedirectHook.html Constructs a new box with uninitialized contents, requiring manual initialization. ```rust let mut five = Box::::new_uninit(); // Deferred initialization: five.write(5); let five = unsafe { five.assume_init() }; assert_eq!(*five, 5) ``` -------------------------------- ### Implement TryRes for Response Source: https://docs.rs/server_fn/0.8.2/src/server_fn/response/generic.rs.html Provides methods to construct HTTP responses from strings, bytes, or streams while handling potential errors. ```rust impl TryRes for Response where E: Send + Sync + FromServerFnError, { fn try_from_string(content_type: &str, data: String) -> Result { let builder = http::Response::builder(); builder .status(200) .header(http::header::CONTENT_TYPE, content_type) .body(data.into()) .map_err(|e| { ServerFnErrorErr::Response(e.to_string()).into_app_error() }) } fn try_from_bytes(content_type: &str, data: Bytes) -> Result { let builder = http::Response::builder(); builder .status(200) .header(http::header::CONTENT_TYPE, content_type) .body(Body::Sync(data)) .map_err(|e| { ServerFnErrorErr::Response(e.to_string()).into_app_error() }) } fn try_from_stream( content_type: &str, data: impl Stream> + Send + 'static, ) -> Result { let builder = http::Response::builder(); builder .status(200) .header(http::header::CONTENT_TYPE, content_type) .body(Body::Async(Box::pin( data.map_err(|e| ServerFnErrorWrapper(E::de(e))) .map_err(Error::from), ))) .map_err(|e| { ServerFnErrorErr::Response(e.to_string()).into_app_error() }) } } ``` -------------------------------- ### Manipulate Bytes with slicing and splitting Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Demonstrates creating a Bytes instance and performing slice and split operations. ```rust use bytes::Bytes; let mut mem = Bytes::from("Hello world"); let a = mem.slice(0..5); assert_eq!(a, "Hello"); let b = mem.split_to(6); assert_eq!(mem, "world"); assert_eq!(b, "Hello "); ``` -------------------------------- ### Convert URL to String Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Url.html Consumes the Url instance and returns its string representation. ```rust use url::Url; let url_str = "https://example.net/"; let url = Url::parse(url_str)?; assert_eq!(String::from(url), url_str); ``` -------------------------------- ### Get last chunk of slice Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Retrieves an array reference to the last N items in the slice, returning None if the slice is too short. ```rust let u = [10, 40, 30]; assert_eq!(Some(&[40, 30]), u.last_chunk::<2>()); let v: &[i32] = &[10]; assert_eq!(None, v.last_chunk::<2>()); let w: &[i32] = &[]; assert_eq!(Some(&[]), w.last_chunk::<0>()); ``` -------------------------------- ### GetUrl Codec Source: https://docs.rs/server_fn/0.8.2/server_fn/codec/struct.GetUrl.html The GetUrl codec is used to encode server function arguments into a URL query string for HTTP GET requests. ```APIDOC ## GetUrl Codec ### Description The `GetUrl` struct is a codec implementation that serializes arguments as a URL-encoded query string for use in `GET` requests. ### HTTP Method GET ### Content-Type application/x-www-form-urlencoded ``` -------------------------------- ### Constructing a Box from NonNull with an Allocator Source: https://docs.rs/server_fn/0.8.2/server_fn/redirect/type.RedirectHook.html Demonstrates recreating a Box from a NonNull pointer and manually allocating memory using the system allocator. ```rust #![feature(allocator_api, box_vec_non_null)] use std::alloc::System; let x = Box::new_in(5, System); let (non_null, alloc) = Box::into_non_null_with_allocator(x); let x = unsafe { Box::from_non_null_in(non_null, alloc) }; ``` ```rust #![feature(allocator_api, box_vec_non_null, slice_ptr_get)] use std::alloc::{Allocator, Layout, System}; unsafe { let non_null = System.allocate(Layout::new::())?.cast::(); // In general .write is required to avoid attempting to destruct // the (uninitialized) previous contents of `non_null`. non_null.write(5); let x = Box::from_non_null_in(non_null, System); } ``` -------------------------------- ### Leak a Box into a mutable reference Source: https://docs.rs/server_fn/0.8.2/server_fn/redirect/type.RedirectHook.html Examples showing how to consume a Box to obtain a static mutable reference for both sized and unsized data. ```rust let x = Box::new(41); let static_ref: &'static mut usize = Box::leak(x); *static_ref += 1; assert_eq!(*static_ref, 42); ``` ```rust let x = vec![1, 2, 3].into_boxed_slice(); let static_ref = Box::leak(x); static_ref[0] = 4; assert_eq!(*static_ref, [4, 2, 3]); ``` -------------------------------- ### poll_ready(&mut self, _cx: &mut Context<'_>) Source: https://docs.rs/server_fn/0.8.2/server_fn/request/reqwest/struct.Client.html Checks if the service is ready to process new requests. ```APIDOC ## fn poll_ready(&mut self, _cx: &mut Context<'_>) ### Description Returns Poll::Ready(Ok(())) when the service is able to process requests. ### Parameters - **_cx** (&mut Context<'_>) - Required - The task context used for polling. ``` -------------------------------- ### Actix Middleware Implementation Source: https://docs.rs/server_fn/0.8.2/src/server_fn/middleware/mod.rs.html Partial implementation for Actix web framework integration. ```rust 126#[cfg(feature = "actix")] 127mod actix { 128 use crate::{ 129 error::ServerFnErrorErr, 130 request::actix::ActixRequest, 131 response::{actix::ActixResponse, Res}, 132 }; 133 use actix_web::{HttpRequest, HttpResponse}; 134 use bytes::Bytes; 135 use std::{future::Future, pin::Pin}; 136 137 impl super::Service for S 138 where 139 S: actix_web::dev::Service, 140 S::Future: Send + 'static, 141 S::Error: std::fmt::Display + Send + 'static, 142 { 143 fn run( 144 &mut self, 145 req: HttpRequest, 146 ser: fn(ServerFnErrorErr) -> Bytes, 147 ) -> Pin + Send>> { 148 // ... (truncated in source) ``` -------------------------------- ### Split a slice from the end into a limited number of items Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Splits a slice into at most n items starting from the end, with the last item containing the remainder. ```rust let v = [10, 40, 30, 20, 60, 50]; for group in v.rsplitn(2, |num| *num % 3 == 0) { println!("{group:?}"); } ``` -------------------------------- ### Construct a Vec from manually allocated memory Source: https://docs.rs/server_fn/0.8.2/server_fn/type.MiddlewareSet.html Shows how to use Vec::from_parts with memory allocated via the global allocator, ensuring the layout matches the requirements. ```rust #![feature(box_vec_non_null)] use std::alloc::{alloc, Layout}; use std::ptr::NonNull; fn main() { let layout = Layout::array::(16).expect("overflow cannot happen"); let vec = unsafe { let Some(mem) = NonNull::new(alloc(layout).cast::()) else { return; }; mem.write(1_000_000); Vec::from_parts(mem, 1, 16) }; assert_eq!(vec, &[1_000_000]); assert_eq!(vec.capacity(), 16); } ``` -------------------------------- ### Iterate over slice chunks with rchunks_exact Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Returns an iterator over chunks of a fixed size starting from the end of the slice. Panics if the chunk size is zero. ```rust let slice = ['l', 'o', 'r', 'e', 'm']; let mut iter = slice.rchunks_exact(2); assert_eq!(iter.next().unwrap(), &['e', 'm']); assert_eq!(iter.next().unwrap(), &['o', 'r']); assert!(iter.next().is_none()); assert_eq!(iter.remainder(), &['l']); ``` -------------------------------- ### Get pointer range of slice Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Bytes.html Returns a half-open range of raw pointers spanning the slice, useful for C++ interoperability or pointer containment checks. ```rust let a = [1, 2, 3]; let x = &a[1] as *const _; let y = &5 as *const _; assert!(a.as_ptr_range().contains(&x)); assert!(!a.as_ptr_range().contains(&y)); ``` -------------------------------- ### Rebuilding a Vec from raw parts Source: https://docs.rs/server_fn/0.8.2/server_fn/type.MiddlewareSet.html Demonstrates how to extract components from an existing vector and reconstruct it using the same allocator. ```rust #![feature(allocator_api)] use std::alloc::System; use std::ptr; use std::mem; let mut v = Vec::with_capacity_in(3, System); v.push(1); v.push(2); v.push(3); // Prevent running `v`'s destructor so we are in complete control // of the allocation. let mut v = mem::ManuallyDrop::new(v); // Pull out the various important pieces of information about `v` let p = v.as_mut_ptr(); let len = v.len(); let cap = v.capacity(); let alloc = v.allocator(); unsafe { // Overwrite memory with 4, 5, 6 for i in 0..len { ptr::write(p.add(i), 4 + i); } // Put everything back together into a Vec let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone()); assert_eq!(rebuilt, [4, 5, 6]); } ``` -------------------------------- ### run_client Source: https://docs.rs/server_fn/0.8.2/server_fn/struct.Http.html Executes a server function on the client side by serializing the input, sending the request, and deserializing the response. ```APIDOC ## async fn run_client(path: &str, input: Input) -> Result ### Description Runs the server function on the client. The implementation handles serializing the input, sending the HTTP request to the specified path, and deserializing the resulting output. ### Parameters - **path** (&str) - The endpoint path for the server function. - **input** (Input) - The input data to be sent to the server. ```