rexsgdata 0.12.0

Scatter-Gather Data Descriptors
Documentation
//
// Copyright (c) 2019 RepliXio Ltd. All rights reserved.
// Use is subject to license terms.
//

use std::mem;

use bincode::{deserialize, serialize};
use libc::{c_void, iovec};
use rexsgdata::{Iovec, SgData, SgList};
use serde_test::{assert_ser_tokens, Token};

// NB - never use this code outside of the tests - it leaks memory
fn vec_into_iovec(mut vec: Vec<u8>) -> iovec {
    let len = vec.len();
    let base = vec.as_mut_ptr();
    mem::forget(vec);
    iovec {
        iov_base: base as *mut c_void,
        iov_len: len,
    }
}

// NB - never use this code outside of the tests - it leaks memory
fn create_sglist(sgvec: Vec<Vec<u8>>) -> SgList {
    let vec = sgvec.into_iter().map(vec_into_iovec).collect::<Vec<_>>();
    let len = vec.len();
    let iov = vec.as_ptr();
    mem::forget(vec);
    SgList::new(iov, len)
}

#[test]
fn add_buf() {
    let mut data: SgData = vec![12, 56, 34].into();
    data += vec![255, 129, 99].into();

    assert_eq!(data, vec![12, 56, 34, 255, 129, 99].into());
    assert_eq!(
        data + vec![0, 111, 222].into(),
        vec![12, 56, 34, 255, 129, 99, 0, 111, 222].into()
    );
}

#[test]
fn add_vec() {
    let mut data: SgData = vec![vec![12, 56], vec![16, 27, 38]].into();
    data += vec![255, 129].into();

    assert_eq!(
        data,
        vec![vec![12, 56], vec![16, 27, 38], vec![255, 129]].into()
    );
    assert_eq!(
        data + vec![0, 111].into(),
        vec![vec![12, 56], vec![16, 27, 38], vec![255, 129], vec![0, 111]].into()
    );
}

#[test]
fn clone_from() {
    let iovec = vec![vec![0; 1024], vec![0; 1024], vec![0; 1024]];
    let (base, count) = create_sglist(iovec).into_inner();

    let data: SgData = vec![0xAA; 3072].into();
    let sglist = unsafe { data.drain_into(base as *mut libc::iovec, count) };

    let buf = serialize(&sglist).unwrap();
    let sgvec: SgData = deserialize(&buf).unwrap();
    let buf = serialize(&sgvec).unwrap();
    let direct: SgData = deserialize(&buf).unwrap();

    assert_eq!(SgData::from(vec![0xAA; 3072]), direct);
}

#[test]
fn sglist_capacity() {
    let sgvec = vec![vec![0; 345], vec![0; 123], vec![0; 2000]];
    let sglist = create_sglist(sgvec);
    let capacity = unsafe { sglist.capacity() };
    assert_eq!(capacity, 2468);
}

#[test]
fn iter_sgvec() {
    let v1 = vec![12, 56, 76];
    let v2 = vec![128, 255];
    let data: SgData = vec![v1.clone(), v2.clone()].into();
    let mut iter = data.iter();
    assert_eq!(iter.next(), Some(v1.as_slice()));
    assert_eq!(iter.next(), Some(v2.as_slice()));
    assert_eq!(iter.next(), None);
}

#[test]
fn drain_into() {
    let sgdata: SgData = vec![0, 202, 3, 4, 10, 23, 12, 134, 45, 198].into();
    let iov = vec![vec![0; 5], vec![0; 2], vec![0; 3]];
    let (iovec, count) = create_sglist(iov).into_inner();
    let sgdata: SgData = unsafe { sgdata.drain_into(iovec as *mut iovec, count) };

    assert_eq!(sgdata.size(), 3);

    let mut slices = sgdata.iter();

    assert_eq!(slices.next(), Some([0, 202, 3, 4, 10].as_ref()));
    assert_eq!(slices.next(), Some([23, 12].as_ref()));
    assert_eq!(slices.next(), Some([134, 45, 198].as_ref()));
    assert_eq!(slices.next(), None);
}

#[test]
fn iter_direct() {
    let v1 = vec![12, 56, 34, 255, 0];
    let data: SgData = v1.clone().into();
    let mut iter = data.iter();

    assert_eq!(iter.next(), Some(v1.as_slice()));
    assert_eq!(iter.next(), None);
}

