Skip to content

Commit

Permalink
bytewords: Make Style Copy and Clone
Browse files Browse the repository at this point in the history
It won't impact performance and allows to pass it as a value.

Signed-off-by: Jean-Pierre De Jesus DIAZ <me@jeandudey.tech>
  • Loading branch information
jeandudey authored and dspicher committed Dec 11, 2022
1 parent f820d9b commit 00dd637
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 44 deletions.
4 changes: 2 additions & 2 deletions fuzz/fuzz_targets/bytewords_encode.rs
Expand Up @@ -8,8 +8,8 @@ fn main() {
ur::bytewords::Style::Uri,
ur::bytewords::Style::Minimal,
] {
let encoded = ur::bytewords::encode(data, &style);
let decoded = ur::bytewords::decode(&encoded, &style).unwrap();
let encoded = ur::bytewords::encode(data, style);
let decoded = ur::bytewords::decode(&encoded, style).unwrap();
assert_eq!(data, decoded);
}
});
Expand Down
70 changes: 32 additions & 38 deletions src/bytewords.rs
Expand Up @@ -7,37 +7,37 @@
//! ```
//! use ur::bytewords::{decode, encode, Style};
//! let data = "Some bytes".as_bytes();
//! let encoded = encode(data, &Style::Standard);
//! let encoded = encode(data, Style::Standard);
//! assert_eq!(
//! encoded,
//! "guru jowl join inch crux iced kick jury inch junk taxi aqua kite limp"
//! );
//! assert_eq!(data, decode(&encoded, &Style::Standard).unwrap());
//! assert_eq!(data, decode(&encoded, Style::Standard).unwrap());
//! ```
//!
//! # URI style
//! ```
//! use ur::bytewords::{decode, encode, Style};
//! let data = "Some bytes".as_bytes();
//! let encoded = encode(data, &Style::Uri);
//! let encoded = encode(data, Style::Uri);
//! assert_eq!(
//! encoded,
//! "guru-jowl-join-inch-crux-iced-kick-jury-inch-junk-taxi-aqua-kite-limp"
//! );
//! assert_eq!(data, decode(&encoded, &Style::Uri).unwrap());
//! assert_eq!(data, decode(&encoded, Style::Uri).unwrap());
//! ```
//!
//! # Minimal style
//! ```
//! use ur::bytewords::{decode, encode, Style};
//! let data = "Some binary data".as_bytes();
//! let encoded = encode(data, &Style::Minimal);
//! let encoded = encode(data, Style::Minimal);
//! assert_eq!(encoded, "gujljnihcxidinjthsjpkkcxiehsjyhsnsgdmkht");
//! assert_eq!(data, decode(&encoded, &Style::Minimal).unwrap());
//! assert_eq!(data, decode(&encoded, Style::Minimal).unwrap());
//! ```

