1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110

use std::fs::{File};
use std::io::BufReader;

use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt};

use {Affine, Header, Point, Points, Streamlines, Translation};
use cheader::{Endianness};

pub struct Reader {
    reader: BufReader<File>,
    endianness: Endianness,
    pub header: Header,
    pub affine: Affine,
    pub translation: Translation,

    nb_floats_per_point: usize,
    float_buffer: Vec<f32>
}

impl Reader {
    pub fn new(path: &str) -> Reader {
        let f = File::open(path).expect("Can't read trk file.");
        let mut reader = BufReader::new(f);

        let (header, endianness) = Header::read(&mut reader);
        let affine = header.affine;
        let translation = header.translation;
        let nb_floats_per_point = 3 + header.scalars.len() as usize;

        Reader {
            reader, endianness, header, affine, translation,
            nb_floats_per_point, float_buffer: Vec::with_capacity(300)
        }
    }

    pub fn read_all(&mut self) -> Streamlines {
        match self.endianness {
            Endianness::Little => self.read_all_::<LittleEndian>(),
            Endianness::Big => self.read_all_::<BigEndian>()
        }
    }

    fn read_all_<E: ByteOrder>(&mut self) -> Streamlines {
        self.header.scalars.reserve(300);
        self.header.properties.reserve(self.header.nb_streamlines);

        let mut lengths = Vec::new();
        let mut v = Vec::with_capacity(300);
        while let Ok(nb_points) = self.reader.read_i32::<E>() {
            lengths.push(nb_points as usize);
            self.read_streamline::<E>(&mut v, nb_points as usize);
        }
        self.float_buffer = vec![];
        Streamlines::new(lengths, v)
    }

    fn read_streamline<E: ByteOrder>(
        &mut self,
        points: &mut Points,
        nb_points: usize)
    {
        // Vec::resize never decreases capacity, it can only increase it
        // so there won't be any useless allocation.
        let nb_floats = nb_points * self.nb_floats_per_point;
        self.float_buffer.resize(nb_floats as usize, 0.0);
        self.reader.read_f32_into_unchecked::<E>(
            self.float_buffer.as_mut_slice()).unwrap();

        for floats in self.float_buffer.chunks(self.nb_floats_per_point) {
            let p = Point::new(floats[0], floats[1], floats[2]);
            points.push((p * self.affine) + self.translation);

            for (&mut (_, ref mut scalar), f) in self.header.scalars.iter_mut()
                                                 .zip(&floats[3..]) {
                scalar.push(*f);
            }
        }

        for &mut (_, ref mut scalar) in &mut self.header.scalars {
            scalar.end_push();
        }

        for &mut (_, ref mut property) in &mut self.header.properties {
            property.push(self.reader.read_f32::<E>().unwrap());
        }
    }
}

impl Iterator for Reader {
    type Item = Points;

    fn next(&mut self) -> Option<Points> {
        if let Ok(nb_points) = match self.endianness {
            Endianness::Little => self.reader.read_i32::<LittleEndian>(),
            Endianness::Big => self.reader.read_i32::<BigEndian>()
        } {
            let mut points = Vec::with_capacity(nb_points as usize);
            match self.endianness {
                Endianness::Little => self.read_streamline::<LittleEndian>(
                    &mut points, nb_points as usize),
                Endianness::Big => self.read_streamline::<BigEndian>(
                    &mut points, nb_points as usize)
            };
            Some(points)
        } else {
            None
        }
    }
}