Expand description
This module provides conversion utility functions for use with Serde.
This module attempts to consider the common use cases for (de)serialisation,
and provide functions that are semantically appropriate for those use cases.
The functions are intended to be used with the
#[serde(serialize_with)]
and #[serde(deserialize_with)]
attributes.
Of course, as this module is an extension of standard Serde functionality,
it does not attempt to reproduce what Serde already does by default. For
instance, if a struct has a field of type u32
, then Serde will already
know how to serialise and deserialise that field. Equally, if a struct has a
field that is an enum, then Serde is able to serialise and deserialise that
field according to the available enum variants, and the chosen internal
representation of the enum.
Where this module provides particular value is when an alternative serialised representation is required for certain struct members. For example, it is common to have an enum that naturally serialises to and from an integer, but also has a string representation. Or equally, it could be that the required serialised form is not the default. This module allows easy specification of alternative forms for serialisation and deserialisation, while working with the existing Serde derive macros.
As a general statement, the intention of this module is to provide this
functionality for data types such as structs and enums, where the Serde
derive macros would be used, and there is no obvious application for
primitive types such as integers, floats, and booleans, or string types such
as String
and str
.
§Naming conventions
Generally in Rust, the naming of functions carries semantic meaning:
-
to_
prefix: This implies a conversion that does not necessarily consume the original value. It’s often seen in methods that return a new value based on the original, without consuming the original. -
into_
prefix: This indicates that the function consumes the original value and transforms it into another. It’s commonly used with Rust’s ownership system, signifying that the original value will no longer be usable after the conversion. -
as_
prefix: This is typically used for cheap reference conversions that don’t involve any data processing. It suggests a view or representation of the original value, not a conversion or transformation.
§From
and Into
The first case considered is general conversion using Into
and From
.
In a situation where a type implements Into<T>
and either
From<T>
or TryFrom<T>
, then it seems natural and
appropriate to be able to use those implementations for serialisation and
deserialisation. Indeed, Serde does allow this, and it is possible to use
the #[serde(into)]
,
and #[serde(from)]
, and
and #[serde(try_from)]
attributes to specify the desired primary types. However, these apply at the
container level, and there are no equivalent attributes for specifying the
same behaviour at the field level. Instead, the #[serde(with)]
attribute can be used, but this requires the implementation of a custom
serialiser and/or deserialiser. That’s where this module comes in.
The into()
, from()
, and try_from()
functions can be used to
specify the desired behaviour at the field level, matching the behaviour of
the Serde container-level attributes, without the need to implement custom
serialisers and deserialisers. This allows for variations other than the
default to be easily specified. Additionally, ease-of-use functions for
String
conversion are provided in the form of into_string()
,
from_string()
, and try_from_string()
. Note that these functions
expect to work on a full String
, not a str
slice, due to their
context.
The end result is that it becomes trivial to specify alternate conversions for any type that implements the common conversion traits.
§Display
and ToString
, and FromStr
Implementing Display
for a type adds a free implementation of
ToString
as well, which provides the to_string()
method. This is intended to be used for human-readable representations of a
type, and provides a String
copy of the converted type. This is not
necessarily the same as the serialised representation, which is intended for
machine-readable uses. However, for cases where the Display
implementation is the same as the serialised representation, it is possible
to use the to_string()
function to provide the desired behaviour.
Notably, this is conceptually a subset of the Into<String>
use
case, as Into<String>
is intended to be used for any type that can
be converted to a String
, and ToString
does that as well, albeit
with a different semantic purpose, and via copy versus consumption. Although
it is advised to use the into_string()
or as_str()
functions
instead (as appropriate), the to_string()
Serde helper function is
provided for completeness and for such cases where a Display
implementation may exist and is the same as the serialised form, in which
case it would be onerous to also implement another function just for the
sake of it.
The other side of the ToString
coin is FromStr
, which provides the
from_str()
method. This is intended to be used for
parsing a String
into a type, and is the counterpart to to_string()
.
For this purpose, the from_str()
function is provided, which is
basically equivalent to from()
, but for String
types. In this way,
it serves the same essential purpose as from_string()
, but for types
that implement FromStr
instead of TryFrom<String>
. That is
the only difference, and the choice of which to use is entirely down to the
implementation of the type in question.
§AsStr
The second case considered is representation using AsStr
. The
as_str()
function is intended to be used with any type that implements
the AsStr
trait, which provides an as_str()
method.
This function is primarily intended to be used with enums, where it is
common to have variants that naturally serialise to and from integers, but
also have a string representation. In such cases, the enums will typically
be created with static &str
values for such representation, in which case
it is desirable to use and propagate those actual values by reference
instead of making unnecessary copies. This is the purpose of the
as_str()
function.
In keeping with Rust naming conventions and idioms, the concept of representation is considered to be distinct from the concept of conversion, with this function providing an unmodified, uncopied “view” onto a value provided by the type for this purpose.
Functions§
- Returns a string representation of a type from a string slice.
- Returns a type from a string or other serialised representation.
- Converts an integer to a
Decimal
to 2 decimal places. - Converts an integer to a
Decimal
to 2 decimal places. - Returns a type from a string slice representation.
- Returns a type from a string representation.
- Returns a serialised representation of a type.
- Returns string representation of a type.
- Converts a
Decimal
to an integer to 2 decimal places. - Converts a
Decimal
to an integer to 2 decimal places. - Returns a string copy of a type.
- Returns a type from a string or other serialised representation.
- Converts an integer to a floating-point number to 1 decimal place.
- Converts an integer to a floating-point number to 2 decimal places.
- Converts an integer to a floating-point number to 3 decimal places.
- Converts an integer to a floating-point number to 4 decimal places.
- Converts an integer to a floating-point number with scale.
- Returns a type from a string representation.
- Converts a floating-point number to an integer to 1 decimal place.
- Converts a floating-point number to an integer to 2 decimal places.
- Converts a floating-point number to an integer to 3 decimal places.
- Converts a floating-point number to an integer to 4 decimal places.
- Converts a floating-point number to an integer with scale.