rustyproxy 1.1.9

GUI for the rustyproxy project
Documentation
use egui::{CollapsingResponse, Response, Ui};

pub enum DisplayResponse {
    CollapsingResponse(CollapsingResponse<()>),
    GenericResponse(Response),
}
#[derive(Debug)]
pub struct PathPart {
    uri: String,
    is_dir: bool,
    childs: Vec<PathPart>,
    is_root: bool,
}

impl PathPart {
    pub fn is_directory(&self) -> bool {
        self.is_dir
    }

    // pub fn childs(&self) -> Vec<&PathPart> {
    //     let mut out = vec![];
    //     for child in &self.childs {
    //         out.push(child);
    //     }
    //     out
    // }

    pub fn new_root(uri: impl ToString) -> Self {
        let mut out = Self::new(uri, false);
        out.is_root = true;
        out
    }

    pub fn new(uri: impl ToString, is_endpoint: bool) -> Self {
        Self {
            uri: uri.to_string(),
            is_dir: !is_endpoint,
            childs: vec![],
            is_root: false,
        }
    }

    pub fn add_child(&mut self, child: PathPart) {
        self.childs.push(child);
    }

    pub fn merge(&mut self, tree: PathPart) {
        if let Some(c) = self.childs.iter_mut().find(|x| x.uri == tree.uri) {
            /* already seen, go deeper */
            for nchild in tree.childs {
                c.merge(nchild);
            }
        } else {
            /* never seen uri, push */
            self.childs.push(tree)
        }
    }

    // pub fn len(&self) -> usize {
    //     if self.is_dir {
    //         let mut len = 0;
    //         for child in &self.childs {
    //             len += child.len()
    //         }
    //         len
    //     } else {
    //         1
    //     }

    // }

    fn ui(&self, ui: &mut Ui) -> DisplayResponse {
        let heading = if self.uri.is_empty() { "/" } else { &self.uri };
        if self.is_directory() {
            DisplayResponse::CollapsingResponse(ui.collapsing(heading.to_string(), |ui| {
                for child in &self.childs {
                    child.ui(ui);
                }
            }))
        } else {
            DisplayResponse::GenericResponse(ui.label(heading))
        }
    }
}

#[derive(Debug)]
pub struct Paths {
    inner: PathPart,
}

impl Paths {
    pub fn new() -> Self {
        Self {
            inner: PathPart::new_root("History"),
        }
    }

    pub fn merge(&mut self, ntree: PathPart) {
        if ntree.uri.is_empty() {
            /* need to go 1 time deeper because parent's uri is "" */
            for child in ntree.childs {
                self.merge(child);
            }
        } else {
            self.inner.merge(ntree);
        }
    }

    pub fn sort(&mut self) {
        self.inner.childs.sort_by_key(|x| x.uri.to_string());
    }

    pub fn _childs(&self) -> &Vec<PathPart> {
        &self.inner.childs
    }

    pub fn ui(&self, ui: &mut Ui) -> DisplayResponse {
        self.inner.ui(ui)
    }
}

pub fn new_tree_from_uri(uri: &str) -> PathPart {
    let mut nodes = vec![];
    let parts = uri.split('/').collect::<Vec<&str>>();
    for (idx, part) in parts.iter().enumerate() {
        let node = PathPart::new(part, idx == (parts.len() - 1));
        nodes.push(node);
    }
    let mut parent;
    let mut child;
    while nodes.len() > 1 {
        child = nodes.pop().unwrap();
        parent = nodes.pop().unwrap();
        parent.add_child(child);
        nodes.push(parent)
    }
    parent = nodes.pop().unwrap();
    parent
}