diff --git a/Cargo.lock b/Cargo.lock index 301b453..aa02a47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -309,7 +309,7 @@ checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "urbit-q" -version = "0.1.2" +version = "0.2.0" dependencies = [ "phf", "proptest", diff --git a/Cargo.toml b/Cargo.toml index cf2de95..301f87f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "urbit-q" -version = "0.1.2" +version = "0.2.0" authors = ["k2l8m11n2"] edition = "2018" description = "Encode and decode data in Urbit's @q format" diff --git a/README.md b/README.md index 90e5a82..a21f924 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,12 @@ Based on [urbit-ob](https://github.com/urbit/urbit-ob), supports only the `@q` f ## usage -Note that `encode` pads the beginning to an even number of bytes (as per the -original implementation) and `decode` ignores any dashes or spaces within the -string. +Note that when encoding more than one byte, `encode` pads from the beginning to +an even number (as per the original implementation) and `decode` ignores any +dashes or spaces within the string. ```rust -let bytes: [u8; 3] = [1, 2, 3]; -let string = urbit_q::encode(&bytes); // doznec-binwes +urbit_q::encode(&[1]); // nec +let string = urbit_q::encode(&[1, 2, 3]); // doznec-binwes urbit_q::decode(&string).unwrap(); // [0, 1, 2, 3] urbit_q::decode("doz nec bin wes"); // Some([0, 1, 2, 3]) urbit_q::decode("do-z ne cb inwes"); // Some([0, 1, 2, 3]) diff --git a/src/lib.rs b/src/lib.rs index afa1dc8..6c0e641 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,12 +4,12 @@ //! //! ## usage //! -//! Note that `encode` pads the beginning to an even number of bytes (as per the -//! original implementation) and `decode` ignores any dashes or spaces within the -//! string. +//! Note that when encoding more than one byte, `encode` pads from the beginning to +//! an even number (as per the original implementation) and `decode` ignores any +//! dashes or spaces within the string. //! ```rust -//! let bytes: [u8; 3] = [1, 2, 3]; -//! let string = urbit_q::encode(&bytes); // doznec-binwes +//! urbit_q::encode(&[1]); // nec +//! let string = urbit_q::encode(&[1, 2, 3]); // doznec-binwes //! urbit_q::decode(&string).unwrap(); // [0, 1, 2, 3] //! urbit_q::decode("doz nec bin wes"); // Some([0, 1, 2, 3]) //! urbit_q::decode("do-z ne cb inwes"); // Some([0, 1, 2, 3]) @@ -29,6 +29,12 @@ mod consts; /// decode(&string).unwrap(); // [0, 1, 2, 3] /// ``` pub fn encode(input: &[u8]) -> String { + if input.len() == 0 { + return String::new(); + } + if input.len() == 1 { + return String::from(consts::SUFFIXES[input[0] as usize]); + } let should_pad = input.len() % 2 != 0; let length = input.len() + should_pad as usize; let dashes = if input.len() > 2 { length / 2 - 1 } else { 0 }; @@ -73,6 +79,9 @@ pub fn decode(input: &str) -> Option> { return None; } let stripped_input = input.replace(&['-', ' '][..], ""); + if stripped_input.len() == 3 { + return Some(vec![*consts::SUFFIXES_MAP.get(&stripped_input[..])?]); + } if stripped_input.len() % 3 != 0 { return None; } diff --git a/tests/manual.rs b/tests/manual.rs index ffe9e74..bffa36d 100644 --- a/tests/manual.rs +++ b/tests/manual.rs @@ -1,10 +1,31 @@ #[test] fn readme() { - let bytes: [u8; 3] = [1, 2, 3]; - let string = urbit_q::encode(&bytes); + assert_eq!(urbit_q::encode(&[1]), "nec"); + let string = urbit_q::encode(&[1, 2, 3]); assert_eq!(string, "doznec-binwes"); assert_eq!(urbit_q::decode(&string).unwrap(), vec![0, 1, 2, 3]); assert_eq!(urbit_q::decode("doz nec bin wes"), Some(vec!(0, 1, 2, 3))); assert_eq!(urbit_q::decode("do-z ne cb inwes"), Some(vec!(0, 1, 2, 3))); assert_eq!(urbit_q::decode("hello world"), None); } + +#[test] +fn simple() { + assert_eq!(urbit_q::encode(&[]), ""); + assert_eq!(urbit_q::decode(""), Some(vec![])); + assert_eq!(urbit_q::encode(&[0]), "zod"); + assert_eq!(urbit_q::decode("zod"), Some(vec![0])); + assert_eq!(urbit_q::encode(&[1]), "nec"); + assert_eq!(urbit_q::decode("nec"), Some(vec![1])); + assert_eq!(urbit_q::encode(&[1, 2]), "marbud"); + assert_eq!(urbit_q::decode("marbud"), Some(vec![1, 2])); + assert_eq!(urbit_q::encode(&[1, 2, 3]), "doznec-binwes"); + assert_eq!(urbit_q::decode("doznec-binwes"), Some(vec![0, 1, 2, 3])); + assert_eq!(urbit_q::encode(&[1, 2, 3, 4]), "marbud-wansev"); + assert_eq!(urbit_q::decode("marbud-wansev"), Some(vec![1, 2, 3, 4])); + assert_eq!(urbit_q::encode(&[1, 2, 3, 4, 5]), "doznec-binwes-samper"); + assert_eq!( + urbit_q::decode("doznec-binwes-samper"), + Some(vec![0, 1, 2, 3, 4, 5]) + ); +} diff --git a/tests/proptest.rs b/tests/proptest.rs index 6108635..63d560d 100644 --- a/tests/proptest.rs +++ b/tests/proptest.rs @@ -14,7 +14,7 @@ proptest! { #[test] fn roundtrip(bytes: Vec) { let mut padded = bytes.clone(); - if padded.len() % 2 != 0{ + if padded.len() != 1 && padded.len() % 2 != 0 { padded.insert(0, 0); } let tripped = decode(&encode(&bytes)).unwrap();