fn try_from()

in reverie-util/src/pedigree.rs [100:173]


    fn try_from(pedigree: &Pedigree) -> Result<Self, Self::Error> {
        // Define mpping of pedigree bits -> PID bits
        const MSB_ZERO_BITS: usize = 1;
        const TREE_BITS: usize = 16;
        const RUN_INDEX_BITS: usize = 4;
        const RUN_TYPE_BITS: usize = 1;
        const RUN_LENGTH_BITS: usize = 10;
        debug_assert!(
            MSB_ZERO_BITS + TREE_BITS + RUN_INDEX_BITS + RUN_TYPE_BITS + RUN_LENGTH_BITS
                == mem::size_of::<pid_t>() * 8
        );

        // Trim off any trailing P's from pedigree, i.e. viewing it as
        // a sequence of 'P' (parent) and 'C' (child) directions.
        let mut sequence = pedigree.raw();
        while sequence.len() > 1 && sequence.last() == Some(&false) {
            sequence.pop();
        }

        // Find longest run in pedigree sequence
        let (index, len) = longest_run(&sequence);

        // Make sure pedigree will fit into the bit encoding
        if index >= 2_usize.pow(RUN_INDEX_BITS as u32)
            || len >= 2_usize.pow(RUN_LENGTH_BITS as u32)
            || sequence.len() - len > TREE_BITS
        {
            Err(Self::Error::new(
                io::ErrorKind::Other,
                "Pedigree is too large or complex to be deterministically converted into virtual PID.",
            ))
        } else {
            // Extract the longest run of bits from pedigree
            let mut lower_tree = sequence.split_off(index + len);
            let run = sequence.split_off(index);
            let mut tree = sequence;
            tree.append(&mut lower_tree);

            // Construct a BitVec which will be interpreted as a pid_t
            let mut vpid_bits: BitVec<Msb0, u32> =
                BitVec::with_capacity(mem::size_of::<pid_t>() * 8);

            // pid_t is signed, so MSB must always be zero or it will be interpreted as error
            // when returned from fork, clone, etc.
            vpid_bits.push(false);

            // Pack the rest of the bits, using asserts to make sure the bitfield sizing
            // is correct. Any errors here are fatal bugs, so assert seems acceptable.

            let mut tree_bits: BitVec<Msb0, u32> = BitVec::repeat(false, TREE_BITS - tree.len());
            tree_bits.append(&mut tree);
            debug_assert!(tree_bits.len() == TREE_BITS);
            vpid_bits.append(&mut tree_bits);

            let mut run_index_bits = BitVec::<Msb0, u32>::from_element(index as u32);
            run_index_bits = run_index_bits.split_off(run_index_bits.len() - RUN_INDEX_BITS);
            debug_assert!(run_index_bits.len() == RUN_INDEX_BITS);
            vpid_bits.append(&mut run_index_bits);

            let mut run_type_bits: BitVec<Msb0, u32> = BitVec::new();
            run_type_bits.push(run[0]);
            debug_assert!(run_type_bits.len() == RUN_TYPE_BITS);
            vpid_bits.append(&mut run_type_bits);

            let mut run_length_bits = BitVec::<Msb0, u32>::from_element(len as u32);
            run_length_bits = run_length_bits.split_off(run_length_bits.len() - RUN_LENGTH_BITS);
            debug_assert!(run_length_bits.len() == RUN_LENGTH_BITS);
            vpid_bits.append(&mut run_length_bits);

            debug_assert!(vpid_bits.len() == mem::size_of::<pid_t>() * 8);

            Ok(Pid::from_raw(vpid_bits.into_vec()[0] as i32))
        }
    }