rsc_osrm 0.1.56

rust wrapper for osrm, folk from TehGoat/rs_osrm
use crate::Osrm;
use crate::Status;
use std::os::raw::{c_int, c_void};

#[link(name = "c_osrm")]
extern "C" {
    fn tile_result_destroy(result: *mut CTileResult);

    fn osrm_tile(
        osrm: *mut c_void,
        request: *mut CTileRequest,
        result: *mut *mut CTileResult,
    ) -> Status;
}

#[repr(C)]
struct CTileRequest {
    x: c_int,
    y: c_int,
    z: c_int,
}

impl CTileRequest {
    fn new(request: &mut TileRequest) -> CTileRequest {
        CTileRequest {
            x: request.x,
            y: request.y,
            z: request.z,
        }
    }
}

pub struct TileRequest {
    x: i32,
    y: i32,
    z: i32,
}

impl TileRequest {
    pub fn new(x: i32, y: i32, z: i32) -> TileRequest {
        TileRequest { x, y, z }
    }

    pub fn run(&mut self, osrm: &Osrm) -> (Status, TileResult) {
        unsafe {
            let mut result: *mut CTileResult = std::ptr::null_mut();
            let result_ptr: *mut *mut CTileResult = &mut result;

            let status = osrm_tile(
                *osrm.config,
                &mut CTileRequest::new(self) as *mut CTileRequest,
                result_ptr,
            );

            let converted_result = TileResult::new(&(*result));

            tile_result_destroy(result);

            (status, converted_result)
        }
    }
}

#[repr(C)]
struct CTileResult {
    result: *const u8,
    string_length: c_int,
}

pub struct TileResult {
    pub result: Vec<u8>,
}

impl TileResult {
    fn new(c_result: &CTileResult) -> TileResult {
        let mut result = TileResult { result: Vec::new() };

        let converted_result = unsafe {
            std::slice::from_raw_parts(
                c_result.result as *const u8,
                c_result.string_length as usize,
            )
        };

        for value in converted_result {
            result.result.push(value.clone());
        }

        result
    }
}