Ordes
A crate for treating arrays and tuples a little bit more like vectors.
At the moment, this crate provides .pop(), .rest(), .push(val), and .cons(val) methods
through the OrdesPop, OrdesRest, OrdesPush, and OrdesCons traits respectively, and
additionally provides the .split(), .concat(arr), .remove(), and .insert(val) methods
through the OrdesSplit, OrdesConcat, OrdesRemove, and OrdesInsert traits respectively
through the const_generics crate feature, which requires a nightly compiler and enables the
incomplete generic_const_exprs feature. These last four traits are only available and implemented
through this feature since each individual one would require a nonlinearly-scaling number of trait
implementations, and I'm not sure anyone would like to put up with those compile times. For this
same reason they're also only implemented on arrays.
This crate was born out of my stubborn desire to use iterators wherever possible instead of for
loops, which makes packing data together a bit of a pain in the neck at times. For instance,
consider an iterator producing all lowercase four letter "words":
.flat_map
.flat_map
.flat_map
.for_each;
As we can see, this is both:
- Not particularly pleasant to write or look at
- Not something a sane person would do
This crate offers an alternative:
use OrdesPush;
.flat_map
.flat_map
.flat_map
.for_each;
There's not any real magic going on here. .push(val) produces a value of a new type. In the first
example, chars.push(l3), the input type is (char, char) and the output is (char, char, char).
Similar story for chars.push(l4) - input of (char, char, char), output of
(char, char, char, char). A nearly identical implementation can be made with arrays as well:
use OrdesPush;
.flat_map
.flat_map
.flat_map
.for_each;
In this case, chars.push(l3) takes in [char; 2] and produces [char; 3], and chars.push(l4)
takes in [char; 3] and produces [char; 4].
A silly use case that came up recently that prompted me to add two new traits - OrdesRest and
OrdesCons<T> - is tagging a fixed-size array with an indicator byte before serialising that into a
bytestream:
use IpAddr;
use OrdesCons;
Without .cons(_), it would be necessary to include another line in each branch writing 4 or 6
to data[0]. Small improvement, but I'm petty enough to count it.
In this crate I implement OrdesPop, OrdesRest, OrdesPush<T>, and OrdesCons<T> for arrays and
tuples, but with some caveats:
- On stable, all traits are only implemented for array lengths up to 32 (by default, there's features for up to 1024).
- On both nightly and stable, all traits are only implemented for tuples up to 32 types (by default, there's features for up to 1024).
All trait methods exposed by this crate consume self and produce a new type that's longer or
shorter (or with an extra or dropping the last type in the case of tuples). I'm well aware this is a
very limited use case, but it's useful to me, and hopefully a few other people.
Note about the const_generics feature
In order to use this crate with the const_generics feature, you must also put
#![feature(generic_const_exprs)] somewhere in your crate (lib.rs, main.rs, etc.). Any trait
impl in this crate that relies on ConstCheck<B> will have that bound fail if the feature is not
enabled.