#[test]
fn sglist_serde() {
    let sgvec = vec![vec![0x45_u8; 4096]; 5];
    let data: SgData = unsafe { SgData::from_sglist(create_sglist(sgvec)) };
    let buf = serialize(&data).unwrap();
    let data: SgData = deserialize(&buf).unwrap();

    assert_eq!(data, SgData::from(vec![0x45_u8; 4096 * 5]));
}

#[test]
fn iovec_serde() {
    let data: SgData = vec![vec![0x46; 4096]; 7]
        .into_iter()
        .map(vec_into_iovec)
        .map(Iovec::from)
        .collect();

    let buf = serialize(&data).unwrap();
    let data: SgData = deserialize(&buf).unwrap();

    assert_eq!(data, SgData::from(vec![vec![0x46; 4096]; 7]));
}

#[test]
fn sgvec_serde() {
    let data: SgData = vec![vec![12, 56, 76], vec![128, 255]].into();
    let buf = serialize(&data).unwrap();
    let data: SgData = deserialize(&buf).unwrap();

    assert_eq!(data, SgData::from(vec![12, 56, 76, 128, 255]));
}

#[test]
fn mixed_serde() {
    let data: SgData = unsafe {
        SgData::from(vec![0xa2; 2])
            + SgData::from_sglist(create_sglist(vec![vec![12, 56, 76], vec![128, 255]]))
            + Iovec::from(vec_into_iovec(vec![0x5a; 3])).into()
    };
    let buf = serialize(&data).unwrap();
    let data: SgData = deserialize(&buf).unwrap();
    let expected = SgData::from(vec![0xa2, 0xa2, 12, 56, 76, 128, 255, 0x5a, 0x5a, 0x5a]);

    assert_eq!(data, expected);
}

mod tokens {
    use super::*;

    #[test]
    fn direct() {
        let data: SgData = vec![12, 56, 34, 0, 255].into();

        assert_ser_tokens(
            &data,
            &[
                Token::Struct {
                    name: "SgData",
                    len: 1,
                },
                Token::Str("data"),
                Token::Seq { len: Some(1) },
                Token::Bytes(&[12, 56, 34, 0, 255]),
                Token::SeqEnd,
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn sglist() {
        let data: SgData =
            unsafe { SgData::from_sglist(create_sglist(vec![vec![12, 56, 76], vec![128, 255]])) };

        assert_ser_tokens(
            &data,
            &[
                Token::Struct {
                    name: "SgData",
                    len: 1,
                },
                Token::Str("data"),
                Token::Seq { len: Some(2) },
                Token::Bytes(&[12, 56, 76]),
                Token::Bytes(&[128, 255]),
                Token::SeqEnd,
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn iovec() {
        let data: SgData = vec![vec![36, 123, 234], vec![87, 187, 211, 45]]
            .into_iter()
            .map(vec_into_iovec)
            .map(Iovec::from)
            .collect();

        assert_ser_tokens(
            &data,
            &[
                Token::Struct {
                    name: "SgData",
                    len: 1,
                },
                Token::Str("data"),
                Token::Seq { len: Some(2) },
                Token::Bytes(&[36, 123, 234]),
                Token::Bytes(&[87, 187, 211, 45]),
                Token::SeqEnd,
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn mixed() {
        let data: SgData = unsafe {
            SgData::from(vec![0xa2; 4])
                + SgData::from_sglist(create_sglist(vec![vec![12, 56, 76], vec![128, 255]]))
                + Iovec::from(vec_into_iovec(vec![0x5a; 4])).into()
        };

        assert_ser_tokens(
            &data,
            &[
                Token::Struct {
                    name: "SgData",
                    len: 1,
                },
                Token::Str("data"),
                Token::Seq { len: Some(4) },
                Token::Bytes(&[0xa2; 4]),
                Token::Bytes(&[12, 56, 76]),
                Token::Bytes(&[128, 255]),
                Token::Bytes(&[0x5a; 4]),
                Token::SeqEnd,
                Token::StructEnd,
            ],
        );
    }
}

mod version {
    #[test]
    fn version() {
        assert_eq!(rexsgdata::VERSION, env!("CARGO_PKG_VERSION"));
    }
}