Home > Blockchain >  How to collect specific bytes from byte array - RUST
How to collect specific bytes from byte array - RUST

Time:08-16

This is decoded string from bytes, they are always different. Am not using it in the code, its just for shown what is all about.

"Background:Sunfire Topo;Base:Eagle;Accessory3:None;Patch:Oreo;Jacket:Pink Bonez;Eyes:BloodShot;Beak:Drool;Accessory2:Nose Ring;Accessory1:None;Item:Knife;tags:Dope Eagles,ELEMENT-HYDRO,ATTACK-10,DEFENSE-5,HIGHNESS-4,SWAG-1;metadata:QmU7JcFDoGcUvNkDgsPz9cy13md4xHdNyD6itwmgVLuo7x/860.json"

This is array of bytes from above string which i get as input.

[66, 97, 99, 107, 103, 114, 111, 117, 110, 100, 58, 83, 117, 110, 102, 105, 114, 101, 32, 84, 111, 112, 111, 59, 66, 97, 115, 101, 58, 69, 97, 103, 108, 101, 59, 65, 99, 99, 101, 115, 115, 111, 114, 121, 51, 58, 78, 111, 110, 101, 59, 80, 97, 116, 99, 104, 58, 79, 114, 101, 111, 59, 74, 97, 99, 107, 101, 116, 58, 80, 105, 110, 107, 32, 66, 111, 110, 101, 122, 59, 69, 121, 101, 115, 58, 66, 108, 111, 111, 100, 83, 104, 111, 116, 59, 66, 101, 97, 107, 58, 68, 114, 111, 111, 108, 59, 65, 99, 99, 101, 115, 115, 111, 114, 121, 50, 58, 78, 111, 115, 101, 32, 82, 105, 110, 103, 59, 65, 99, 99, 101, 115, 115, 111, 114, 121, 49, 58, 78, 111, 110, 101, 59, 73, 116, 101, 109, 58, 75, 110, 105, 102, 101, 59, 116, 97, 103, 115, 58, 68, 111, 112, 101, 32, 69, 97, 103, 108, 101, 115, 44, 69, 76, 69, 77, 69, 78, 84, 45, 72, 89, 68, 82, 79, 44, 65, 84, 84, 65, 67, 75, 45, 49, 48, 44, 68, 69, 70, 69, 78, 83, 69, 45, 53, 44, 72, 73, 71, 72, 78, 69, 83, 83, 45, 52, 44, 83, 87, 65, 71, 45, 49, 59, 109, 101, 116, 97, 100, 97, 116, 97, 58, 81, 109, 85, 55, 74, 99, 70, 68, 111, 71, 99, 85, 118, 78, 107, 68, 103, 115, 80, 122, 57, 99, 121, 49, 51, 109, 100, 52, 120, 72, 100, 78, 121, 68, 54, 105, 116, 119, 109, 103, 86, 76, 117, 111, 55, 120, 47, 56, 54, 48, 46, 106, 115, 111, 110]

What i need is get the values from ELEMENT, ATTACK,DEFENSE,HIGHNESS,SWAG. While every byte in the array is changing. but some bytes are always same. I was thinking if there is any way how to extract it without using any Strings... Thanks for any ideas

so the output would look like this:

let element = [72, 89, 68, 82, 79];
let attack = [49, 48];
let defense = [53];
let highness = [52];
let swag = [49];

CodePudding user response:

You can do all this without allocating any extra space using rusts iterators, using split and related functions

At the top level, your data is of the form (key:value;)* This suggests first splitting on ; Then splitting each of these pieces into key and value using :

In your case, all the information is when the key is "tags".

Then within the tags section, you again have (mostly) key-value pairs of the form (key-value,)* so we need to split on , then break into key-value pairs using -.

An example that does this but only prints all the tag key-value pairs is:

fn split_kv(v: &[u8], c: u8) -> Option<(&[u8], &[u8])> {
    let n = v.iter().position(|&b| b == c)?;
    let w = v.split_at(n);
    Some((w.0, &(w.1)[1..]))
}

fn main() {
    let s: &str = "Background:Sunfire Topo;Base:Eagle;Accessory3:None;Patch:Oreo;Jacket:Pink Bonez;Eyes:BloodShot;Beak:Drool;Accessory2:Nose Ring;Accessory1:None;Item:Knife;tags:Dope Eagles,ELEMENT-HYDRO,ATTACK-10,DEFENSE-5,HIGHNESS-4,SWAG-1;metadata:QmU7JcFDoGcUvNkDgsPz9cy13md4xHdNyD6itwmgVLuo7x/860.json";
    let ss: &[u8] = s.as_bytes();

    let tags = ss
        .split(|&b| b == b';') // Break up at ';'
        .filter_map(|s| split_kv(s, b':')) // Split each piece into key-value pairs using ':'
        .filter_map(|(k, v)| { // Only keep the tags entry.
            if k == "tags".as_bytes() {
                Some(v)
            } else {
                None
            }
        }) 
        .next() // And just take the first of those.
        .unwrap(); 

    // Split the tags by ','
    for t in tags.split(|&b| b == b',') {
        // Then try to convert each to a key-value using '-' as seperator.
        if let Some((k, v)) = split_kv(t, b'-') {       
            println!(
                "k={:?} v={:?}",
                std::str::from_utf8(k).unwrap(),
                std::str::from_utf8(v).unwrap()
            );
        } else {
            println!("t={:?}", std::str::from_utf8(t).unwrap());
        }
    }
}

You can run this here

  • Related