1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use protobuf::{self, Message};

use {Screen, Node, Meta, random_fg_color};
use pb;

pub fn serialize_screen(screen: &Screen) -> Vec<u8> {
    let mut screen_pb = pb::Screen::default();
    screen_pb.set_max_id(screen.max_id);
    let nodes = screen.nodes
        .iter()
        .map(|(_, node)| serialize_node(node))
        .collect();
    screen_pb.set_nodes(protobuf::RepeatedField::from_vec(nodes));
    let arrows = screen.arrows
        .iter()
        .map(|&(from, to)| {
            let mut arrow_pb = pb::Arrow::default();
            arrow_pb.set_from_node(from);
            arrow_pb.set_to_node(to);
            arrow_pb
        })
        .collect();
    screen_pb.set_arrows(protobuf::RepeatedField::from_vec(arrows));
    screen_pb.write_to_bytes().unwrap()
}

fn serialize_meta(meta: &Meta) -> pb::Meta {
    let mut gps_pb = pb::Gps::default();
    gps_pb.set_lat(meta.gps.0);
    gps_pb.set_lon(meta.gps.1);
    let mut meta_pb = pb::Meta::default();
    meta_pb.set_gps(gps_pb);
    meta_pb.set_ctime(meta.ctime);
    meta_pb.set_mtime(meta.mtime);
    if let Some(finish_time) = meta.finish_time {
        meta_pb.set_finish_time(finish_time);
    }
    let mut tags = vec![];
    for (tagk, tagv) in &meta.tags {
        let mut tag = pb::Tag::default();
        tag.set_key(tagk.clone());
        tag.set_value(tagv.clone());
        tags.push(tag);
    }
    meta_pb.set_tags(protobuf::RepeatedField::from_vec(tags));
    meta_pb
}

fn serialize_node(node: &Node) -> pb::Node {
    let mut node_pb = pb::Node::default();
    node_pb.set_id(node.id);
    node_pb.set_text(node.content.clone());
    node_pb.set_children(node.children.clone());
    node_pb.set_collapsed(node.collapsed);
    node_pb.set_stricken(node.stricken);
    node_pb.set_hide_stricken(node.hide_stricken);
    node_pb.set_parent_id(node.parent_id);
    node_pb.set_x(node.rooted_coords.0 as u32);
    node_pb.set_y(node.rooted_coords.1 as u32);
    node_pb.set_meta(serialize_meta(&node.meta));
    if let Some(ref free_text) = node.free_text {
        node_pb.set_free_text(free_text.to_owned());
    }
    node_pb
}

fn deserialize_meta(meta_pb: &pb::Meta) -> Meta {
    let gps = meta_pb.get_gps();
    Meta {
        ctime: meta_pb.get_ctime(),
        mtime: meta_pb.get_mtime(),
        finish_time: if meta_pb.has_finish_time() {
            Some(meta_pb.get_finish_time())
        } else {
            None
        },
        gps: (gps.get_lat(), gps.get_lon()),
        tags: meta_pb.get_tags()
            .iter()
            .map(|tag| (tag.get_key().to_owned(), tag.get_value().to_owned()))
            .collect(),
    }
}

fn deserialize_node(node_pb: &pb::Node) -> Node {
    Node {
        parent_id: node_pb.get_parent_id(),
        rooted_coords: (node_pb.get_x() as u16, node_pb.get_y() as u16),
        content: node_pb.get_text().to_owned(),
        children: node_pb.get_children().to_vec(),
        selected: node_pb.get_selected(),
        collapsed: node_pb.get_collapsed(),
        stricken: node_pb.get_stricken(),
        hide_stricken: node_pb.get_hide_stricken(),
        meta: deserialize_meta(node_pb.get_meta()),
        id: node_pb.get_id(),
        free_text: if node_pb.has_free_text() {
            Some(node_pb.get_free_text().to_owned())
        } else {
            None
        },
        color: random_fg_color(),
        auto_arrange: false,
    }
}

pub fn deserialize_screen(data: Vec<u8>) -> Result<Screen, protobuf::ProtobufError> {
    let screen_pb: pb::Screen = protobuf::parse_from_bytes(&*data)?;
    let mut screen = Screen::default();
    screen.max_id = screen_pb.get_max_id();
    screen.nodes = screen_pb.get_nodes()
        .iter()
        .map(|node_pb| {
            let node = deserialize_node(node_pb);
            (node.id, node)
        })
        .collect();

    screen.arrows = screen_pb.get_arrows()
        .iter()
        .map(|arrow_pb| {
            let from = arrow_pb.get_from_node();
            let to = arrow_pb.get_to_node();
            (from, to)
        })
        .collect();
    Ok(screen)
}