1use super::domain::Network;
6use crate::Result;
7use crate::schema;
8use crate::xml::{write_document, write_document_at};
9use std::io::Write;
10use std::path::Path;
11
12pub fn write_network(path: &Path, network: &Network) -> Result<()> {
25 write_document_at::<schema::NetType, _>(network, "net", "SUMO network", path)
26}
27
28pub fn write_network_to(network: &Network, sink: impl Write) -> Result<()> {
35 write_document::<schema::NetType, _, _>(network, "net", "SUMO network", sink)
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41 use crate::domain::{
42 Boundary, Edge, EdgeFunction, EdgeId, Junction, JunctionId, JunctionKind, Lane, LaneId,
43 LaneIndex, Location, Phase, Point, Projection, Shape, TrafficLightId, TrafficLightKind,
44 TrafficLightOffset, TrafficLightProgram,
45 };
46 use crate::net::reader::read_network_from;
47 use uom::si::f64::{Length, Time, Velocity};
48 use uom::si::length::meter;
49 use uom::si::time::second;
50 use uom::si::velocity::meter_per_second;
51
52 fn sample_network() -> Network {
64 Network {
65 location: Location {
66 net_offset: Point {
67 x: 0.0,
68 y: 0.0,
69 z: 0.0,
70 },
71 converted_boundary: Boundary {
72 min: Point { x: 0.0, y: 0.0, z: 0.0 },
73 max: Point { x: 100.0, y: 0.0, z: 0.0 },
74 },
75 original_boundary: Boundary {
76 min: Point { x: -1.0, y: -1.0, z: 0.0 },
77 max: Point { x: 1.0, y: 1.0, z: 0.0 },
78 },
79 projection: Projection::None,
80 },
81 edges: vec![Edge {
82 id: EdgeId("e0".into()),
83 function: EdgeFunction::Normal,
84 from: Some(JunctionId("j0".into())),
85 to: Some(JunctionId("j1".into())),
86 name: None,
87 priority: None,
88 length: None,
89 shape: None,
90 spread_type: None,
91 lanes: vec![Lane {
92 id: LaneId("e0_0".into()),
93 index: LaneIndex(0),
94 speed: Velocity::new::<meter_per_second>(13.75),
95 length: Length::new::<meter>(100.0),
96 width: Length::new::<meter>(3.25),
97 end_offset: Length::new::<meter>(0.0),
98 shape: Shape(vec![
99 Point {
100 x: 0.0,
101 y: 0.0,
102 z: 0.0,
103 },
104 Point {
105 x: 100.0,
106 y: 0.0,
107 z: 0.0,
108 },
109 ]),
110 allow: vec![],
111 disallow: vec![],
112 }],
113 }],
114 junctions: vec![
115 Junction {
116 id: JunctionId("j0".into()),
117 position: Point {
118 x: 0.0,
119 y: 0.0,
120 z: 0.0,
121 },
122 kind: JunctionKind::DeadEnd,
123 incoming_lanes: vec![],
124 internal_lanes: vec![],
125 shape: None,
126 name: None,
127 },
128 Junction {
129 id: JunctionId("j1".into()),
130 position: Point {
131 x: 100.0,
132 y: 0.0,
133 z: 0.0,
134 },
135 kind: JunctionKind::TrafficLight,
136 incoming_lanes: vec![LaneId("e0_0".into())],
137 internal_lanes: vec![],
138 shape: None,
139 name: None,
140 },
141 ],
142 connections: vec![],
143 roundabouts: vec![],
144 traffic_light_programs: vec![TrafficLightProgram {
145 id: TrafficLightId("j1".into()),
146 program_id: "0".into(),
147 kind: Some(TrafficLightKind::Static),
148 offset: Some(TrafficLightOffset::Fixed(Time::new::<second>(0.0))),
149 phases: vec![
150 Phase {
151 duration: Time::new::<second>(42.0),
152 state: "G".into(),
153 },
154 Phase {
155 duration: Time::new::<second>(3.0),
156 state: "r".into(),
157 },
158 ],
159 }],
160 }
161 }
162
163 #[test]
164 fn writes_a_document_a_correctly_rooted_reader_accepts() {
165 let mut buf = Vec::new();
166 write_network_to(&sample_network(), &mut buf).unwrap();
167
168 let xml = String::from_utf8(buf).unwrap();
169 assert!(xml.starts_with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
170 assert!(xml.contains("<net"));
171
172 let read_back = read_network_from(xml.as_bytes()).unwrap();
173 assert_eq!(read_back, sample_network());
174 }
175}