shapefile 0.1.0

Read & Write shapefiles in Rust
Documentation
use std::io::{Read, Write};

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use record::traits::{HasM, HasMutXY, HasXY};
use record::{is_no_data, PointZ, NO_DATA};

pub(crate) fn read_xy_in_vec_of<PointType, T>(
    source: &mut T,
    num_points: i32,
) -> Result<Vec<PointType>, std::io::Error>
where
    PointType: HasMutXY + Default,
    T: Read,
{
    let mut points = Vec::<PointType>::with_capacity(num_points as usize);
    for _ in 0..num_points {
        let mut p = PointType::default();
        *p.x_mut() = source.read_f64::<LittleEndian>()?;
        *p.y_mut() = source.read_f64::<LittleEndian>()?;
        points.push(p);
    }
    Ok(points)
}

pub(crate) fn read_ms_into<T: Read, D: HasM>(
    source: &mut T,
    points: &mut Vec<D>,
) -> Result<(), std::io::Error> {
    for point in points {
        *point.m_mut() = f64::max(source.read_f64::<LittleEndian>()?, NO_DATA);
    }
    Ok(())
}

pub(crate) fn read_zs_into<T: Read>(
    source: &mut T,
    points: &mut Vec<PointZ>,
) -> Result<(), std::io::Error> {
    for point in points.iter_mut() {
        point.z = source.read_f64::<LittleEndian>()?;
    }
    Ok(())
}

pub(crate) fn read_range<T: Read>(source: &mut T) -> Result<[f64; 2], std::io::Error> {
    let mut range = [0.0, 0.0];
    range[0] = source.read_f64::<LittleEndian>()?;
    range[1] = source.read_f64::<LittleEndian>()?;
    Ok(range)
}

pub(crate) fn read_parts<T: Read>(
    source: &mut T,
    num_parts: i32,
) -> Result<Vec<i32>, std::io::Error> {
    let mut parts = Vec::<i32>::with_capacity(num_parts as usize);
    for _ in 0..num_parts {
        parts.push(source.read_i32::<LittleEndian>()?);
    }
    Ok(parts)
}

pub(crate) fn write_points<T: Write, PointType: HasXY>(
    dest: &mut T,
    points: &[PointType],
) -> Result<(), std::io::Error> {
    for point in points {
        dest.write_f64::<LittleEndian>(point.x())?;
        dest.write_f64::<LittleEndian>(point.y())?;
    }
    Ok(())
}

pub(crate) fn write_ms<T: Write, PointType: HasM>(
    dest: &mut T,
    points: &[PointType],
) -> Result<(), std::io::Error> {
    for point in points {
        dest.write_f64::<LittleEndian>(point.m())?;
    }
    Ok(())
}

pub(crate) fn write_zs<T: Write>(dest: &mut T, points: &[PointZ]) -> Result<(), std::io::Error> {
    for point in points {
        dest.write_f64::<LittleEndian>(point.z)?;
    }
    Ok(())
}

pub(crate) fn write_parts<T: Write>(dest: &mut T, parts: &[i32]) -> Result<(), std::io::Error> {
    for p in parts {
        dest.write_i32::<LittleEndian>(*p)?;
    }
    Ok(())
}

pub(crate) fn write_range<T: Write>(dest: &mut T, range: [f64; 2]) -> Result<(), std::io::Error> {
    dest.write_f64::<LittleEndian>(range[0])?;
    dest.write_f64::<LittleEndian>(range[1])?;
    Ok(())
}

pub(crate) fn calc_m_range<PointType: HasM>(points: &[PointType]) -> [f64; 2] {
    let mut range = [std::f64::MAX, std::f64::MIN];
    for point in points {
        range[0] = f64::min(range[0], point.m());
        range[1] = f64::max(range[1], point.m());
    }

    if is_no_data(range[0]) {
        range[0] = 0.0;
    }

    if is_no_data(range[1]) {
        range[1] = 0.0;
    }

    range
}

pub(crate) fn calc_z_range(points: &[PointZ]) -> [f64; 2] {
    let mut range = [std::f64::MAX, std::f64::MIN];
    for point in points {
        range[0] = f64::min(range[0], point.z);
        range[1] = f64::max(range[1], point.z);
    }
    range
}