gistools/readers/shapefile/
mod.rs

1/// Database File Reader
2pub mod dbf;
3/// File based functions
4#[cfg(feature = "std")]
5pub mod file;
6/// MMap based functions
7#[cfg(feature = "std")]
8pub mod mmap;
9/// Shape File Reader
10pub mod shp;
11
12use crate::{parsers::BufferReader, proj::Transformer, util::iter_zip_folder};
13use alloc::{collections::BTreeMap, string::String};
14pub use dbf::*;
15use s2json::MValueCompatible;
16pub use shp::*;
17
18/// A description of what relevant files exist and where
19#[cfg(feature = "std")]
20#[derive(Debug)]
21pub struct Definition {
22    /// The path to the .shp file
23    shp: String,
24    /// The path to the .dbf file. dbf is optional, but needed if you want attributes */
25    dbf: Option<String>,
26    /// The path to the .prj file. prj is optional, but needed if your file is in some
27    /// projection you don't want it in
28    prj: Option<String>,
29    /// The path to the .cpg file. cpg is optional, but needed if your dbf is in some
30    /// weird (non utf8) encoding.
31    cpg: Option<String>,
32}
33
34/// # Read a Shapefile from a Gzip folder.
35///
36/// ## Description
37/// Assumes the input is an arraybuffer that is pointing to a collection of zip shapefile data.
38pub fn shapefile_from_gzip<P: MValueCompatible>(
39    input: &[u8],
40    epsg_codes: BTreeMap<String, String>,
41) -> ShapeFileReader<BufferReader, P> {
42    let mut encoding = None;
43    let mut transform = None;
44    let mut dbf_reader = None;
45    let mut shp_data = None;
46    for item in iter_zip_folder(input).unwrap() {
47        if item.filename.ends_with("cpg") {
48            encoding = Some(String::from_utf8_lossy(&(item.read)().unwrap_or_default()).into());
49        } else if item.filename.ends_with("dbf") {
50            if let Ok(data) = (item.read)() {
51                dbf_reader = Some(DataBaseFile::new(data.into(), encoding.clone()));
52            }
53        } else if item.filename.ends_with("shp") {
54            if let Ok(data) = (item.read)() {
55                shp_data = Some(data);
56            }
57        } else if item.filename.ends_with("prj")
58            && let Ok(data) = (item.read)()
59        {
60            let mut transformer = Transformer::new();
61            for (code, value) in epsg_codes.iter() {
62                transformer.insert_epsg_code(code.clone(), value.clone());
63            }
64            transformer.set_source(String::from_utf8_lossy(&data).into());
65            transform = Some(transformer);
66        }
67    }
68    if let Some(shp_data) = shp_data {
69        ShapeFileReader::new(shp_data.into(), dbf_reader, transform)
70    } else {
71        panic!("Shapefile not found");
72    }
73}