Tag Archives: concat

Rust – Arrays? Make chains, not concat!

If your application needs to iterate over a bunch of items from different sources or arrays, someone with C/C++ background might copy all items into a single vector and iterate this vector.

This strategy will cause high costs in terms of allocating heap memory for the consecutive vector buffer.

Instead, keep the data where it is, and chain it together to form an iterator over a virtual array.

The following Rust code demonstrates the chaining of multiple arrays, forming a single iterator, without any additional allocation of vector buffer in heap.

Note, the zip operation in the following code snippet pairs each item with a slot in the buffer. The zip will stop if either end is reached, the end of chained_byte_sequence or the end of therequest buffer, whichever comes first. Just, the length of chained_byte_sequence might be unknown and only a single pass shall be performed. So, how do we know all items have been written, and the amount? The solution is to borrow the iterator via chained_byte_sequence.by_ref(), iterating the chain and finally verifying if any item remained in the sequence chained_byte_sequence.next()!=None.

  let req_method_get = b"GET ";
    let req_method_head = b"HEAD ";
    let uri = b"/infotext.html HTTP/1.1";

    let mut request = [0 as u8; 128];

    // chaining various byte-arrays together, for example two here:
    let mut chained_byte_sequence =  req_method_get.iter()
        .chain(uri.iter());

    // take a ref and zip against the destination buffer and 
    // while iterating via fold, each element is counted.
    let  nwritten =
        chained_byte_sequence
        .by_ref()
        .zip(request.as_mut())
            .fold(0, |cnt, (item, slot) | {
                *slot = item.clone(); cnt+1
            });

    // finally, verify the iterator of the chained_byte_sequence is empty
    if chained_byte_sequence.next()!=None {
        /* slice too short */ panic!();
    } else {
        println!("{:?}", &request[0..nwritten].as_ref());
    };