Convert u64 to String for concatenation

Hello team,

I have a following scenario:

fn push_bytes(ref mut a: Bytes, b: Bytes) {
    let mut i = 0;
    while i < b.len() {
        a.push(b.get(i).unwrap());
        i = i + 1;
    }
}

pub fn concat_str_with_num(s: String, num: u64) -> String {
    let mut result = Bytes::new();
    push_bytes(result, s.as_bytes());
    push_bytes(result, String::from_ascii_str("$").as_bytes()); // an arbitrary delimeter
    push_bytes(result, num.to_le_bytes()); // [link to the lib](https://github.com/FuelLabs/sway/blob/master/sway-lib-std/src/bytes_conversions/u64.sw) 
    String::from_ascii(result)
}

The problem is: when I try to create a Unit test like the following:

#[test]
fn test_concat_str_with_num() {
    log(concat_str_with_num(String::from_ascii_str("test"), 1));
    assert(concat_str_with_num(String::from_ascii_str("test"), 1) == String::from_ascii_str("test$1"));
}

tests fail all the time regardless of what endian type I use in the conversion → to_be_bytes() also leads to the same failure of the test.

Could you please tell me if there is a way to concatenate strings like that or where I might be mistaken.

Also I have a follow-up question to this (might create another topic for that): is there any way of how one can display a pointer-based data type in the logs? Currently for any pointer type the response looks like this:

{
    "LogData": {
      "data": "0000000003ffffd20000000000000010000000000000000f",
      "digest": "f0bc62614581cb6b44520055e084416ca3359a15efd3ee394fd83e6f3edb7d92",
      "id": "0000000000000000000000000000000000000000000000000000000000000000",
      "is": 10336,
      "len": 24,
      "pc": 299280,
      "ptr": 308016,
      "ra": 0,
      "rb": 18
    }
  }

Thank you!

EDIT/SOLUTION: the to_le_bytes() returns 8 bytes for num.to_le_bytes() which is totally fine and thus it might concatenate 8 symbols to the string which is not what we want.
I tried several available built-in methods without any luck and came up with my own solution which works but might be unoptimal/not super efficient:

fn convert_num_to_ascii_bytes(num: u64) -> Bytes {
    let mut bytes = Bytes::new();
    let mut n = num;
    if n == 0 {
        bytes.push(48);
        return bytes;
    }
    while n != 0 {
        // 48 - is an ASCII offset for digits
        bytes.push(((n % 10) + 48).try_as_u8().unwrap());
        n /= 10;
    }
    let mut reversed_bytes = Bytes::with_capacity(bytes.len());
    while !bytes.is_empty() {
        reversed_bytes.push(bytes.pop().unwrap());
    }
    return reversed_bytes;
}

Then we can use it like that:

pub fn concat_str_with_num(s: String, num: u64) -> String {
    let mut result = Bytes::new();
    push_bytes(result, s.as_bytes());
    push_bytes(result, String::from_ascii_str("$").as_bytes()); // an arbitrary delimeter
    push_bytes(result, num.convert_num_to_ascii_bytes()); 
    String::from_ascii(result)
}
2 Likes

Hey @Serafim unfortunately there is currently no directly support for string concatenation as it would not conform to the UTF-8 format. The Sway team is aware of the short comings of strings but have been grinding other higher priority features for our upcoming devnet/mainnet. Rest assured that it is accounted for on the roadmap. I appreciate your patience here @Serafim :bowing_man:

3 Likes

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.