osm-io 0.3.0

Read and write OSM data
Documentation
use crate::osm::model::element::Element;

enum State {
    Nodes,
    Ways,
    Relations,
}

pub(crate) struct ElementAccumulator {
    block_size: usize,
    elements: Vec<Element>,
    state: State,
    index: usize,
}

impl ElementAccumulator {
    pub(crate) fn new() -> ElementAccumulator {
        let block_size = 8000usize;
        ElementAccumulator {
            block_size,
            elements: Vec::with_capacity(block_size),
            state: State::Nodes,
            index: 0,
        }
    }

    pub(crate) fn add(&mut self, element: Element) -> Option<Vec<Element>> {
        let mut result = None;
        match self.state {
            State::Nodes => {
                match &element {
                    Element::Node { .. } => {
                        self.elements.push(element);
                        if self.elements.len() == self.block_size {
                            result = Some(std::mem::replace(&mut self.elements, Vec::with_capacity(self.block_size)));
                            self.index += 1;
                        }
                    }
                    Element::Way { .. } => {
                        self.state = State::Ways;
                        result = Some(std::mem::replace(&mut self.elements, Vec::with_capacity(self.block_size)));
                        self.index += 1;
                        self.add(element);
                    }
                    Element::Relation { .. } => {
                        panic!("expected Element::Node or Element::Way but got Element::Relation");
                    }
                    Element::Sentinel => {}
                }
            }
            State::Ways => {
                match &element {
                    Element::Node { .. } => {
                        panic!("expected Element::Way or Element::Relation but got Element::Node");
                    }
                    Element::Way { .. } => {
                        self.elements.push(element);
                        if self.elements.len() == self.block_size {
                            result = Some(std::mem::replace(&mut self.elements, Vec::with_capacity(self.block_size)));
                            self.index += 1;
                        }
                    }
                    Element::Relation { .. } => {
                        self.state = State::Relations;
                        result = Some(std::mem::replace(&mut self.elements, Vec::with_capacity(self.block_size)));
                        self.index += 1;
                        self.add(element);
                    }
                    Element::Sentinel => {}
                }
            }
            State::Relations => {
                match &element {
                    Element::Node { .. } => {
                        panic!("expected Element::Relation but got Element::Node");
                    }
                    Element::Way { .. } => {
                        panic!("expected Element::Relation but got Element::Way");
                    }
                    Element::Relation { .. } => {
                        self.elements.push(element);
                        if self.elements.len() == self.block_size {
                            result = Some(std::mem::replace(&mut self.elements, Vec::with_capacity(self.block_size)));
                            self.index += 1;
                        }
                    }
                    Element::Sentinel => {}
                }
            }
        }
        result
    }

    pub(crate) fn elements(&mut self) -> Vec<Element> {
        self.index += 1;
        std::mem::take(&mut self.elements)
    }

    pub(crate) fn index(&self) -> usize {
        self.index
    }

    #[allow(dead_code)]
    pub(crate) fn len(&self) -> usize {
        self.elements.len()
    }
}