【问题标题】:How to convert hexadecimal values to Base64 in Rust如何在 Rust 中将十六进制值转换为 Base64
【发布时间】:2014-10-03 19:25:58
【问题描述】:

我在理解 Rust 中的特征概念时遇到了一些问题。我正在尝试将一个简单的十六进制值编码为 Base64 但没有运气,这是我的代码(还有一个字符串到 Base64 的示例)

extern crate serialize;

use serialize::base64::{ToBase64, STANDARD};
use serialize::hex::{FromHex, ToHex};

fn main () {
  let stringOfText = "This is a String";
  let mut config = STANDARD;

  println!("String to base64 = {}", stringOfText.as_bytes().to_base64(config));

  // Can't figure out this 

Vladimir 提供的解决方案适用于 0x 表示的十六进制值。现在我正在寻找以字符串表示的十六进制值:

extern crate serialize;

use serialize::base64::{ToBase64, STANDARD};
use serialize::hex::{FromHex, ToHex};
fn main () {
  let stringOfText = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
  let mut config = STANDARD;

  println!("String to base64 = {}", stringOfText.from_hex().from_utf8_owned().as_bytes().to_base64(config));

  // result should be: SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t

}

from_hex() 给了我一个Vec<u8>.to_base64() 期待u8, 的缓冲区首先我想将Vec<u8> 转换为字符串,然后使用as_bytes() 来获取缓冲区,到目前为止仍然不走运。

【问题讨论】:

  • ToBase64 trait 的唯一实现者是 &[u8] (doc.rust-lang.org/serialize/base64/trait.ToBase64.html) ,因此您需要将该数字转换为它才能使用 to_base64()
  • 谢谢@snf,刚刚更新到这个let hex = 0x49276d2;let integer = hex as u8;println!("Hex to base64 = {}", integer.to_base64(config));,但还是没有运气
  • 我不明白你想要做什么,你想base64_encode "0x49276d2" or "\x04\x92\x76\xd2" 还是别的什么?
  • @david-dias 您能否将接受的答案更改为 2017 年有效的答案?
  • 完成,感谢您的 ping! :)

标签: hex base64 rust


【解决方案1】:

现在是 2017 年,并且 rustc-serialize 现在也已弃用(请参阅 here)。新的大型序列化库称为serde,但我认为这对于这个问题来说有点沉重。

这是一个快速的解决方案,手动将十六进制的String 转换为Vec<u8>,然后使用this 转换为base64 编码的String

我不相信这个 for 循环是将十六进制的 String 转换为 Vec<u8> 的最佳解决方案,但我对 Rust 相当陌生,这就是我所拥有的。评论/改进表示赞赏。

(嘿,等一下,我认出了这些编码字符串,你在做cryptopals吗?)

extern crate base64;
use std::u8;
use self::base64::{encode};

pub fn hex_to_base64(hex: String) -> String {

    // Make vector of bytes from octets
    let mut bytes = Vec::new();
    for i in 0..(hex.len()/2) {
        let res = u8::from_str_radix(&hex[2*i .. 2*i+2], 16);
        match res {
            Ok(v) => bytes.push(v),
            Err(e) => println!("Problem with hex: {}", e),
        };
    };

    encode(&bytes) // now convert from Vec<u8> to b64-encoded String
}    

【讨论】:

  • 我不知道 OP,但我知道。感谢您的提示。
【解决方案2】:

Rust 目前正在发展,接受的答案不再正常工作。具体来说,extern crate 语句不允许引用参数,并且 rustc-serialize crate 的名称现在是 rustc_serialize

以下代码正确地对字符串进行 base64 编码,产生与接受的答案相同的结果(rustc 1.3.0):

extern crate rustc_serialize as serialize;

use serialize::base64::{self, ToBase64};
use serialize::hex::FromHex;

fn main() {
    let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
    let result = input.from_hex().unwrap().to_base64(base64::STANDARD);
    println!("{}", result);
}

结果:

SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t

