8.9 KiB
Encoding
Recipe | Crates | Categories |
---|---|---|
Serialize and deserialize unstructured JSON | ||
Deserialize a TOML configuration file | ||
Percent-encode a string | ||
Encode and decode hex | ||
Encode and decode base64 |
Serialize and deserialize unstructured JSON
The serde_json
crate provides a from_str
function to parse a &str
of
JSON into a type of the caller's choice.
Unstructured JSON can be parsed into a universal serde_json::Value
type that
is able to represent any valid JSON data.
The example below shows a &str
of JSON being parsed and then compared to what
we expect the parsed value to be. The expected value is declared using the
json!
macro.
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate error_chain;
use serde_json::Value;
error_chain! {
foreign_links {
Json(serde_json::Error);
}
}
fn run() -> Result<()> {
let j = r#"{
"userid": 103609,
"verified": true,
"access_privileges": [
"user",
"admin"
]
}"#;
let parsed: Value = serde_json::from_str(j)?;
let expected = json!({
"userid": 103609,
"verified": true,
"access_privileges": [
"user",
"admin"
]
});
assert_eq!(parsed, expected);
Ok(())
}
quick_main!(run);
Deserialize a TOML configuration file
Parse some TOML into a universal toml::Value
that is able to represent any
valid TOML data.
extern crate toml;
#[macro_use]
extern crate error_chain;
use toml::Value;
error_chain! {
foreign_links {
Toml(toml::de::Error);
}
}
fn run() -> Result<()> {
let toml_content = r#"
[package]
name = "your_package"
version = "0.1.0"
authors = ["You! <you@example.org>"]
[dependencies]
serde = "1.0"
"#;
let package_info: Value = toml::from_str(toml_content)?;
assert_eq!(package_info["dependencies"]["serde"].as_str(), Some("1.0"));
assert_eq!(package_info["package"]["name"].as_str(), Some("your_package"));
Ok(())
}
quick_main!(run);
Parse TOML into your own structs using Serde:
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate toml;
#[macro_use]
extern crate error_chain;
use std::collections::HashMap;
#[derive(Deserialize)]
struct Config {
package: Package,
dependencies: HashMap<String, String>,
}
#[derive(Deserialize)]
struct Package {
name: String,
version: String,
authors: Vec<String>,
}
error_chain! {
foreign_links {
Toml(toml::de::Error);
}
}
fn run() -> Result<()> {
let toml_content = r#"
[package]
name = "your_package"
version = "0.1.0"
authors = ["You! <you@example.org>"]
[dependencies]
serde = "1.0"
"#;
let package_info: Config = toml::from_str(toml_content)?;
assert_eq!(package_info.package.name, "your_package");
assert_eq!(package_info.package.version, "0.1.0");
assert_eq!(package_info.package.authors, vec!["You! <you@example.org>"]);
assert_eq!(package_info.dependencies["serde"], "1.0");
Ok(())
}
quick_main!(run);
Percent-encode a string
Encode an input string with percent-encoding using the utf8_percent_encode
function from the url
crate. Then decode using the percent_decode
function.
extern crate url;
#[macro_use]
extern crate error_chain;
use url::percent_encoding::{utf8_percent_encode, percent_decode, DEFAULT_ENCODE_SET};
error_chain! {
foreign_links {
Utf8(std::str::Utf8Error);
}
}
fn run() -> Result<()> {
let input = "confident, productive systems programming";
let iter = utf8_percent_encode(input, DEFAULT_ENCODE_SET);
let encoded: String = iter.collect();
assert_eq!(encoded, "confident,%20productive%20systems%20programming");
let iter = percent_decode(encoded.as_bytes());
let decoded = iter.decode_utf8()?;
assert_eq!(decoded, "confident, productive systems programming");
Ok(())
}
quick_main!(run);
The encode set defines which bytes (in addition to non-ASCII and controls) need
to be percent-encoded. The choice of this set depends on context. For example,
?
needs to be encoded in a URL path but not in a query string.
The return value of encoding is an iterator of &str
slices which can be
collected into a String
.
Encode and decode hex
The data_encoding
crate provides a HEXUPPER::encode
method which
takes a &[u8]
and returns a String
containing the hexadecimal
representation of the data.
Similarly, a HEXUPPER::decode
method is provided which takes a &[u8]
and
returns a Vec<u8>
if the input data is successfully decoded.
The example below shows a &[u8]
of data being converted to its hexadecimal
representation and then being compared to its expected value. The returned
hex String
is then converted back to its original representation and is
compared to the original value provided.
extern crate data_encoding;
#[macro_use]
extern crate error_chain;
use data_encoding::{HEXUPPER, DecodeError};
error_chain! {
foreign_links {
Decode(DecodeError);
}
}
fn run() -> Result<()> {
let original = b"The quick brown fox jumps over the lazy dog.";
let expected = "54686520717569636B2062726F776E20666F78206A756D7073206F76\
657220746865206C617A7920646F672E";
let encoded = HEXUPPER.encode(original);
assert_eq!(encoded, expected);
let decoded = HEXUPPER.decode(&encoded.into_bytes())?;
assert_eq!(&decoded[..], &original[..]);
Ok(())
}
quick_main!(run);
Encode and decode base64
Byte slice is encoded into base64
String with help of encode
and subsequently decoded with decode
.
#[macro_use]
extern crate error_chain;
extern crate base64;
use std::str;
use base64::{encode, decode};
error_chain! {
foreign_links {
Base64(base64::DecodeError);
Utf8Error(str::Utf8Error);
}
}
fn run() -> Result<()> {
let hello = b"hello rustaceans";
let encoded = encode(hello);
let decoded = decode(&encoded)?;
println!("origin: {}", str::from_utf8(hello)?);
println!("base64 encoded: {}", encoded);
println!("back to origin: {}", str::from_utf8(&decoded)?);
Ok(())
}
quick_main!(run);