digitalis-core 0.1.0

Core module for Digitalis
Documentation
use std::collections::{HashSet, VecDeque};

use base64::{engine::general_purpose::STANDARD, Engine as _};
use protobuf::{descriptor::FileDescriptorSet, Message, MessageFull};

fn get_fd_set<T: MessageFull>() -> FileDescriptorSet {
    let mut fd_set = FileDescriptorSet::new();
    let mut to_add = VecDeque::new();
    let mut added = HashSet::<String>::new();
    to_add.push_back(T::descriptor().file_descriptor().clone());

    while let Some(next) = to_add.pop_front() {
        for dep in next.deps() {
            if !added.contains(dep.name()) {
                added.insert(dep.name().into());
                to_add.push_back(dep.clone());
            }
        }
        fd_set.file.push(next.proto().clone());
    }

    fd_set
}

pub fn base64_proto<T: MessageFull>() -> String {
    let buf = get_fd_set::<T>().write_to_bytes().unwrap();

    STANDARD.encode(buf)
}

#[cfg(test)]
mod test {
    use digitalis_protobuf::{Color, Pose};

    use super::*;

    #[test]
    fn test_fd_set() {
        let fd_set = get_fd_set::<Color>();

        assert_eq!(fd_set.file.len(), 1);
        assert_eq!(
            fd_set.file[0].name.as_ref().unwrap(),
            "foxglove/Color.proto"
        );

        let fd_set = get_fd_set::<Pose>();

        assert_eq!(fd_set.file.len(), 3);

        for msg in &["Vector3", "Quaternion", "Pose"] {
            assert!(fd_set
                .file
                .iter()
                .any(|f| f.name == Some(format!("foxglove/{}.proto", msg))));
        }
    }
}