extern crate base64;
fn read_float_vec_from_byte_vec(v: Vec<u8>) -> Result<Vec<f32>, &'static str> {
#[inline(always)]
fn float_from_u8_slice(s: &[u8]) -> f32 {
let array = [s[0], s[1], s[2], s[3]];
unsafe { std::mem::transmute(array) }
}
match v.len() % 4 {
0 => Ok(v.chunks(4).map(float_from_u8_slice).collect()),
_ => Err("Number not divisible by 4"),
}
}
fn float_vec_as_byte_vec(values: &Vec<f32>) -> Vec<u8> {
let dest_len = values.len() * 4;
let mut result = Vec::<u8>::with_capacity(dest_len);
result.resize(dest_len, 0);
for (i, x) in values.iter().enumerate() {
let bytes: [u8; 4] = unsafe { std::mem::transmute(*x) };
result[i*4..i*4+4].copy_from_slice(&bytes[..]);
}
result
}
fn show_base64_decode_error(e: base64::DecodeError) -> String {
use std::error::Error;
format!("{:?}", e.description())
}
fn base64_to_f32_16_array(base64_str: &str) -> Result<[f32; 16], String>
{
base64::decode(base64_str
).map_err(show_base64_decode_error
).and_then(read_float_vec_from_byte_vec
).map(
|float_vec| {
let mut result: [f32; 16] = [0.0; 16];
result.copy_from_slice(&float_vec[..]);
result
}
)
}
fn f32_16_array_to_base64(vals: &[f32; 16]) -> String
{
base64::encode(&float_vec_as_byte_vec(&vals.to_vec()))
}
#[cfg(test)]
mod tests {
static VALUES: [f32; 16] = [-0.35, -0.97, 0.05, 0.49, 1.35, 1.08, -0.71, 0.27, -0.44, 0.22, -1.34, -1.17, 0.68, 0.02, -0.52, 0.83];
static BASE64_STR: &str = "MzOzvuxReL/NzEw9SOH6Ps3MrD9xPYo/j8I1v3E9ij6uR+G+rkdhPh+Fq7+PwpW/exQuPwrXozy4HgW/4XpUPw==";
#[test]
fn base64_to_f32_16_array_test() {
assert_eq!(super::base64_to_f32_16_array(&BASE64_STR), Ok(VALUES));
assert_eq!(
super::base64_to_f32_16_array("foo"),
Err("Number of bytes not divisible by 4.".to_string()));
}
#[test]
fn f32_16_array_to_base64_test() {
assert_eq!(super::f32_16_array_to_base64(&VALUES), BASE64_STR);
}
}
ZXh0ZXJuIGNyYXRlIGJhc2U2NDsKCmZuIHJlYWRfZmxvYXRfdmVjX2Zyb21fYnl0ZV92ZWModjogVmVjPHU4PikgLT4gUmVzdWx0PFZlYzxmMzI+LCAmJ3N0YXRpYyBzdHI+IHsKICAgICNbaW5saW5lKGFsd2F5cyldCiAgICBmbiBmbG9hdF9mcm9tX3U4X3NsaWNlKHM6ICZbdThdKSAtPiBmMzIgewogICAgICAgIGxldCBhcnJheSA9IFtzWzBdLCBzWzFdLCBzWzJdLCBzWzNdXTsKICAgICAgICB1bnNhZmUgeyBzdGQ6Om1lbTo6dHJhbnNtdXRlKGFycmF5KSB9CiAgICB9CgogICAgbWF0Y2ggdi5sZW4oKSAlIDQgewogICAgICAgIDAgPT4gT2sodi5jaHVua3MoNCkubWFwKGZsb2F0X2Zyb21fdThfc2xpY2UpLmNvbGxlY3QoKSksCiAgICAgICAgXyA9PiBFcnIoIk51bWJlciBub3QgZGl2aXNpYmxlIGJ5IDQiKSwKICAgIH0KfQoKZm4gZmxvYXRfdmVjX2FzX2J5dGVfdmVjKHZhbHVlczogJlZlYzxmMzI+KSAtPiBWZWM8dTg+IHsKICAgIGxldCBkZXN0X2xlbiA9IHZhbHVlcy5sZW4oKSAqIDQ7CiAgICBsZXQgbXV0IHJlc3VsdCA9IFZlYzo6PHU4Pjo6d2l0aF9jYXBhY2l0eShkZXN0X2xlbik7CiAgICByZXN1bHQucmVzaXplKGRlc3RfbGVuLCAwKTsKICAgIGZvciAoaSwgeCkgaW4gdmFsdWVzLml0ZXIoKS5lbnVtZXJhdGUoKSB7CiAgICAgICAgbGV0IGJ5dGVzOiBbdTg7IDRdID0gdW5zYWZlIHsgc3RkOjptZW06OnRyYW5zbXV0ZSgqeCkgfTsKICAgICAgICByZXN1bHRbaSo0Li5pKjQrNF0uY29weV9mcm9tX3NsaWNlKCZieXRlc1suLl0pOwogICAgfQogICAgcmVzdWx0Cn0KCmZuIHNob3dfYmFzZTY0X2RlY29kZV9lcnJvcihlOiBiYXNlNjQ6OkRlY29kZUVycm9yKSAtPiBTdHJpbmcgewogICAgdXNlIHN0ZDo6ZXJyb3I6OkVycm9yOwogICAgZm9ybWF0ISgiezo/fSIsIGUuZGVzY3JpcHRpb24oKSkKfQoKZm4gYmFzZTY0X3RvX2YzMl8xNl9hcnJheShiYXNlNjRfc3RyOiAmc3RyKSAtPiBSZXN1bHQ8W2YzMjsgMTZdLCBTdHJpbmc+CnsKICAgIGJhc2U2NDo6ZGVjb2RlKGJhc2U2NF9zdHIKICAgICAgICApLm1hcF9lcnIoc2hvd19iYXNlNjRfZGVjb2RlX2Vycm9yCiAgICAgICAgKS5hbmRfdGhlbihyZWFkX2Zsb2F0X3ZlY19mcm9tX2J5dGVfdmVjCiAgICAgICAgKS5tYXAoCiAgICAgICAgfGZsb2F0X3ZlY3wgewogICAgICAgICAgICBsZXQgbXV0IHJlc3VsdDogW2YzMjsgMTZdID0gWzAuMDsgMTZdOwogICAgICAgICAgICByZXN1bHQuY29weV9mcm9tX3NsaWNlKCZmbG9hdF92ZWNbLi5dKTsKICAgICAgICAgICAgcmVzdWx0CiAgICAgICAgfQogICAgKQp9CgpmbiBmMzJfMTZfYXJyYXlfdG9fYmFzZTY0KHZhbHM6ICZbZjMyOyAxNl0pIC0+IFN0cmluZwp7CiAgICBiYXNlNjQ6OmVuY29kZSgmZmxvYXRfdmVjX2FzX2J5dGVfdmVjKCZ2YWxzLnRvX3ZlYygpKSkKfQoKI1tjZmcodGVzdCldCm1vZCB0ZXN0cyB7CiAgICBzdGF0aWMgVkFMVUVTOiBbZjMyOyAxNl0gPSBbLTAuMzUsIC0wLjk3LCAwLjA1LCAwLjQ5LCAxLjM1LCAxLjA4LCAtMC43MSwgMC4yNywgLTAuNDQsIDAuMjIsIC0xLjM0LCAtMS4xNywgMC42OCwgMC4wMiwgLTAuNTIsIDAuODNdOwogICAgc3RhdGljIEJBU0U2NF9TVFI6ICZzdHIgPSAiTXpPenZ1eFJlTC9OekV3OVNPSDZQczNNckQ5eFBZby9qOEkxdjNFOWlqNnVSK0crcmtkaFBoK0ZxNytQd3BXL2V4UXVQd3JYb3p5NEhnVy80WHBVUHc9PSI7CiAgICAjW3Rlc3RdCiAgICBmbiBiYXNlNjRfdG9fZjMyXzE2X2FycmF5X3Rlc3QoKSB7CiAgICAgICAgYXNzZXJ0X2VxIShzdXBlcjo6YmFzZTY0X3RvX2YzMl8xNl9hcnJheSgmQkFTRTY0X1NUUiksIE9rKFZBTFVFUykpOwogICAgICAgIGFzc2VydF9lcSEoCiAgICAgICAgICAgIHN1cGVyOjpiYXNlNjRfdG9fZjMyXzE2X2FycmF5KCJmb28iKSwKICAgICAgICAgICAgRXJyKCJOdW1iZXIgb2YgYnl0ZXMgbm90IGRpdmlzaWJsZSBieSA0LiIudG9fc3RyaW5nKCkpKTsKICAgIH0KICAgICNbdGVzdF0KICAgIGZuIGYzMl8xNl9hcnJheV90b19iYXNlNjRfdGVzdCgpIHsKICAgICAgICBhc3NlcnRfZXEhKHN1cGVyOjpmMzJfMTZfYXJyYXlfdG9fYmFzZTY0KCZWQUxVRVMpLCBCQVNFNjRfU1RSKTsKICAgIH0KfQo=