2
\$\begingroup\$

As a first project in Rust, I'm translating an existing, working piece of Python code. This code's purpose is to convert a 15-character Salesforce Id (which is guaranteed to be ASCII, exactly 15 bytes of base-62 data) to its 18-character equivalent, which includes a 3-character suffix to discriminate between values differing from one another only in case.

The Rust code works. I am looking for guidance on how to improve its idiomaticity in Rust, particularly around processing this type of data. It's a String conceptually, but doesn't need the overhead of UTF-8 handling, and is likely to be read from (e.g.) CSV files or Web services that do return UTF-8 encoded data.

I also suspect that the way I handle the "accumulator" values suffix and base_two is not proper Rust and welcome education there.

Python

class SalesforceId(object):
    def __init__(self, idstr):
        if isinstance(idstr, SalesforceId):
            self.id = idstr.id
        else:
            idstr = idstr.strip()
            if len(idstr) == 15:
                suffix = ''
                for i in range(0, 3):
                    baseTwo = 0
                    for j in range (0, 5):
                        character = idstr[i*5+j]
                        if character >= 'A' and character <= 'Z':
                            baseTwo += 1 << j
                    suffix += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345'[baseTwo]
                self.id = idstr + suffix
            elif len(idstr) == 18:
                self.id = idstr
            else:
                raise ValueError('Salesforce Ids must be 15 or 18 characters.')

Rust

#[derive(Debug)]
struct SalesforceId(String);

impl SalesforceId {
    fn from_string(s: &str) -> SalesforceId {
        let b = s.as_bytes();
        match b.len() {
            18 => { SalesforceId(s.to_string()) }
            15 => {
                let mut suffix: [u8; 3] = [b'A', b'A', b'A'];
                for i in 0..3 {
                    let mut base_two = 0;
                    for j in 0..5 {
                        let character = b[i*5+j];
                        if character >= b'A' && character <= b'Z' {
                            base_two += 1 << j;
                        }
                    }

                    suffix[i] = b'A' + base_two
                }
                SalesforceId(format!("{}{}", s, std::str::from_utf8(&suffix).unwrap()))
            }
            _ => panic!("invalid Salesforce Id")
        }
    }
}

fn main() {
    println!("{:?}", SalesforceId::from_string("0063600000aqQ1h"));
}
\$\endgroup\$
  • \$\begingroup\$ play.rust-lang.org/… \$\endgroup\$ – Stargateur Mar 12 at 2:25
  • \$\begingroup\$ ABCDEFGHIJKLMNOPQRSTUVWXYZ012345'[baseTwo] != suffix[i] = b'A' + base_two are you sure your code is correct ? \$\endgroup\$ – Stargateur Mar 12 at 2:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.