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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//! OxiGDAL Shapefile Driver - ESRI Shapefile Implementation
//!
//! This crate provides a pure Rust implementation of ESRI Shapefile reading and writing
//! for the OxiGDAL ecosystem. It supports the complete Shapefile format including:
//!
//! - `.shp` files (geometry)
//! - `.dbf` files (attributes)
//! - `.shx` files (spatial index)
//!
//! # Supported Geometry Types
//!
//! - Point, PointZ, PointM
//! - PolyLine, PolyLineZ, PolyLineM
//! - Polygon, PolygonZ, PolygonM
//! - MultiPoint, MultiPointZ, MultiPointM
//!
//! # Features
//!
//! - Pure Rust implementation (no C/Fortran dependencies)
//! - Support for all DBF field types (Character, Number, Logical, Date, Float)
//! - Proper encoding handling with code page support
//! - Comprehensive error handling
//! - No `unwrap()` or `panic!()` in production code
//! - Round-trip compatibility (read → modify → write)
//! - Spatial index (.shx) support
//!
//! # Example - Reading
//!
//! ```rust,no_run
//! use oxigdal_shapefile::ShapefileReader;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Open a Shapefile (reads .shp, .dbf, and .shx)
//! let reader = ShapefileReader::open("path/to/shapefile")?;
//!
//! // Read all features
//! let features = reader.read_features()?;
//!
//! for feature in &features {
//! println!("Record {}: {:?}", feature.record_number, feature.geometry);
//! println!("Attributes: {:?}", feature.attributes);
//! }
//! # Ok(())
//! # }
//! ```
//!
//! # Example - Writing
//!
//! ```rust,no_run
//! use oxigdal_shapefile::{ShapefileWriter, ShapefileSchemaBuilder};
//! use oxigdal_shapefile::shp::shapes::ShapeType;
//! use std::env;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Create schema
//! let schema = ShapefileSchemaBuilder::new()
//! .add_character_field("NAME", 50)?
//! .add_numeric_field("VALUE", 10, 2)?
//! .build();
//!
//! // Create writer
//! let temp_dir = env::temp_dir();
//! let output_path = temp_dir.join("output");
//! let mut writer = ShapefileWriter::new(output_path, ShapeType::Point, schema)?;
//!
//! // Write features (example omitted for brevity)
//! // writer.write_features(&features)?;
//! # Ok(())
//! # }
//! ```
//!
//! # File Format
//!
//! A Shapefile consists of three required files:
//!
//! 1. **`.shp`** - Main file containing geometry data
//! 2. **`.dbf`** - dBase file containing attribute data
//! 3. **`.shx`** - Index file containing record offsets
//!
//! Additional optional files include `.prj` (projection), `.cpg` (code page), etc.
//!
//! # Binary Format Details
//!
//! ## .shp File Structure
//!
//! - Header (100 bytes)
//! - File code: 9994 (big endian)
//! - File length in 16-bit words (big endian)
//! - Version: 1000 (little endian)
//! - Shape type (little endian)
//! - Bounding box (8 doubles, little endian)
//! - Records (variable length)
//! - Record header (8 bytes, big endian)
//! - Shape content (variable, little endian)
//!
//! ## .dbf File Structure
//!
//! - Header (32 bytes)
//! - Version, date, record count, header size, record size
//! - Field descriptors (32 bytes each)
//! - Header terminator (0x0D)
//! - Records (fixed length based on field descriptors)
//! - File terminator (0x1A)
//!
//! ## .shx File Structure
//!
//! - Header (100 bytes, same as .shp)
//! - Index entries (8 bytes each)
//! - Offset (4 bytes, big endian)
//! - Content length (4 bytes, big endian)
//!
//! # COOLJAPAN Policies
//!
//! - Pure Rust implementation (no C/C++ dependencies)
//! - No `unwrap()` or `expect()` in production code
//! - Comprehensive error handling with descriptive errors
//! - Extensive testing (unit + integration + property-based)
//! - Clean API design following Rust idioms
//! - Files under 2000 lines (use splitrs for refactoring)
//!
//! # Performance Considerations
//!
//! - Buffered I/O for efficient reading/writing
//! - Spatial index (.shx) for fast random access
//! - Streaming API for large files (iterate records one at a time)
//! - Zero-copy optimizations where possible
//!
//! # Limitations
//!
//! - Currently only Point geometries are fully supported for conversion to OxiGDAL
//! - PolyLine, Polygon, and MultiPoint parsing is implemented but conversion pending
//! - MultiPatch (3D surfaces) support is limited
//! - No support for memo fields (.dbt files)
//!
//! # References
//!
//! - [ESRI Shapefile Technical Description](https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf)
//! - [dBase File Format](http://www.dbase.com/Knowledgebase/INT/db7_file_fmt.htm)
// Pedantic disabled to reduce noise - default clippy::all is sufficient
// #![warn(clippy::pedantic)]
// Allow slice patterns
// Allow partial documentation
// Allow collapsible match for explicit branching
extern crate std;
// Re-export commonly used types
pub use ;
pub use ;
pub use ;
pub use ;
// Re-export shape types
pub use ;
pub use ;
// Re-export DBF types
pub use ;
/// Crate version
pub const VERSION: &str = env!;
/// Crate name
pub const NAME: &str = env!;
/// Shapefile magic number (file code)
pub const FILE_CODE: i32 = 9994;
/// Shapefile version
pub const FILE_VERSION: i32 = 1000;
/// Shapefile file extension
pub const FILE_EXTENSION: &str = ".shp";
/// DBF file extension
pub const DBF_EXTENSION: &str = ".dbf";
/// SHX file extension
pub const SHX_EXTENSION: &str = ".shx";