check this code:


impl Bed12 {
    pub fn new(line: &str) -> Result<Bed12, &'static str> {
        let fields: Vec<&str> = line.split('\t').collect();

        if fields.len() < MIN_BED_FIELDS {
            return Err("Bed line has less than 12 fields and cannot be parsed into a Record");
        }

        let chrom = fields[0].to_string();
        let tx_start = fields[1]
            .parse::<u64>()
            .map_err(|_| "Cannot parse tx_start")?;
        let tx_end = fields[2]
            .parse::<u64>()
            .map_err(|_| "Cannot parse tx_end")?;
        let id = Arc::from(fields[3]);
        let strand = fields[5]
            .parse::<char>()
            .map_err(|_| "Cannot parse strand")?;
        let cds_start = fields[6]
            .parse::<u64>()
            .map_err(|_| "Cannot parse cds_start")?;
        let cds_end = fields[7]
            .parse::<u64>()
            .map_err(|_| "Cannot parse cds_end")?;
        let exon_start = fields[11]
            .split(',')
            .filter(|s| !s.is_empty())
            .map(|x| x.parse::<u64>())
            .collect::<Result<Vec<u64>, _>>();
        let exon_end = fields[10]
            .split(',')
            .filter(|s| !s.is_empty())
            .map(|x| x.parse::<u64>())
            .collect::<Result<Vec<u64>, _>>();

        let exon_start = exon_start.map_err(|_| "Cannot parse exon_start")?;
        let exon_end = exon_end.map_err(|_| "Cannot parse exon_end")?;

        if exon_start.len() != exon_end.len() {
            return Err("Exon start and end vectors have different lengths");
        }

        let exon_starts: Vec<u64> = exon_start.iter().map(|&s| s + tx_start).collect();
        let exon_ends: Vec<u64> = exon_end
            .iter()
            .enumerate()
            .map(|(i, &s)| s + exon_starts[i])
            .collect();

        let exons = exon_starts
            .iter()
            .zip(exon_ends.iter())
            .map(|(&s, &e)| (s, e))
            .collect::<HashSet<(u64, u64)>>();

        let introns = exon_starts[1..]
            .iter()
            .map(|&s| s - 1)
            .zip(exon_ends[..exon_ends.len() - 1].iter().map(|&e| e + 1))
            .map(|(s, e)| (e, s))
            .filter(|&(e, s)| e < s)
            .collect::<HashSet<(u64, u64)>>();

        let exons = match strand {
            '+' => exons,
            '-' => exons
                .iter()
                .map(|(s, e)| (SCALE - *e, SCALE - *s))
                .collect(),
            _ => return Err("Strand is not + or -"),
        };

        let introns = match strand {
            '+' => introns,
            '-' => introns
                .iter()
                .map(|(s, e)| (SCALE - *e, SCALE - *s))
                .collect(),
            _ => return Err("Strand is not + or -"),
        };

        let utr = match strand {
            '+' => Utr::new(tx_start, cds_start, cds_end, tx_end),
            '-' => Utr::new(
                SCALE - tx_end,
                SCALE - cds_end,
                SCALE - cds_start,
                SCALE - tx_start,
            ),
            _ => return Err("Strand is not + or -"),
        };

        let tx_start_stranded = match strand {
            '+' => tx_start,
            '-' => SCALE - tx_end,
            _ => return Err("Strand is not + or -"),
        };

        let tx_end_stranded = match strand {
            '+' => tx_end,
            '-' => SCALE - tx_start,
            _ => return Err("Strand is not + or -"),
        };

        Ok(Bed12 {
            chrom: chrom.to_string(),
            info: (tx_start_stranded, tx_end_stranded, exons, introns, utr, id),
            line: line.to_string(),
        })
    }
}

you are an expert Rust programmer. Any idea on how to make it more elegant, efficient or faster?