ur
is a crate to interact with uniform resource
encodings of binary data.
The encoding scheme is optimized for transport in URIs and QR codes.
The [ur::Encoder
] allows a byte payload to be transmissioned in
multiple stages, respecting maximum size requirements. Under the hood,
a fountain
encoder is used to create an unbounded stream of URIs,
subsets of which can be recombined at the receiving side into the payload:
let data = String::from("Ten chars!").repeat(10);
let max_length = 5;
let mut encoder = ur::Encoder::bytes(data.as_bytes(), max_length).unwrap();
let part = encoder.next_part().unwrap();
assert_eq!(
part,
"ur:bytes/1-20/lpadbbcsiecyvdidatkpfeghihjtcxiabdfevlms"
);
let mut decoder = ur::Decoder::default();
while !decoder.complete() {
let part = encoder.next_part().unwrap();
// Simulate some communication loss
if encoder.current_index() & 1 > 0 {
decoder.receive(&part).unwrap();
}
}
assert_eq!(decoder.message().unwrap().as_deref(), Some(data.as_bytes()));
The following useful building blocks are also part of the public API:
- The
crate::bytewords
module contains functionality to encode byte payloads into a suitable alphabet, achieving hexadecimal byte-per-character efficiency. - The
crate::fountain
module provides an implementation of a fountain encoder, which splits up a byte payload into multiple segments and emits an unbounded stream of parts which can be recombined at the receiving decoder side.
Add ur
to the dependencies of your Cargo.toml
:
cargo add ur
To run this example, execute
cargo run --example qr -- "This is my super awesome UR payload"
which will print out URIs and QR codes transmitting the provided payload.
a proposed method of encoding binary data of arbitrary content and length so that it is suitable for transport in either URIs or QR codes.
The resulting constraints on the permissible encoding alphabet are nicely analyzed here.
The following building blocks interact to achieve this goal:
- Bytewords map binary data to case-insensitive characters with a 4 bits/char efficiency (identical to hexadecimal encoding)
- Fragments for transmitting multi-part messages are constructed based on a Luby transform (a particular kind of fountain encoding), generating a potentially limitless sequence of fragments, small subsets of which can restore the original message
- CBOR allows for self-describing byte payloads
- A properly seeded Xoshiro pseudo-random generator allows the encoding and decoding parties to agree on which message parts were combined into a fountain encoding fragment
This Rust implementation, in particular its test vectors, is based on the following reference implementations:
Pull requests are welcome.
This project is licensed under the terms of the MIT license.