【讨论】:

    【解决方案3】:

    对于您更新的问题,试试这个:

    extern crate "rustc-serialize" as serialize;
    
    use serialize::base64::{self, ToBase64};
    use serialize::hex::FromHex;
    
    fn main() {
        let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
        let result = input.from_hex().unwrap().as_slice().to_base64(base64::STANDARD);
        println!("{}", result);
    }
    

    (请注意,序列化现在位于外部 crate 中,请参阅 rustc-serialize。感谢 gsingh2011。)

    from_hex 返回一个Result&lt;Vec&lt;u8&gt;, FromHexError&gt;,它被解包为Vec&lt;u8&gt;,然后用作&amp;[u8]as_slice()

    ResultOkErr 的类型,通常从无法计算结果的方法返回。在上述情况下,unwrap 用于获取Ok 值。如果结果不是Ok,则失败(尝试从字符串中删除其中一个字母)。

    根据你的程序做什么,错误情况应该使用匹配来明确处理:

    match input.from_hex() {
        Ok(result) => println!("Yay: {}", result.as_slice().to_base64(base64::STANDARD)),
        Err(error) => println!("Nay: {}", error)
    }
    

    或者如果你只是想继续使用默认值,你可以使用unwrap_or

    println!("{}", input.from_hex().unwrap_or(vec!()).as_slice().to_base64(base64::STANDARD));
    

    其他方法见documentation for Result

    【讨论】:

    • 非常感谢罗宾斯特!因此,如果我理解正确,Rust 的最佳实践是在“包”中返回结果和错误,然后必须将其解包以获得实际结果(或错误时的错误?)
    • 是的,我在答案中添加了更多解释。其他语言有时会为此使用异常,或使用多个返回值。 Rust 有一个带有很好方法的类型,它允许调用者以一种或另一种方式处理它。
    • 请注意,base64 转换函数已移至外部 crate:github.com/rust-lang/rustc-serialize
    【解决方案4】:

    我不知道你是什么意思 - 将十六进制值转换为 base64(fwiw 没有十六进制值之类的东西 - 它只是相同文字数字的另一种形式)。假设您要转换构成 int 值的字节,您可以执行以下操作:

    extern crate serialize;
    
    use std::mem;
    use serialize::base64::{mod, ToBase64};
    
    fn decompose_int(n: int, buf: &mut [u8]) {
        assert!(mem::size_of::<int>() == buf.len());
        for i in range(0, buf.len()) {
            buf[i] = ((n >> i*8) & 0xFF) as u8;
        }
    }
    
    fn main() {
        let mut bytes = [0u8, ..8];
        let x = 0x1122334455667788;
        decompose_int(x, &mut bytes);
        println!("{}", bytes.to_base64(base64::STANDARD));
    }
    

    (试试看here

    这里decompose_int 函数将int 值序列化为小端格式的字节片。然后这个切片照常转换为base64。

    如果您需要大端表示,则需要将buf[i] 更改为buf[buf.len()-1-i]

    【讨论】:

    • 谢谢 :) 。确切地说,我只是想了解如何在 Rust 中迈出第一步。感谢您的解决方案,它绝对适用于 0x 值(正如我所要求的那样。)现在我正在尝试使用字符串来表示十六进制值,这需要我将其转换为字节向量(请参阅顶部的更新)。
    • 你认为修改参数是个好主意 - buf[i] = ?相反,必须有另一个变量let buf1 = buf; buf1[i] = ...
    • @AlexanderSupertramp,为什么?我看不出临时变量的原因。
    • 一般来说,修改参数是不好的,你没听说过吗?
    • @AlexanderSupertramp,这可能当您自己修改参数时(例如,在这种情况下,如果您将一个切片替换为另一个切片,但这是不可能的因为buf 变量是不可变的),我认为即使这在 Rust 中也是有争议的。此外,这里的 slice 本身是可变的,它存在的唯一原因是允许改变它的元素。添加局部变量只会带来混乱。抱歉,但不加思索地应用这样的规则是一种非常错误的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2012-07-02
    • 2023-01-16
    相关资源
    最近更新 更多