1use crate::constants::*;
15use crate::errors::DigipinError;
16use crate::location::Location;
17use crate::validation::{validate_digipin_territory, validate_geodetic_coordinates};
18
19pub fn encode(location: Location) -> Result<String, DigipinError> {
26 validate_geodetic_coordinates(location)?;
27 validate_digipin_territory(location)?;
28
29 let mut latitude_min = DIGIPIN_LATITUDE_MIN;
30 let mut latitude_max = DIGIPIN_LATITUDE_MAX;
31 let mut longitude_min = DIGIPIN_LONGITUDE_MIN;
32 let mut longitude_max = DIGIPIN_LONGITUDE_MAX;
33
34 let mut digipin = String::with_capacity(DIGIPIN_LENGTH);
35
36 for _ in 0..DIGIPIN_LENGTH {
37 let latitude_step = (latitude_max - latitude_min) / DIGIPIN_GRID_SIZE as f64;
38 let longitude_step = (longitude_max - longitude_min) / DIGIPIN_GRID_SIZE as f64;
39
40 let mut row = ((latitude_max - location.latitude) / latitude_step).floor() as usize;
41 let mut column = ((location.longitude - longitude_min) / longitude_step).floor() as usize;
42
43 row = row.min(DIGIPIN_GRID_SIZE - 1);
45 column = column.min(DIGIPIN_GRID_SIZE - 1);
46
47 let symbol = DIGIPIN_LABEL_GRID[row][column];
48 digipin.push(symbol);
49
50 latitude_max -= row as f64 * latitude_step;
51 latitude_min = latitude_max - latitude_step;
52
53 longitude_min += column as f64 * longitude_step;
54 longitude_max = longitude_min + longitude_step;
55 }
56
57 Ok(digipin)
58}