controlmap_parser/
lib.rs

1#![allow(clippy::tabs_in_doc_comments)] // <- controlmap.txt ignores clippy's caution because tab is part of the language use.
2//! # ControlMap Parser Library
3//!
4//! The controlmap.txt parser for Skyrim.
5//!
6//! ## features
7//!
8//! - [x] controlmap.txt => json structure
9//! - [x] json structure => controlmap.txt
10//! - [x] Analysis using enum scanCodes.
11//!
12//! # Examples
13//!
14//! ```rust
15//! use controlmap_parser::ControlMap;
16//!
17//! type Result<T, E = Box<dyn std::error::Error + 'static>> = core::result::Result<T, E>;
18//! fn main() -> Result<()> {
19//!     let input = r#"
20//! // Lockpicking
21//! RotatePick	0xff		0xa		0x000b	0	0	0	0x8
22//! RotateLock	0x1e,0xff	0xff	0x000c	0	0	0	0x8
23//! DebugMode	0x35		0xff	0x4000	0	0	0	0x8
24//! Cancel		0x0f		0xff	0x1000	0	0	0	0x8
25//!
26//! // Favor
27//! Cancel	0x0f	0xff	0x1000	0	0	0	0x108"#;
28//!
29//!     let control_map = ControlMap::from_txt(input)?;
30//!     println!("txt => Struct:\n{:?}", &control_map);
31//!
32//!     let json = serde_json::to_string_pretty(&control_map)?;
33//!     let expected_json = r#"{
34//!   "lines": [
35//!     "BlankLine",
36//!     {
37//!       "Comment": " Lockpicking"
38//!     },
39//!     {
40//!       "EventLine": {
41//!         "event_name": "RotatePick",
42//!         "keyboard_id": {
43//!           "One": "0xff"
44//!         },
45//!         "mouse_id": {
46//!           "One": "0xa"
47//!         },
48//!         "gamepad_id": {
49//!           "One": "0x000b"
50//!         },
51//!         "remap_key": false,
52//!         "remap_mouse": false,
53//!         "remap_gamepad": false,
54//!         "event_binary_flag": "0x8"
55//!       }
56//!     },
57//!     {
58//!       "EventLine": {
59//!         "event_name": "RotateLock",
60//!         "keyboard_id": {
61//!           "Or": [
62//!             {
63//!               "One": "0x1e"
64//!             },
65//!             {
66//!               "One": "0xff"
67//!             }
68//!           ]
69//!         },
70//!         "mouse_id": {
71//!           "One": "0xff"
72//!         },
73//!         "gamepad_id": {
74//!           "One": "0x000c"
75//!         },
76//!         "remap_key": false,
77//!         "remap_mouse": false,
78//!         "remap_gamepad": false,
79//!         "event_binary_flag": "0x8"
80//!       }
81//!     },
82//!     {
83//!       "EventLine": {
84//!         "event_name": "DebugMode",
85//!         "keyboard_id": {
86//!           "One": "0x35"
87//!         },
88//!         "mouse_id": {
89//!           "One": "0xff"
90//!         },
91//!         "gamepad_id": {
92//!           "One": "0x4000"
93//!         },
94//!         "remap_key": false,
95//!         "remap_mouse": false,
96//!         "remap_gamepad": false,
97//!         "event_binary_flag": "0x8"
98//!       }
99//!     },
100//!     {
101//!       "EventLine": {
102//!         "event_name": "Cancel",
103//!         "keyboard_id": {
104//!           "One": "0x0f"
105//!         },
106//!         "mouse_id": {
107//!           "One": "0xff"
108//!         },
109//!         "gamepad_id": {
110//!           "One": "0x1000"
111//!         },
112//!         "remap_key": false,
113//!         "remap_mouse": false,
114//!         "remap_gamepad": false,
115//!         "event_binary_flag": "0x8"
116//!       }
117//!     },
118//!     "BlankLine",
119//!     {
120//!       "Comment": " Favor"
121//!     },
122//!     {
123//!       "EventLine": {
124//!         "event_name": "Cancel",
125//!         "keyboard_id": {
126//!           "One": "0x0f"
127//!         },
128//!         "mouse_id": {
129//!           "One": "0xff"
130//!         },
131//!         "gamepad_id": {
132//!           "One": "0x1000"
133//!         },
134//!         "remap_key": false,
135//!         "remap_mouse": false,
136//!         "remap_gamepad": false,
137//!         "event_binary_flag": "0x108"
138//!       }
139//!     }
140//!   ]
141//! }"#;
142//!     assert_eq!(&json, expected_json);
143//!
144//!     let control_map: ControlMap = serde_json::from_str(&json)?;
145//!     // Yes, blank lines are not removed, they are applied as is.
146//!     // There are places where it would be an error to do otherwise.
147//!     let formatted_control_map = r#"
148//! // Lockpicking
149//! RotatePick	0xff	0xa	0x000b	0	0	0	0x8
150//! RotateLock	0x1e+0xff	0xff	0x000c	0	0	0	0x8
151//! DebugMode	0x35	0xff	0x4000	0	0	0	0x8
152//! Cancel	0x0f	0xff	0x1000	0	0	0	0x8
153//!
154//! // Favor
155//! Cancel	0x0f	0xff	0x1000	0	0	0	0x108
156//! "#;
157//!     assert_eq!(control_map.to_string(), formatted_control_map);
158//!
159//!     Ok(())
160//! }
161//! ```
162
163mod controlmap;
164pub mod parser;
165pub mod scan_code;
166
167pub use controlmap::{ControlMap, ControlMapError};