A lifetime annotation names a relationship between borrowed references. Rust can often infer that a returned reference comes from an input. When a function accepts more than one reference, the signature may need to say which input the result borrows from. An annotation describes that relationship; it does not keep the underlying value alive longer. section 4.4.1
Which input owns the result?
`fn get_value(numbers: &Vec<i32>) -> &i32` can return `&numbers[0]`: the single borrowed input makes the relationship clear. Add a separate `s: &str` argument, and Rust cannot tell from the signature whether the returned `&i32` borrows from `numbers` or `s`. Write `fn get_value<'a>(numbers: &'a Vec<i32>, s: &str) -> &'a i32`. The name `'a` ties the result to `numbers`; `s` need not share that lifetime. section 4.4.1
The relationship has a practical consequence. If `value` still refers to an element of `numbers`, Rust rejects a `numbers.push(6)` before the last use of `value`: mutation could invalidate the borrowed element. An annotation cannot make a reference to a function’s local variable safe to return, because that variable does not survive the call. section 4.4.1
Listing 4.13 Returning a reference to an argument
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let value = get_value(&numbers, "Getting the number");
println!("value: {}", value);
}
fn get_value<'a>(numbers: &'a Vec<i32>, s: &str) -> &'a i32 { #1
println!("{}", s);
&numbers[0]
}
Compare the annotated `numbers` argument and return type with the unannotated `s` argument. section 4.4.1
The same pattern matters when reading an NGINX request body through Rust’s FFI. In `request_body_as_str<'a>(request: &'a ngx_http_request_t) -> Result<&'a str, &'static str>`, the successful string slice borrows request-owned memory and cannot outlive the request reference. The `'static` annotation applies to the error string. The body bytes are viewed as a slice and checked as UTF-8 rather than copied into a new string. This lifetime relationship does not replace the unsafe-code checks needed before reading NGINX pointers. section 4.4 section 4.4.2
unsafe fn request_body_as_str<'a>(
request: &'a ngx_http_request_t,
) -> Result<&'a str, &'static str> {
if request.request_body.is_null()
|| (*request.request_body).bufs.is_null()
|| (*(*request.request_body).bufs).buf.is_null()
{
return Err("Request body buffers
were not initialized as expected");
}
let buf = (*(*request.request_body).bufs).buf;
let start = (*buf).pos;
let len = (*buf).last.offset_from(start) as usize;
let body_bytes = std::slice::from_raw_parts(start, len);
let body_str = std::str::from_utf8(body_bytes)
.map_err(|_| "Body contains invalid UTF-8")?;
Ok(body_str)
}
Follow the null checks, raw buffer view, UTF-8 conversion, and annotated return type in the complete request-body helper. section 4.4

