Previously, recursion into rewriting 'self' in field validations would
cease after the first function call. This meant that internal uses of
'self' were not properly rewritten. This commit ameliorates the
situation.
Previously, 'serde_json::Value' was used to store the serialized
template context. This value does not represent all of serde's data
model. This means we may fail to serialize a valid Rust value into it,
for instance, 128-bit integers. This is reduced with Figment's 'Value',
which supports the majority if not all of the serde data model.
At present, all supported templating engines use 'serde_json::Value', so
in practice, this commit has no effect but to reduce local dependencies
and provide better error messages for bad contexts.
This allows responses to be sent to the client even when data is only
partially read, significantly improving the experience for the client
from one with a "connection closed" error to one with a proper response.
The consequence is a lifetime in 'Data'.
Though other non-lifetime-introducing solutions exist, the introduction
of a lifetime to 'Data' is a longstanding desire as it prevents
smuggling 'Data' into a longer-lived context. Use of 'Data' in that
context was unspecified with various runtime consequences. The addition
of a lifetime bound by the request prevents this error statically.
In summary, the changes are:
* Clients receive responses even when data isn't fully read.
* 'Data' becomes 'Data<'r>'. 'FromData' changes accordingly.
* Route 'Outcome's are strictly tied to the request lifetime.
Tangentially, the invalid length form field validation error message has
improved to format length in byte units if it exceeds 1024.
If stars aligned properly, we might imagine writing this:
#[non_exhaustive]
struct Config {
pub field: Foo,
pub other: Bar,
}
...with semantics that would allow the defining crate (here, Rocket), to
construct the structure directly while consumers would need to use
public constructors or struct update syntax:
Config {
field: Foo,
other: Bar,
..Default::default()
}
Alas, this is not the way `non_exhaustive` works on structs. You cannot
use field-update syntax to construct `Config` above. You must use public
constructors. This means builder methods or mutating an already built
struct. This is not what we want.
I don't know why it works this way. I don't see why it must. Something
something Drop.
So we have this hack from the pre-non_exhaustive era.