/// The three different `bytewords` encoding styles. See the [`encode`] documentation for examples.
#[derive(PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Style {
/// Four-letter words, separated by spaces
Standard,
Expand Down Expand Up @@ -67,31 +67,31 @@ impl std::fmt::Display for Error {

impl std::error::Error for Error {}

/// Deocdes a `bytewords`-encoded String back into a byte payload. The encoding
/// Decodes a `bytewords`-encoded String back into a byte payload. The encoding
/// must contain a four-byte checksum.
///
/// # Examples
///
/// ```
/// use ur::bytewords::{decode, Style};
/// assert_eq!(
/// decode("able tied also webs lung", &Style::Standard).unwrap(),
/// decode("able tied also webs lung", Style::Standard).unwrap(),
/// vec![0]
/// );
/// assert_eq!(
/// decode("able-tied-also-webs-lung", &Style::Uri).unwrap(),
/// decode("able-tied-also-webs-lung", Style::Uri).unwrap(),
/// vec![0]
/// );
/// // Notice how the minimal encoding consists of the start and end letters of the bytewords
/// assert_eq!(decode("aetdaowslg", &Style::Minimal).unwrap(), vec![0]);
/// assert_eq!(decode("aetdaowslg", Style::Minimal).unwrap(), vec![0]);
/// ```
///
/// # Errors
///
/// If the encoded string contains unrecognized words, is inconsistent with
/// the provided `style`, or contains an invalid checksum, an error will be
/// returned.
pub fn decode(encoded: &str, style: &Style) -> Result<Vec<u8>, Error> {
pub fn decode(encoded: &str, style: Style) -> Result<Vec<u8>, Error> {
let separator = match style {
Style::Standard => " ",
Style::Uri => "-",
Expand Down Expand Up @@ -139,13 +139,13 @@ fn strip_checksum(data: &[u8]) -> Result<Vec<u8>, Error> {
///
/// ```
/// use ur::bytewords::{encode, Style};
/// assert_eq!(encode(&[0], &Style::Standard), "able tied also webs lung");
/// assert_eq!(encode(&[0], &Style::Uri), "able-tied-also-webs-lung");
/// assert_eq!(encode(&[0], Style::Standard), "able tied also webs lung");
/// assert_eq!(encode(&[0], Style::Uri), "able-tied-also-webs-lung");
/// // Notice how the minimal encoding consists of the start and end letters of the bytewords
/// assert_eq!(encode(&[0], &Style::Minimal), "aetdaowslg");
/// assert_eq!(encode(&[0], Style::Minimal), "aetdaowslg");
/// ```
#[must_use]
pub fn encode(data: &[u8], style: &Style) -> String {
pub fn encode(data: &[u8], style: Style) -> String {
let checksum = crate::crc32().checksum(data).to_be_bytes();
let data = data.iter().chain(checksum.iter());
let words: Vec<&str> = match style {
Expand Down Expand Up @@ -178,62 +178,56 @@ mod tests {
fn test_bytewords() {
let input = vec![0, 1, 2, 128, 255];
assert_eq!(
encode(&input, &Style::Standard),
encode(&input, Style::Standard),
"able acid also lava zoom jade need echo taxi"
);
assert_eq!(
encode(&input, &Style::Uri),
encode(&input, Style::Uri),
"able-acid-also-lava-zoom-jade-need-echo-taxi"
);
assert_eq!(encode(&input, &Style::Minimal), "aeadaolazmjendeoti");
assert_eq!(encode(&input, Style::Minimal), "aeadaolazmjendeoti");

assert_eq!(
decode(
"able acid also lava zoom jade need echo taxi",
&Style::Standard
Style::Standard
)
.unwrap(),
input
);
assert_eq!(
decode("able-acid-also-lava-zoom-jade-need-echo-taxi", &Style::Uri).unwrap(),
input
);
assert_eq!(
decode("aeadaolazmjendeoti", &Style::Minimal).unwrap(),
decode("able-acid-also-lava-zoom-jade-need-echo-taxi", Style::Uri).unwrap(),
input
);
assert_eq!(decode("aeadaolazmjendeoti", Style::Minimal).unwrap(), input);

// empty payload is allowed
decode(&encode(&[], &Style::Minimal), &Style::Minimal).unwrap();
decode(&encode(&[], Style::Minimal), Style::Minimal).unwrap();

// bad checksum
assert_eq!(
decode(
"able acid also lava zero jade need echo wolf",
&Style::Standard
Style::Standard
)
.unwrap_err(),
Error::InvalidChecksum
);
assert_eq!(
decode("able-acid-also-lava-zero-jade-need-echo-wolf", &Style::Uri).unwrap_err(),
decode("able-acid-also-lava-zero-jade-need-echo-wolf", Style::Uri).unwrap_err(),
Error::InvalidChecksum
);
assert_eq!(
decode("aeadaolazojendeowf", &Style::Minimal).unwrap_err(),
decode("aeadaolazojendeowf", Style::Minimal).unwrap_err(),
Error::InvalidChecksum
);

// too short
assert_eq!(
decode("wolf", &Style::Standard).unwrap_err(),
decode("wolf", Style::Standard).unwrap_err(),
Error::InvalidChecksum
);
assert_eq!(
decode("", &Style::Standard).unwrap_err(),
Error::InvalidWord
);
assert_eq!(decode("", Style::Standard).unwrap_err(), Error::InvalidWord);
}

#[test]
Expand Down Expand Up @@ -266,12 +260,12 @@ mod tests {
fhecwzonnbmhcybtgwwelpflgmfezeonledtgocs\
fzhycypf";

assert_eq!(decode(encoded, &Style::Standard).unwrap(), input.to_vec());
assert_eq!(decode(encoded, Style::Standard).unwrap(), input.to_vec());
assert_eq!(
decode(encoded_minimal, &Style::Minimal).unwrap(),
decode(encoded_minimal, Style::Minimal).unwrap(),
input.to_vec()
);
assert_eq!(encode(&input, &Style::Standard), encoded);
assert_eq!(encode(&input, &Style::Minimal), encoded_minimal);
assert_eq!(encode(&input, Style::Standard), encoded);
assert_eq!(encode(&input, Style::Minimal), encoded_minimal);
}
}
8 changes: 4 additions & 4 deletions src/ur.rs
Expand Up @@ -39,7 +39,7 @@ use anyhow::Context;
/// );
/// ```
pub fn encode<T: Into<String>>(data: &[u8], ur_type: T) -> String {
let body = crate::bytewords::encode(data, &crate::bytewords::Style::Minimal);
let body = crate::bytewords::encode(data, crate::bytewords::Style::Minimal);
encode_ur(&[ur_type.into(), body])
}

Expand Down Expand Up @@ -93,7 +93,7 @@ impl Encoder {
/// If serialization fails an error will be returned.
pub fn next_part(&mut self) -> anyhow::Result<String> {
let part = self.fountain.next_part();
let body = crate::bytewords::encode(&part.cbor()?, &crate::bytewords::Style::Minimal);
let body = crate::bytewords::encode(&part.cbor()?, crate::bytewords::Style::Minimal);
Ok(encode_ur(&[self.ur_type.clone(), part.sequence_id(), body]))
}

Expand Down Expand Up @@ -168,7 +168,7 @@ pub fn decode(value: &str) -> anyhow::Result<(Kind, Vec<u8>)> {
match strip_type.rsplit_once('/') {
None => Ok((
Kind::SinglePart,
crate::bytewords::decode(strip_type, &crate::bytewords::Style::Minimal)?,
crate::bytewords::decode(strip_type, crate::bytewords::Style::Minimal)?,
)),
Some((indices, payload)) => {
let (idx, idx_total) = indices.split_once('-').context("Invalid indices")?;
Expand All @@ -178,7 +178,7 @@ pub fn decode(value: &str) -> anyhow::Result<(Kind, Vec<u8>)> {
);
Ok((
Kind::MultiPart,
crate::bytewords::decode(payload, &crate::bytewords::Style::Minimal)?,
crate::bytewords::decode(payload, crate::bytewords::Style::Minimal)?,
))
}
}
Expand Down

0 comments on commit 00dd637

Please sign in to comment.