Rust Old Version

Hello, I’m a programming enthusiast, and I came across an Arduino project where the author uses the Rust language to convert map files to binary and use them on Arduino.

The code was written in an older version of Rust, and I couldn’t compile it for the newer version. I don’t have enough knowledge to update the code to the latest version.

Could someone help me with how I can compile the code to work correctly?

The source code is in (bicycle_gps)

This is pre-1.0 Rust. Some notable but trivial changes are:

  • int, uint are now called isize and usize
  • Show has been split into Debug and Display, of which only Debug is derive-able
  • std::io::Writer is now Write (and I assume it's the same with Read); IoResult is just Result (in the io module). SeekSet is not a thing.
3 Likes

This compiles, but I recommend you to run clippy to adapt the code to more best current practices. I changed some dependencies to more modern equivalents. Also, I've never used the postgres crate and don't know if it will work reading and writing the json. Please test thoroughly.

/*
[dependencies]
postgres = {version="0.19.7", features=["with-serde_json-1"]}
bitflags = "1.3.2"
serde_json = "1.0.116"
byteorder = "1"
*/

use postgres::NoTls;

use bitflags::bitflags;
use std::cmp;
use std::default::Default;
use std::fs::File;
use std::io;
use std::io::Seek;
use std::io::SeekFrom;
use std::io::Write;
use std::path::Path;

use byteorder::LittleEndian;
use byteorder::WriteBytesExt;
use serde_json::Value;

use postgres::Client;
use postgres::{Row, Statement, Transaction};

use self::InsertResult::Full;
use self::InsertResult::Inserted;
use self::NodeData::Leaf;
use self::NodeData::SubNodes;

// as much as you can fit in a 512 byte block
static DEGREE: usize = 25;

#[derive()]
enum InsertResult<T> {
    Inserted(Node<T>),
    Full(Node<T>, Node<T>),
}

#[derive(Copy, Clone, Default)]
struct Point {
    x: isize,
    y: isize,
}

#[derive(Copy, Clone, Default)]
struct Rect {
    x0: isize,
    y0: isize,
    x1: isize,
    y1: isize,
}

#[derive()]
enum NodeData<T> {
    SubNodes(Vec<Node<T>>),
    Leaf(T),
}

#[derive()]
struct Node<T> {
    rect: Rect,
    sub: NodeData<T>,
}

bitflags! {
    struct WayFlags: u8 {
        const VANILLA  = 0x00;
        const FRIENDLY = 0x01;
        const HOSTILE  = 0x02;
        const ROUTE    = 0x04;
    }
}

struct Way {
    flags: WayFlags,
    name: String,
    nodes: Vec<Point>,
}

impl Rect {
    fn height(&self) -> isize {
        return self.y1 - self.y0;
    }

    fn width(&self) -> isize {
        return self.x1 - self.x0;
    }

    fn center(&self) -> Point {
        return Point {
            x: self.x0 + (self.width() / 2),
            y: self.y0 + (self.height() / 2),
        };
    }

    fn needed_growth(&self, rect: &Rect) -> isize {
        let newrect = self.grow(rect);
        let diff = (newrect.width() * newrect.height()) - (self.width() * self.height());
        return cmp::max(0, diff);
    }

    fn grow(&self, rect: &Rect) -> Rect {
        return Rect {
            x0: cmp::min(self.x0, rect.x0),
            y0: cmp::min(self.y0, rect.y0),
            x1: cmp::max(self.x1, rect.x1),
            y1: cmp::max(self.y1, rect.y1),
        };
    }
}

impl<T: TreeWriter> Node<T> {
    fn new(rect: Rect) -> Node<T> {
        return Node {
            rect: rect,
            sub: SubNodes(Vec::with_capacity(DEGREE)),
        };
    }

    fn is_leaf(&self) -> bool {
        return match self.sub {
            Leaf(_) => true,
            SubNodes(_) => false,
        };
    }

    fn subnodes(&self) -> &Vec<Node<T>> {
        return match self.sub {
            Leaf(_) => panic!("leaf has no nodes"),
            SubNodes(ref n) => n,
        };
    }

    fn mut_subnodes(&mut self) -> &mut Vec<Node<T>> {
        return match self.sub {
            Leaf(_) => panic!("leaf has no nodes"),
            SubNodes(ref mut n) => n,
        };
    }

    fn move_subnodes(self) -> Vec<Node<T>> {
        return match self.sub {
            Leaf(_) => panic!("leaf has no nodes"),
            SubNodes(n) => n,
        };
    }

    fn mut_leaf(&mut self) -> &mut T {
        return match self.sub {
            Leaf(ref mut l) => l,
            SubNodes(_) => panic!("Not a leaf"),
        };
    }

    fn split(self) -> [Node<T>; 2] {
        let rect = self.rect;
        let mut subnodes = self.move_subnodes();
        let len = subnodes.len();
        if rect.width() > rect.height() {
            subnodes.sort_by(|n, m| n.rect.center().x.cmp(&m.rect.center().x));
        } else {
            subnodes.sort_by(|n, m| n.rect.center().y.cmp(&m.rect.center().y));
        }
        let b = subnodes.split_off(len / 2);
        let a = subnodes;
        let mut n1: Node<T> = Node::new(Default::default());
        let mut n2: Node<T> = Node::new(Default::default());
        n1.sub = SubNodes(a);
        n1.update_rect();
        n2.sub = SubNodes(b);
        n2.update_rect();
        return [n1, n2];
    }

    fn update_rect(&mut self) {
        let init: Option<Rect> = None;
        self.rect = self
            .subnodes()
            .iter()
            .fold(init, |i, n| match i {
                None => Some(n.rect),
                Some(r) => Some(r.grow(&n.rect)),
            })
            .unwrap();
    }

    fn best_node(&mut self, rect: &Rect) -> Node<T> {
        let (index, _) = self
            .subnodes()
            .iter()
            .enumerate()
            .filter(|(_, n)| !n.is_leaf())
            .min_by_key(|(_, n)| n.rect.needed_growth(rect))
            .expect("no insertable subs");
        //println!("best is {} of {}", index, self.subnodes().len());
        return self.mut_subnodes().swap_remove(index);
    }

    fn insert_(mut self, new: Node<T>) -> InsertResult<T> {
        if self.subnodes().iter().any(|n| !n.is_leaf()) {
            // ***************************
            // There are subnodes, descend.
            //println!("subs");
            let node = self.best_node(&new.rect);
            match node.insert_(new) {
                Inserted(newchild) => {
                    // ***************************
                    // Node inserted. Back out.
                    //println!("inserted, now {} children", self.subnodes().len());
                    assert!(self.subnodes().len() < DEGREE);
                    self.mut_subnodes().push(newchild);
                    self.update_rect();
                    return Inserted(self);
                }
                Full(mut newchild, new) => {
                    // ***************************
                    // Child full. Split.
                    // This is the tricky part.
                    //println!("child full");
                    newchild.mut_subnodes().push(new);
                    let [n1, n2] = newchild.split();
                    //println!("n1 = {}, n2 = {}", n1.subnodes().len(), n2.subnodes().len());
                    assert!(self.subnodes().len() < DEGREE);
                    self.mut_subnodes().push(n1);
                    if self.subnodes().len() < DEGREE {
                        self.mut_subnodes().push(n2);
                        self.update_rect();
                        //println!("inserted after split, now {} children", self.subnodes().len());
                        return Inserted(self);
                    } else {
                        self.update_rect();
                        //println!("full after split, now {} children", self.subnodes().len());
                        return Full(self, n2);
                    }
                }
            }
        } else if self.subnodes().len() < DEGREE {
            // ***************************
            // Add the new node at this level
            //println!("inserting in node with {} children", self.subnodes().len());
            self.rect = self.rect.grow(&new.rect);
            self.mut_subnodes().push(new);
            return Inserted(self);
        } else {
            // ***************************
            // This node is full
            //println!("full");
            return Full(self, new);
        }
    }

    fn insert(self, new: Node<T>) -> Node<T> {
        match self.insert_(new) {
            Inserted(node) => return node,
            Full(mut node, new) => {
                println!("root full");
                let mut newroot: Node<T> = Node::new(node.rect);
                node.mut_subnodes().push(new);
                let [n1, n2] = node.split();
                newroot.mut_subnodes().push(n1);
                newroot.mut_subnodes().push(n2);
                newroot.update_rect();
                return newroot;
            }
        }
    }
}

trait TreeWriter {
    fn write<U>(&self, w: &mut U) -> io::Result<u64>
    where
        U: Write + Seek;
}

impl TreeWriter for Point {
    fn write<U>(&self, w: &mut U) -> io::Result<u64>
    where
        U: Write + Seek,
    {
        let offset = w.seek(std::io::SeekFrom::Current(0))?;
        w.write_i32::<LittleEndian>(self.x as i32)?;
        w.write_i32::<LittleEndian>(self.y as i32)?;
        return Ok(offset);
    }
}

impl TreeWriter for Rect {
    fn write<U>(&self, w: &mut U) -> io::Result<u64>
    where
        U: Write + Seek,
    {
        let offset = w.seek(std::io::SeekFrom::Current(0))?;
        w.write_i32::<LittleEndian>(self.x0 as i32)?;
        w.write_i32::<LittleEndian>(self.y0 as i32)?;
        w.write_i32::<LittleEndian>(self.x1 as i32)?;
        w.write_i32::<LittleEndian>(self.y1 as i32)?;
        return Ok(offset);
    }
}

fn seek_block<S: Seek>(w: &mut S, blocksize: u64) -> io::Result<u64> {
    // seek forward to the nearest 512 bytes
    let bsbits = blocksize - 1;
    let offset = w.seek(std::io::SeekFrom::Current(0))? + bsbits & !bsbits;
    assert!(offset % blocksize == 0);
    w.seek(SeekFrom::Start(offset))?;
    return Ok(offset);
}

impl TreeWriter for Node<Way> {
    fn write<U>(&self, w: &mut U) -> io::Result<u64>
    where
        U: Write + Seek,
    {
        match self.sub {
            Leaf(ref data) => {
                let offset = seek_block(w, 512)?;
                w.write_u8(0)?; // leaf node
                data.write(w)?;
                return Ok(offset);
            }
            SubNodes(ref subs) => {
                let offsets: Vec<u64> = subs.iter().filter_map(|sub| sub.write(w).ok()).collect();
                let offset = seek_block(w, 512)?;
                w.write_u8(offsets.len() as u8)?;
                for (o, sub) in offsets.into_iter().zip(subs.iter()) {
                    w.write_u32::<LittleEndian>(o as u32)?;
                    sub.rect.write(w)?;
                }
                return Ok(offset);
            }
        }
    }
}

impl TreeWriter for Way {
    fn write<U>(&self, w: &mut U) -> io::Result<u64>
    where
        U: Write + Seek,
    {
        let offset = w.seek(std::io::SeekFrom::Current(0))?;
        w.write_u16::<LittleEndian>(self.nodes.len() as u16)?;
        w.write_u8(self.name.len() as u8)?;
        w.write_u8(self.flags.bits())?;

        w.write_all(self.name.as_bytes())?;
        w.write_u8(0)?; // C null byte

        // allign points to 512 byte block
        seek_block(w, 8)?;
        for o in self.nodes.iter() {
            o.write(w)?;
        }
        return Ok(offset);
    }
}

fn query(conn: &mut Transaction) -> Statement {
    return conn
        .prepare(
            "SELECT w.id,
                                ST_X(n.geom), ST_Y(n.geom),
                                ST_XMIN(w.bbox), ST_YMIN(w.bbox),
                                ST_XMAX(w.bbox), ST_YMAX(w.bbox),
                                HSTORE_TO_JSON(w.tags)
                         FROM way_nodes as wn
                         INNER JOIN nodes as n ON n.id = wn.node_id
                         INNER JOIN ways as w ON w.id = wn.way_id
                         ORDER BY wn.way_id, wn.sequence_id",
        )
        .unwrap();
}

fn get_fixedpoint(row: &Row, idx: usize) -> isize {
    let fl: f64 = row.get(idx);
    return (fl * 10000000.0) as isize;
}

fn parse_hstore(row: &Row) -> (String, WayFlags) {
    let text = row.get(7);
    let data = match text {
        Some(Value::Object(m)) => m,
        _ => panic!("No JSON in hstore"),
    };

    let name = match data.get(&String::from("name")) {
        Some(&Value::String(ref s)) => s.clone(),
        _ => String::new(),
    };
    let highway = match data.get(&String::from("highway")) {
        Some(&Value::String(ref s)) if s.as_str() == "motorway" => WayFlags::HOSTILE,
        Some(&Value::String(ref s)) if s.as_str() == "trunk" => WayFlags::HOSTILE,
        Some(&Value::String(ref s)) if s.as_str() == "primary" => WayFlags::HOSTILE,
        Some(&Value::String(ref s)) if s.as_str() == "residential" => WayFlags::FRIENDLY,
        Some(&Value::String(ref s)) if s.as_str() == "unclassified" => WayFlags::FRIENDLY,
        Some(&Value::String(ref s)) if s.as_str() == "cycleway" => WayFlags::FRIENDLY,
        _ => WayFlags::VANILLA,
    };
    let bicycle = match data.get(&String::from("bicycle")) {
        Some(&Value::String(ref s)) if s.as_str() == "no" => WayFlags::HOSTILE,
        Some(&Value::String(ref s)) if s.as_str() == "yes" => WayFlags::FRIENDLY,
        Some(&Value::String(ref s)) if s.as_str() == "designated" => WayFlags::FRIENDLY,
        _ => WayFlags::VANILLA,
    };
    let cycleway = match data.get(&String::from("cycleway")) {
        Some(_) => WayFlags::FRIENDLY,
        _ => WayFlags::VANILLA,
    };
    let bicycle_road = match data.get(&String::from("bicycle_road")) {
        Some(_) => WayFlags::FRIENDLY,
        _ => WayFlags::VANILLA,
    };
    return (name, highway | cycleway | bicycle | bicycle_road);
}

fn main() {
    let mut conn = Client::connect("postgres://pepijndevos@localhost/osm", NoTls).unwrap();
    let mut trans = conn.transaction().unwrap();
    let mut root: Node<Way> = Node::new(Default::default());
    let mut current_id: Option<i64> = None;
    let mut current_node: Option<Node<Way>> = None;
    let query = query(&mut trans);
    let portal = trans.bind(&query, &[]).unwrap();
    for row in trans.query_portal(&portal, 2000).unwrap() {
        match current_id {
            i @ Some(_) if i == row.get(0) => {
                current_node = match current_node {
                    Some(mut node) => {
                        node.mut_leaf().nodes.push(Point {
                            x: get_fixedpoint(&row, 1),
                            y: get_fixedpoint(&row, 2),
                        });
                        Some(node)
                    }
                    None => None,
                }
            }
            _ => {
                match current_node {
                    Some(node) => {
                        root = root.insert(node);
                        //println!("#########################");
                    }
                    None => (),
                }
                let (name, flags) = parse_hstore(&row);
                current_id = Some(row.get(0));
                current_node = Some(Node {
                    rect: Rect {
                        x0: get_fixedpoint(&row, 3),
                        y0: get_fixedpoint(&row, 4),
                        x1: get_fixedpoint(&row, 5),
                        y1: get_fixedpoint(&row, 6),
                    },
                    sub: Leaf(Way {
                        flags: flags,
                        name: name,
                        nodes: vec![Point {
                            x: get_fixedpoint(&row, 1),
                            y: get_fixedpoint(&row, 2),
                        }],
                    }),
                });
            }
        }
    }
    let ref mut f = File::create(&Path::new("data.bin")).unwrap();
    f.seek(SeekFrom::Start(4)).unwrap();
    let start = root.write(f).unwrap();
    f.seek(SeekFrom::Start(0)).unwrap();
    f.write_u32::<LittleEndian>(start as u32).unwrap();
}

#[test]
fn needed_growth_test() {
    let r1 = Rect {
        x0: 0,
        y0: 0,
        x1: 100,
        y1: 100,
    };
    let r2 = Rect {
        x0: 0,
        y0: 0,
        x1: 100,
        y1: 101,
    };
    let r3 = Rect {
        x0: 0,
        y0: 0,
        x1: 101,
        y1: 101,
    };
    let r4 = Rect {
        x0: -1,
        y0: -1,
        x1: 101,
        y1: 101,
    };
    assert_eq!(r1.needed_growth(&r2), 100);
    assert_eq!(r1.needed_growth(&r3), 201);
    assert_eq!(r1.needed_growth(&r4), 404);
}

#[test]
fn grow_test() {
    let r1 = Rect {
        x0: 0,
        y0: 0,
        x1: 100,
        y1: 100,
    };
    let r2 = Rect {
        x0: 200,
        y0: 200,
        x1: 200,
        y1: 200,
    };
    let g = r1.grow(&r2);
    assert_eq!(g.x0, 0);
    assert_eq!(g.y0, 0);
    assert_eq!(g.x1, 200);
    assert_eq!(g.y1, 200);
}

#[test]
fn split_test() {
    let root: Node<Point> = Node::new(Rect {
        x0: 0,
        y0: 0,
        x1: 100,
        y1: 100,
    });
    let newroot = root
        .insert(Node {
            rect: Rect {
                x0: 0,
                y0: 0,
                x1: 50,
                y1: 50,
            },
            sub: Leaf(Point { x: 0, y: 0 }),
        })
        .insert(Node {
            rect: Rect {
                x0: 50,
                y0: 50,
                x1: 100,
                y1: 100,
            },
            sub: Leaf(Point { x: 0, y: 0 }),
        });
    let [n1, n2] = newroot.split();
    assert_eq!(n1.subnodes().len(), 1);
    assert_eq!(n2.subnodes().len(), 1);
}

Thank you so much for you help. I'll test this code.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.