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
use std::convert::TryFrom; use nom::{le_u8, le_u32, le_u64}; use crate::core::parser::{ parse_world_id, parse_vec3f, parse_quat, parse_u8_string, }; use crate::core::types::{Placement3D}; use super::core::{ FileVersion, ZoneFile, SceneRef, SceneTransition, SceneTransitionInfo, SceneTransitionPoint }; named!(pub parse_file_version<FileVersion>, map!(le_u32, FileVersion::from) ); named_args!(pub parse_file_revision(version: FileVersion)<Option<u32>>, cond!(version.id() >= 0x24, call!(le_u32)) ); named_args!(pub parse_spawn_point(version: FileVersion)<Option<Placement3D>>, cond!(version.id() >= 0x26, do_parse!(a: parse_vec3f >> b: parse_quat >> (Placement3D{pos: a, rot: b})) ) ); named_args!(pub parse_scene_count(version: FileVersion)<usize>, switch!(value!(version.id() >= 0x25), true => map_res!(le_u32, usize::try_from) | false => map_res!(le_u8, usize::try_from) ) ); named!(parse_scene_ref<SceneRef>, do_parse!( file_name: parse_u8_string >> id: le_u32 >> layer: le_u32 >> name: parse_u8_string >> take!(3) >> (SceneRef{ file_name, id, layer, name }) ) ); named!(parse_scene_transition_point<SceneTransitionPoint>, do_parse!( a: le_u64 >> b: parse_vec3f >> (SceneTransitionPoint{scene_id: a, point: b}) ) ); named_args!(parse_scene_transition_info(version: FileVersion)<SceneTransitionInfo>, switch!(value!(version.id() <= 0x21 || version.id() >= 0x27), true => map!(count_fixed!(SceneTransitionPoint, parse_scene_transition_point, 2), SceneTransitionInfo::from) | false => map!(count_fixed!(SceneTransitionPoint, parse_scene_transition_point, 5), SceneTransitionInfo::from) ) ); named_args!(parse_scene_transitions(version: FileVersion)<Option<Vec<SceneTransition>>>, cond!(version.id() >= 0x20, length_count!(le_u32, do_parse!( a: cond!(version.id() < 0x25, parse_u8_string) >> b: call!(parse_scene_transition_info, version) >> (SceneTransition{ name: a, points: b, }) )) ) ); named!(pub parse_zone_file<ZoneFile>, do_parse!( file_version: parse_file_version >> b: call!(parse_file_revision, file_version) >> c: parse_world_id >> d: call!(parse_spawn_point, file_version) >> e: call!(parse_scene_count, file_version) >> f: count!(parse_scene_ref, e) >> g: parse_u8_string >> h: parse_u8_string >> i: parse_u8_string >> j: parse_u8_string >> k: call!(parse_scene_transitions, file_version) >> l: cond!(file_version.min(0x23), length_count!(le_u32, le_u8)) >> (ZoneFile{ file_version, file_revision: b, world_id: c, spawn_point: d, scene_refs: f, something: g, map_filename: h, map_name: i, map_description: j, scene_transitions: k, path_data: l, }) ) ); #[test] fn test_parse() { assert_eq!(parse_file_revision(&[20, 0, 0, 0], FileVersion::from(0x24)), Ok((&[][..], Some(20)))); assert_eq!(parse_file_revision(&[20, 0, 0, 0], FileVersion::from(0x23)), Ok((&[20,0,0,0][..], None))); assert_eq!(parse_scene_count(&[20], FileVersion::from(0x24)), Ok((&[][..], 20))); assert_eq!(parse_scene_count(&[20,0,0,0], FileVersion::from(0x25)), Ok((&[][..], 20))); assert_eq!(parse_u8_string(&[2,65,66]), Ok((&[][..], String::from("AB")))); }