polytrack_codes/v1/
mod.rs1#![allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
2#[cfg(test)]
3mod tests;
4
5use std::collections::HashMap;
6
7use facet::Facet;
8
9#[derive(Debug, Facet)]
10struct JsonTrack {
11 version: u32,
12 name: String,
13 track: String,
14}
15
16#[derive(Debug, PartialEq, Eq)]
17pub struct Track {
18 pub version: u32,
19 pub name: String,
20 pub track: TrackInfo,
21}
22
23#[derive(Debug, Facet, PartialEq, Eq)]
24pub struct JsonTrackInfo {
25 pub version: u32,
26 pub parts: HashMap<String, Vec<i32>>,
27}
28
29#[derive(Debug, PartialEq, Eq)]
30pub struct TrackInfo {
31 pub version: u32,
32 pub parts: Vec<Part>,
33}
34
35#[derive(Debug, PartialEq, Eq)]
36pub struct Part {
37 pub id: u32,
38 pub blocks: Vec<Block>,
39}
40
41#[derive(Debug, PartialEq, Eq)]
42pub struct Block {
43 pub x: i32,
44 pub y: i32,
45 pub z: i32,
46 pub rot: u8,
47}
48
49#[must_use]
50pub fn decode_track_code(track_code: &str) -> Option<Track> {
51 let json_track: JsonTrack = facet_json::from_str(track_code).ok()?;
52 let json_track_info: JsonTrackInfo = facet_json::from_str(&json_track.track).ok()?;
53 let mut track_info = TrackInfo {
54 version: json_track_info.version,
55 parts: json_track_info
56 .parts
57 .into_iter()
58 .map(|(id, blocks)| Part {
59 id: id.parse().unwrap_or(0),
60 blocks: blocks
61 .chunks_exact(4)
62 .map(|block| Block {
63 x: block[0],
64 y: block[1],
65 z: block[2],
66 rot: block[3] as u8,
67 })
68 .collect(),
69 })
70 .collect(),
71 };
72 track_info.parts.sort_by_key(|part| part.id);
73 Some(Track {
74 version: json_track.version,
75 name: json_track.name,
76 track: track_info,
77 })
78}