typed_shapefile 0.4.1

Read & Write .dbf in Rust
Documentation
pub mod header;
pub mod reader;
pub mod record;

use byteorder::{LittleEndian, ReadBytesExt};
use std::convert::From;
use std::fmt;
use std::io::Read;

pub use reader::{read, read_as, read_shapes, read_shapes_as, Reader, ShapeReader};
pub use record::Multipatch;
pub use record::{convert_shapes_to_vec_of, HasShapeType, ReadableShape};
pub use record::{Multipoint, MultipointM, MultipointZ};
pub use record::{Patch, Shape, NO_DATA};
pub use record::{Point, PointM, PointZ};
pub use record::{Polygon, PolygonM, PolygonRing, PolygonZ};
pub use record::{Polyline, PolylineM, PolylineZ};

extern crate core;

/// All Errors that can happen when using this library
#[derive(Debug)]
pub enum Error {
    /// Wrapper around standard io::Error that might occur when reading/writing
    IoError(std::io::Error),
    /// The file read had an invalid File code (meaning it's not a Shapefile)
    InvalidFileCode(i32),
    /// The file read had an invalid [ShapeType](enum.ShapeType.html) code
    /// (either in the file header or any record type)
    InvalidShapeType(i32),
    /// The Multipatch shape read from the file had an invalid [PatchType](enum.PatchType.html) code
    InvalidPatchType(i32),
    /// Error returned when trying to read the shape records as a certain shape type
    /// but the actual shape type does not correspond to the one asked
    MismatchShapeType {
        /// The requested ShapeType
        requested: ShapeType,
        /// The actual type of the shape
        actual: ShapeType,
    },
    InvalidShapeRecordSize,
    DbaseError(crate::Error),
    MissingDbf,
    MissingIndexFile,
}

impl From<std::io::Error> for Error {
    fn from(error: std::io::Error) -> Error {
        Error::IoError(error)
    }
}

impl From<crate::Error> for Error {
    fn from(e: crate::Error) -> Error {
        Error::DbaseError(e)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::IoError(e) => write!(f, "{}", e),
            Error::InvalidFileCode(code) => write!(
                f,
                "The file code ' {} ' is invalid, is this a Shapefile ?",
                code
            ),
            Error::InvalidShapeType(code) => write!(
                f,
                "The code ' {} ' does not correspond to any of the ShapeType code defined by ESRI",
                code
            ),
            Error::MismatchShapeType { requested, actual } => write!(
                f,
                "The requested type: '{}' does not correspond to the actual shape type: '{}'",
                requested, actual
            ),
            e => write!(f, "{:?}", e),
        }
    }
}

impl std::error::Error for Error {}

/// The enum for the ShapeType as defined in the
/// specification
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum ShapeType {
    NullShape = 0,
    Point = 1,
    Polyline = 3,
    Polygon = 5,
    Multipoint = 8,

    PointZ = 11,
    PolylineZ = 13,
    PolygonZ = 15,
    MultipointZ = 18,

    PointM = 21,
    PolylineM = 23,
    PolygonM = 25,
    MultipointM = 28,

    Multipatch = 31,
}

impl ShapeType {
    pub(crate) fn read_from<T: Read>(source: &mut T) -> Result<ShapeType, Error> {
        let code = source.read_i32::<LittleEndian>()?;
        Self::from(code).ok_or_else(|| Error::InvalidShapeType(code))
    }

    /// Returns the ShapeType corresponding to the input code
    /// if the code is valid
    /// ```
    /// use typed_shapefile::shapefile::ShapeType;
    ///
    /// assert_eq!(ShapeType::from(25), Some(ShapeType::PolygonM));
    /// assert_eq!(ShapeType::from(60), None);
    /// ```
    pub fn from(code: i32) -> Option<ShapeType> {
        match code {
            0 => Some(ShapeType::NullShape),
            1 => Some(ShapeType::Point),
            3 => Some(ShapeType::Polyline),
            5 => Some(ShapeType::Polygon),
            8 => Some(ShapeType::Multipoint),
            11 => Some(ShapeType::PointZ),
            13 => Some(ShapeType::PolylineZ),
            15 => Some(ShapeType::PolygonZ),
            18 => Some(ShapeType::MultipointZ),
            21 => Some(ShapeType::PointM),
            23 => Some(ShapeType::PolylineM),
            25 => Some(ShapeType::PolygonM),
            28 => Some(ShapeType::MultipointM),
            31 => Some(ShapeType::Multipatch),
            _ => None,
        }
    }

    /// Returns whether the ShapeType has the third dimension Z
    pub fn has_z(self) -> bool {
        match self {
            ShapeType::PointZ
            | ShapeType::PolylineZ
            | ShapeType::PolygonZ
            | ShapeType::MultipointZ
            | ShapeType::Multipatch => true,
            _ => false,
        }
    }

    /// Returns whether the ShapeType has the optional measure dimension
    pub fn has_m(self) -> bool {
        match self {
            ShapeType::PointZ
            | ShapeType::PolylineZ
            | ShapeType::PolygonZ
            | ShapeType::MultipointZ
            | ShapeType::PointM
            | ShapeType::PolylineM
            | ShapeType::PolygonM
            | ShapeType::MultipointM => true,
            _ => false,
        }
    }

    /// Returns true if the shape may have multiple parts
    pub fn is_multipart(self) -> bool {
        match self {
            ShapeType::Point
            | ShapeType::PointM
            | ShapeType::PointZ
            | ShapeType::Multipoint
            | ShapeType::MultipointM
            | ShapeType::MultipointZ => false,
            _ => true,
        }
    }
}

impl fmt::Display for ShapeType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ShapeType::NullShape => write!(f, "NullShape"),
            ShapeType::Point => write!(f, "Point"),
            ShapeType::Polyline => write!(f, "Polyline"),
            ShapeType::Polygon => write!(f, "Polygon"),
            ShapeType::Multipoint => write!(f, "Multipoint"),
            ShapeType::PointZ => write!(f, "PointZ"),
            ShapeType::PolylineZ => write!(f, "PolylineZ"),
            ShapeType::PolygonZ => write!(f, "PolygonZ"),
            ShapeType::MultipointZ => write!(f, "MultipointZ"),
            ShapeType::PointM => write!(f, "PointM"),
            ShapeType::PolylineM => write!(f, "PolylineM"),
            ShapeType::PolygonM => write!(f, "PolygonM"),
            ShapeType::MultipointM => write!(f, "MultipointM"),
            ShapeType::Multipatch => write!(f, "Multipatch"),
        }
    }
}