// helper function to convert cbor to intkey state. This is required becasue cbor does not compile
// into wasm at the time this was written.
helper function to convert cbor to intkey state. This is required becasue cbor does not compile
into wasm at the time this was written.
helper function to convert cbor to intkey state . This is required becasue cbor does not compile into wasm at the time this was written .
fn decode_intkey(hex_string: String) -> Result<BTreeMap<String, u32>, ApplyError> {
    let mut output: BTreeMap<String, u32> = BTreeMap::new();
    // First two characters should be A followed by the number of elements.
    // Only check for A as this will be a map with 15 or less elements
    // It is unlikely that an address will have that many hash collisions.
    let data_type = hex_string
        .get(..1)
        .ok_or_else(|| ApplyError::InvalidTransaction("Unable to get data type".into()))?;
    if data_type != "A" {
        return Err(ApplyError::InvalidTransaction(String::from(
            "Cbor is not a map.",
        )));
    };
    let entries_hex = hex_string.get(1..2).ok_or_else(|| {
        ApplyError::InvalidTransaction("Unable to get number of entries in the map".into())
    })?;
    let entries = u32::from_str_radix(entries_hex, 16)
        .map_err(|err| ApplyError::InvalidTransaction(format!("Unable to decode cbor: {}", err)))?;
    let mut start = 2;
    // For each entry get the Name and Value
    for _n in 0..entries {
        let string_hex = hex_string.get(start..start + 2).ok_or_else(|| {
            ApplyError::InvalidTransaction("Unable to hex for the string data".into())
        })?;
        let string_type = usize::from_str_radix(string_hex, 16).map_err(|err| {
            ApplyError::InvalidTransaction(format!("Unable to decode cbor: {}", err))
        })?;
        // String starts at hex 60 plus the length of the string.
        // For Names it should range from hex 61 (decimal 97) to 74 (decimal 116) because a name
        // cannot be empty and must not be greater than 20 characters
        if string_type < 97 || string_type > 116 {
            return Err(ApplyError::InvalidTransaction(String::from(
                "Name is either too long, too short, or not a string.",
            )));
        }
        start += 2;
        let length = (string_type - 96) * 2;
        let name_hex = hex_string
            .get(start..start + length)
            .ok_or_else(|| ApplyError::InvalidTransaction("Unable to hex for the Name".into()))?;
        let name_bytes = decode(name_hex.to_string()).map_err(|err| {
            ApplyError::InvalidTransaction(format!("Unable to decode cbor: {}", err))
        })?;
        let name = String::from_utf8(name_bytes).map_err(|err| {
            ApplyError::InvalidTransaction(format!("Unable to decode cbor: {}", err))
        })?;
        start += length;
        let number_type = hex_string.get(start..start + 2).ok_or_else(|| {
            ApplyError::InvalidTransaction("Unable to get hex for Value data".into())
        })?;
        let mut number = usize::from_str_radix(number_type, 16).map_err(|err| {
            ApplyError::InvalidTransaction(format!("Unable to decode cbor: {}", err))
        })?;
        start += 2;
        // For number less than 23 (decimal) the first two bytes represent the number. If it is
        // greater than 23 the first two bytes represent the number of digits required to
        // calculate the value followed by the actual bytes for the number.
        if number > 23 {
            number -= 23;
            let value = match number {
                // two bytes
                1 => {
                    let value = hex_string.get(start..start + 2).ok_or_else(|| {
                        ApplyError::InvalidTransaction("Unable to get number data".into())
                    })?;
                    start += 2;
                    value
                }
                // 4 bytes
                2 => {
                    let value = hex_string.get(start..start + 4).ok_or_else(|| {
                        ApplyError::InvalidTransaction("Unable to get number data".into())
                    })?;
                    start += 4;
                    value
                }
                // 8 bytes
                3 => {
                    let value = hex_string.get(start..start + 8).ok_or_else(|| {
                        ApplyError::InvalidTransaction("Unable to get number data".into())
                    })?;
                    start += 8;
                    value
                }
                // Anymore than 8 bytes is not a u32 and is invalid.
                _ => {
                    return Err(ApplyError::InvalidTransaction(String::from(
                        "Value is too large",
                    )));
                }
            };
            let int_value = u32::from_str_radix(value, 16).map_err(|err| {
                ApplyError::InvalidTransaction(format!("Unable to decode cbor: {}", err))
            })?;
            output.insert(name, int_value);
        } else {
            let int_value = u32::from_str_radix(number_type, 16).map_err(|err| {
                ApplyError::InvalidTransaction(format!("Unable to decode cbor: {}", err))
            })?;
            output.insert(name, int_value);
        }
    }
    Ok(output)
}
fn decode_intkey ( hex_string : String ) -> Result < BTreeMap < String , u32 > , ApplyError > { let mut output : BTreeMap < String , u32 > = BTreeMap :: new ( ) ; // First two characters should be A followed by the number of elements. // Only check for A as this will be a map with 15 or less elements // It is unlikely that an address will have that many hash collisions. let data_type = hex_string . get ( .. 1 ) . ok_or_else ( | | ApplyError :: InvalidTransaction ( " " . into ( ) ) ) ? ; if data_type != " " { return Err ( ApplyError :: InvalidTransaction ( String :: from ( " " , ) ) ) ; } ; let entries_hex = hex_string . get ( 1 .. 2 ) . ok_or_else ( | | { ApplyError :: InvalidTransaction ( " " . into ( ) ) } ) ? ; let entries = u32 :: from_str_radix ( entries_hex , 16 ) . map_err ( | err | ApplyError :: InvalidTransaction ( format ! ( " " err ) ) ) ? ; let mut start = 2 ; // For each entry get the Name and Value for _n in 0 .. entries { let string_hex = hex_string . get ( start .. start + 2 ) . ok_or_else ( | | { ApplyError :: InvalidTransaction ( " " . into ( ) ) } ) ? ; let string_type = usize :: from_str_radix ( string_hex , 16 ) . map_err ( | err | { ApplyError :: InvalidTransaction ( format ! ( " " err ) ) } ) ? ; // String starts at hex 60 plus the length of the string. // For Names it should range from hex 61 (decimal 97) to 74 (decimal 116) because a name // cannot be empty and must not be greater than 20 characters if string_type < 97 || string_type > 116 { return Err ( ApplyError :: InvalidTransaction ( String :: from ( " " , ) ) ) ; } start += 2 ; let length = ( string_type - 96 ) * 2 ; let name_hex = hex_string . get ( start .. start + length ) . ok_or_else ( | | ApplyError :: InvalidTransaction ( " " . into ( ) ) ) ? ; let name_bytes = decode ( name_hex . to_string ( ) ) . map_err ( | err | { ApplyError :: InvalidTransaction ( format ! ( " " err ) ) } ) ? ; let name = String :: from_utf8 ( name_bytes ) . map_err ( | err | { ApplyError :: InvalidTransaction ( format ! ( " " err ) ) } ) ? ; start += length ; let number_type = hex_string . get ( start .. start + 2 ) . ok_or_else ( | | { ApplyError :: InvalidTransaction ( " " . into ( ) ) } ) ? ; let mut number = usize :: from_str_radix ( number_type , 16 ) . map_err ( | err | { ApplyError :: InvalidTransaction ( format ! ( " " err ) ) } ) ? ; start += 2 ; // For number less than 23 (decimal) the first two bytes represent the number. If it is // greater than 23 the first two bytes represent the number of digits required to // calculate the value followed by the actual bytes for the number. if number > 23 { number -= 23 ; let value = match number { // two bytes 1 => { let value = hex_string . get ( start .. start + 2 ) . ok_or_else ( | | { ApplyError :: InvalidTransaction ( " " . into ( ) ) } ) ? ; start += 2 ; value } // 4 bytes 2 => { let value = hex_string . get ( start .. start + 4 ) . ok_or_else ( | | { ApplyError :: InvalidTransaction ( " " . into ( ) ) } ) ? ; start += 4 ; value } // 8 bytes 3 => { let value = hex_string . get ( start .. start + 8 ) . ok_or_else ( | | { ApplyError :: InvalidTransaction ( " " . into ( ) ) } ) ? ; start += 8 ; value } // Anymore than 8 bytes is not a u32 and is invalid. _ => { return Err ( ApplyError :: InvalidTransaction ( String :: from ( " " , ) ) ) ; } } ; let int_value = u32 :: from_str_radix ( value , 16 ) . map_err ( | err | { ApplyError :: InvalidTransaction ( format ! ( " " err ) ) } ) ? ; output . insert ( name , int_value ) ; } else { let int_value = u32 :: from_str_radix ( number_type , 16 ) . map_err ( | err | { ApplyError :: InvalidTransaction ( format ! ( " " err ) ) } ) ? ; output . insert ( name , int_value ) ; } } Ok ( output ) }
helper function to convert cbor to intkey state.
helper function to convert cbor to intkey state .
hex_string
String