Skip to main content

mmd_anim_format/
nmd.rs

1use serde::{Deserialize, Serialize};
2
3use crate::binary::ByteReader;
4use crate::error::ImportError;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(rename_all = "camelCase")]
8pub struct NmdParsedManifest {
9    #[serde(default = "default_nmd_format", skip_deserializing)]
10    pub format: &'static str,
11    pub byte_length: usize,
12    pub metadata: NmdParsedMetadata,
13    pub global_track_count: usize,
14    pub keyframe_bundles: NmdKeyframeBundleCounts,
15    pub payload: NmdPayloadSummary,
16    pub diagnostics: Vec<NmdDiagnostic>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(rename_all = "camelCase")]
21pub struct NmdParsedMetadata {
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub main_object_name: Option<String>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub preferred_fps: Option<f32>,
26    pub annotation_count: usize,
27}
28
29#[derive(Debug, Clone, Default, Serialize, Deserialize)]
30#[serde(rename_all = "camelCase")]
31pub struct NmdKeyframeBundleCounts {
32    pub accessory: usize,
33    pub bone: usize,
34    pub camera: usize,
35    pub light: usize,
36    pub model: usize,
37    pub morph: usize,
38    pub self_shadow: usize,
39    pub unknown: usize,
40}
41
42#[derive(Debug, Clone, Default, Serialize, Deserialize)]
43#[serde(rename_all = "camelCase")]
44pub struct NmdPayloadSummary {
45    pub accessory_keyframes: usize,
46    pub bone_local_tracks: usize,
47    pub bone_keyframes: usize,
48    pub morph_local_tracks: usize,
49    pub morph_keyframes: usize,
50    pub camera_keyframes: usize,
51    pub light_keyframes: usize,
52    pub model_keyframes: usize,
53    pub self_shadow_keyframes: usize,
54    pub accessory_frames: Vec<NmdAccessoryKeyframe>,
55    pub bone_frames: Vec<NmdBoneKeyframe>,
56    pub morph_frames: Vec<NmdMorphKeyframe>,
57    pub camera_frames: Vec<NmdCameraKeyframe>,
58    pub light_frames: Vec<NmdLightKeyframe>,
59    pub model_frames: Vec<NmdModelKeyframe>,
60    pub self_shadow_frames: Vec<NmdSelfShadowKeyframe>,
61}
62
63#[derive(Debug, Clone, Default, Serialize, Deserialize)]
64#[serde(rename_all = "camelCase")]
65pub struct NmdAccessoryKeyframe {
66    pub common: NmdKeyframeCommon,
67    pub track_index: u64,
68    pub translation: [f32; 3],
69    pub orientation: [f32; 4],
70    pub scale_factor: f32,
71    pub opacity: f32,
72    pub effect_parameters: Vec<NmdEffectParameter>,
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub binding: Option<NmdModelBinding>,
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub visible: Option<bool>,
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub shadow_enabled: Option<bool>,
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub add_blending_enabled: Option<bool>,
81}
82
83#[derive(Debug, Clone, Default, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub struct NmdKeyframeCommon {
86    pub frame_index: u64,
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub layer_index: Option<u32>,
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub selected: Option<bool>,
91}
92
93#[derive(Debug, Clone, Default, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase")]
95pub struct NmdBoneKeyframe {
96    pub common: NmdKeyframeCommon,
97    pub track_index: u64,
98    pub local_translation: [f32; 3],
99    pub local_orientation: [f32; 4],
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub interpolation: Option<NmdBoneKeyframeInterpolation>,
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub stage_index: Option<u32>,
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub physics_simulation_enabled: Option<bool>,
106}
107
108#[derive(Debug, Clone, Default, Serialize, Deserialize)]
109#[serde(rename_all = "camelCase")]
110pub struct NmdBoneKeyframeInterpolation {
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub x: Option<NmdInterpolationUnit>,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub y: Option<NmdInterpolationUnit>,
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub z: Option<NmdInterpolationUnit>,
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub orientation: Option<NmdInterpolationUnit>,
119}
120
121#[derive(Debug, Clone, Default, Serialize, Deserialize)]
122#[serde(rename_all = "camelCase")]
123pub struct NmdMorphKeyframe {
124    pub common: NmdKeyframeCommon,
125    pub track_index: u64,
126    pub weight: f32,
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub interpolation: Option<NmdInterpolationUnit>,
129}
130
131#[derive(Debug, Clone, Default, Serialize, Deserialize)]
132#[serde(rename_all = "camelCase")]
133pub struct NmdCameraKeyframe {
134    pub common: NmdKeyframeCommon,
135    pub look_at: [f32; 3],
136    pub angle: [f32; 3],
137    pub fov: f32,
138    pub distance: f32,
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub interpolation: Option<NmdCameraKeyframeInterpolation>,
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub stage_index: Option<u32>,
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub perspective_view_enabled: Option<bool>,
145}
146
147#[derive(Debug, Clone, Default, Serialize, Deserialize)]
148#[serde(rename_all = "camelCase")]
149pub struct NmdCameraKeyframeInterpolation {
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub x: Option<NmdInterpolationUnit>,
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub y: Option<NmdInterpolationUnit>,
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub z: Option<NmdInterpolationUnit>,
156    #[serde(skip_serializing_if = "Option::is_none")]
157    pub angle: Option<NmdInterpolationUnit>,
158    #[serde(skip_serializing_if = "Option::is_none")]
159    pub fov: Option<NmdInterpolationUnit>,
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub distance: Option<NmdInterpolationUnit>,
162}
163
164#[derive(Debug, Clone, Default, Serialize, Deserialize)]
165#[serde(rename_all = "camelCase")]
166pub struct NmdLightKeyframe {
167    pub common: NmdKeyframeCommon,
168    pub color: [f32; 3],
169    pub direction: [f32; 3],
170}
171
172#[derive(Debug, Clone, Default, Serialize, Deserialize)]
173#[serde(rename_all = "camelCase")]
174pub struct NmdModelKeyframe {
175    pub common: NmdKeyframeCommon,
176    pub visible: bool,
177    pub constraint_state_count: usize,
178    pub effect_parameter_count: usize,
179    pub binding_count: usize,
180    pub constraint_states: Vec<NmdConstraintState>,
181    pub effect_parameters: Vec<NmdEffectParameter>,
182    pub bindings: Vec<NmdModelBinding>,
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub edge: Option<NmdEdge>,
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub add_blending_enabled: Option<bool>,
187    #[serde(skip_serializing_if = "Option::is_none")]
188    pub physics_simulation_enabled: Option<bool>,
189}
190
191#[derive(Debug, Clone, Default, Serialize, Deserialize)]
192#[serde(rename_all = "camelCase")]
193pub struct NmdConstraintState {
194    pub track_index: u64,
195    pub enabled: bool,
196}
197
198#[derive(Debug, Clone, Default, Serialize, Deserialize)]
199#[serde(rename_all = "camelCase")]
200pub struct NmdEffectParameter {
201    pub track_index: u64,
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub bool_value: Option<bool>,
204    #[serde(skip_serializing_if = "Option::is_none")]
205    pub int_value: Option<i32>,
206    #[serde(skip_serializing_if = "Option::is_none")]
207    pub float_value: Option<f32>,
208    #[serde(skip_serializing_if = "Option::is_none")]
209    pub vector_value: Option<[f32; 4]>,
210}
211
212#[derive(Debug, Clone, Default, Serialize, Deserialize)]
213#[serde(rename_all = "camelCase")]
214pub struct NmdModelBinding {
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub local_bone_track_index: Option<u64>,
217    pub global_object_track_index: u64,
218    pub global_bone_track_index: u64,
219}
220
221#[derive(Debug, Clone, Default, Serialize, Deserialize)]
222#[serde(rename_all = "camelCase")]
223pub struct NmdEdge {
224    pub color: [f32; 4],
225    pub scale_factor: f32,
226}
227
228#[derive(Debug, Clone, Default, Serialize, Deserialize)]
229#[serde(rename_all = "camelCase")]
230pub struct NmdSelfShadowKeyframe {
231    pub common: NmdKeyframeCommon,
232    pub enabled: bool,
233    pub mode: i32,
234    pub distance: f32,
235}
236
237#[derive(Debug, Clone, Default, Serialize, Deserialize)]
238#[serde(rename_all = "camelCase")]
239pub struct NmdInterpolationUnit {
240    #[serde(skip_serializing_if = "Option::is_none")]
241    pub integer: Option<[u32; 4]>,
242    #[serde(skip_serializing_if = "Option::is_none")]
243    pub float: Option<[f32; 4]>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
247#[serde(rename_all = "camelCase")]
248pub struct NmdDiagnostic {
249    pub level: String,
250    pub code: String,
251    pub message: String,
252}
253
254pub fn parse_nmd_manifest(data: &[u8]) -> Result<NmdParsedManifest, ImportError> {
255    if data.is_empty() {
256        return Err(ImportError::UnexpectedEof(1));
257    }
258
259    let mut r = ProtoReader { data, pos: 0 };
260    let mut metadata = NmdParsedMetadata {
261        main_object_name: None,
262        preferred_fps: None,
263        annotation_count: 0,
264    };
265    let mut global_track_count = 0usize;
266    let mut keyframe_bundles = NmdKeyframeBundleCounts::default();
267    let mut payload = NmdPayloadSummary::default();
268
269    while !r.is_eof() {
270        let Some((field, wire_type)) = r.read_key()? else {
271            break;
272        };
273        match (field, wire_type) {
274            (1, WIRE_LEN) => {
275                r.skip_len()?;
276                metadata.annotation_count += 1;
277            }
278            (2, WIRE_LEN) => {
279                let bytes = r.read_len()?;
280                metadata.main_object_name = Some(String::from_utf8_lossy(bytes).into_owned());
281            }
282            (3, WIRE_FIXED32) => {
283                let preferred_fps = r.read_f32()?;
284                if !preferred_fps.is_finite() {
285                    return Err(ImportError::UnsupportedFormat {
286                        format: "NMD",
287                        detail: "preferred FPS is not finite",
288                    });
289                }
290                metadata.preferred_fps = Some(preferred_fps);
291            }
292            (4, WIRE_LEN) => {
293                r.skip_len()?;
294                global_track_count += 1;
295            }
296            (5, WIRE_LEN) => {
297                let bytes = r.read_len()?;
298                count_keyframe_bundle(bytes, &mut keyframe_bundles, &mut payload)?;
299            }
300            _ => r.skip_value(wire_type)?,
301        }
302    }
303
304    Ok(NmdParsedManifest {
305        format: "nmd",
306        byte_length: data.len(),
307        metadata,
308        global_track_count,
309        keyframe_bundles,
310        payload,
311        diagnostics: vec![NmdDiagnostic {
312            level: "warning".to_owned(),
313            code: "NMD_MOTION_DTO".to_owned(),
314            message: "NMD protobuf was parsed as a motion DTO; exporter roundtrip is not implemented yet.".to_owned(),
315        }],
316    })
317}
318
319fn count_keyframe_bundle(
320    data: &[u8],
321    counts: &mut NmdKeyframeBundleCounts,
322    payload: &mut NmdPayloadSummary,
323) -> Result<(), ImportError> {
324    let mut r = ProtoReader { data, pos: 0 };
325    let mut oneof_payload = None;
326    let mut saw_len_field = false;
327    while !r.is_eof() {
328        let Some((field, wire_type)) = r.read_key()? else {
329            break;
330        };
331        if wire_type == WIRE_LEN {
332            saw_len_field = true;
333            if matches!(field, 1 | 2 | 3 | 5 | 6 | 7 | 9) {
334                oneof_payload = Some((field, r.peek_len()?));
335            }
336        }
337        r.skip_value(wire_type)?;
338    }
339
340    match oneof_payload {
341        Some((1, bytes)) => {
342            counts.accessory += 1;
343            let frames = read_len_messages(bytes, 2)?
344                .into_iter()
345                .map(parse_accessory_keyframe)
346                .collect::<Result<Vec<_>, _>>()?;
347            payload.accessory_keyframes += frames.len();
348            payload.accessory_frames.extend(frames);
349        }
350        Some((2, bytes)) => {
351            counts.bone += 1;
352            count_bone_bundle_payload(bytes, payload)?;
353        }
354        Some((3, bytes)) => {
355            counts.camera += 1;
356            let frames = read_len_messages(bytes, 2)?
357                .into_iter()
358                .map(parse_camera_keyframe)
359                .collect::<Result<Vec<_>, _>>()?;
360            payload.camera_keyframes += frames.len();
361            payload.camera_frames.extend(frames);
362        }
363        Some((5, bytes)) => {
364            counts.light += 1;
365            let frames = read_len_messages(bytes, 2)?
366                .into_iter()
367                .map(parse_light_keyframe)
368                .collect::<Result<Vec<_>, _>>()?;
369            payload.light_keyframes += frames.len();
370            payload.light_frames.extend(frames);
371        }
372        Some((6, bytes)) => {
373            counts.model += 1;
374            let frames = read_len_messages(bytes, 2)?
375                .into_iter()
376                .map(parse_model_keyframe)
377                .collect::<Result<Vec<_>, _>>()?;
378            payload.model_keyframes += frames.len();
379            payload.model_frames.extend(frames);
380        }
381        Some((7, bytes)) => {
382            counts.morph += 1;
383            count_morph_bundle_payload(bytes, payload)?;
384        }
385        Some((9, bytes)) => {
386            counts.self_shadow += 1;
387            let frames = read_len_messages(bytes, 2)?
388                .into_iter()
389                .map(parse_self_shadow_keyframe)
390                .collect::<Result<Vec<_>, _>>()?;
391            payload.self_shadow_keyframes += frames.len();
392            payload.self_shadow_frames.extend(frames);
393        }
394        Some((_, _)) => counts.unknown += 1,
395        None if saw_len_field => counts.unknown += 1,
396        None => counts.unknown += 1,
397    }
398    Ok(())
399}
400
401fn count_bone_bundle_payload(
402    data: &[u8],
403    payload: &mut NmdPayloadSummary,
404) -> Result<(), ImportError> {
405    payload.bone_local_tracks += count_len_field(data, 2)?;
406    let frames = read_len_messages(data, 3)?
407        .into_iter()
408        .map(parse_bone_keyframe)
409        .collect::<Result<Vec<_>, _>>()?;
410    payload.bone_keyframes += frames.len();
411    payload.bone_frames.extend(frames);
412    Ok(())
413}
414
415fn count_morph_bundle_payload(
416    data: &[u8],
417    payload: &mut NmdPayloadSummary,
418) -> Result<(), ImportError> {
419    payload.morph_local_tracks += count_len_field(data, 2)?;
420    let frames = read_len_messages(data, 3)?
421        .into_iter()
422        .map(parse_morph_keyframe)
423        .collect::<Result<Vec<_>, _>>()?;
424    payload.morph_keyframes += frames.len();
425    payload.morph_frames.extend(frames);
426    Ok(())
427}
428
429fn count_len_field(data: &[u8], target_field: u32) -> Result<usize, ImportError> {
430    let mut r = ProtoReader { data, pos: 0 };
431    let mut count = 0usize;
432    while !r.is_eof() {
433        let Some((field, wire_type)) = r.read_key()? else {
434            break;
435        };
436        if field == target_field && wire_type == WIRE_LEN {
437            count += 1;
438        }
439        r.skip_value(wire_type)?;
440    }
441    Ok(count)
442}
443
444fn read_len_messages(data: &[u8], target_field: u32) -> Result<Vec<&[u8]>, ImportError> {
445    let mut r = ProtoReader { data, pos: 0 };
446    let mut messages = Vec::new();
447    while !r.is_eof() {
448        let Some((field, wire_type)) = r.read_key()? else {
449            break;
450        };
451        if field == target_field && wire_type == WIRE_LEN {
452            messages.push(r.peek_len()?);
453        }
454        r.skip_value(wire_type)?;
455    }
456    Ok(messages)
457}
458
459fn parse_common(data: &[u8]) -> Result<NmdKeyframeCommon, ImportError> {
460    let mut r = ProtoReader { data, pos: 0 };
461    let mut common = NmdKeyframeCommon::default();
462    while !r.is_eof() {
463        let Some((field, wire_type)) = r.read_key()? else {
464            break;
465        };
466        match (field, wire_type) {
467            (2, WIRE_VARINT) => common.frame_index = r.read_varint()?,
468            (3, WIRE_VARINT) => common.layer_index = Some(read_u32_varint(&mut r)?),
469            (4, WIRE_VARINT) => common.selected = Some(r.read_bool()?),
470            _ => r.skip_value(wire_type)?,
471        }
472    }
473    Ok(common)
474}
475
476fn parse_accessory_keyframe(data: &[u8]) -> Result<NmdAccessoryKeyframe, ImportError> {
477    let mut r = ProtoReader { data, pos: 0 };
478    let mut frame = NmdAccessoryKeyframe::default();
479    while !r.is_eof() {
480        let Some((field, wire_type)) = r.read_key()? else {
481            break;
482        };
483        match (field, wire_type) {
484            (1, WIRE_LEN) => frame.common = parse_common(r.read_len()?)?,
485            (2, WIRE_VARINT) => frame.track_index = r.read_varint()?,
486            (3, WIRE_LEN) => frame.translation = parse_vec3(r.read_len()?)?,
487            (4, WIRE_LEN) => frame.orientation = parse_vec4(r.read_len()?)?,
488            (5, WIRE_FIXED32) => frame.scale_factor = r.read_f32()?,
489            (6, WIRE_FIXED32) => frame.opacity = r.read_f32()?,
490            (7, WIRE_LEN) => frame
491                .effect_parameters
492                .push(parse_effect_parameter(r.read_len()?)?),
493            (8, WIRE_LEN) => frame.binding = Some(parse_model_binding(r.read_len()?)?),
494            (9, WIRE_VARINT) => frame.visible = Some(r.read_bool()?),
495            (10, WIRE_VARINT) => frame.shadow_enabled = Some(r.read_bool()?),
496            (11, WIRE_VARINT) => frame.add_blending_enabled = Some(r.read_bool()?),
497            _ => r.skip_value(wire_type)?,
498        }
499    }
500    Ok(frame)
501}
502
503fn parse_bone_keyframe(data: &[u8]) -> Result<NmdBoneKeyframe, ImportError> {
504    let mut r = ProtoReader { data, pos: 0 };
505    let mut frame = NmdBoneKeyframe::default();
506    while !r.is_eof() {
507        let Some((field, wire_type)) = r.read_key()? else {
508            break;
509        };
510        match (field, wire_type) {
511            (1, WIRE_LEN) => frame.common = parse_common(r.read_len()?)?,
512            (2, WIRE_VARINT) => frame.track_index = r.read_varint()?,
513            (3, WIRE_LEN) => frame.local_translation = parse_vec3(r.read_len()?)?,
514            (4, WIRE_LEN) => frame.local_orientation = parse_vec4(r.read_len()?)?,
515            (5, WIRE_LEN) => frame.interpolation = Some(parse_bone_interpolation(r.read_len()?)?),
516            (6, WIRE_VARINT) => frame.stage_index = Some(read_u32_varint(&mut r)?),
517            (7, WIRE_VARINT) => frame.physics_simulation_enabled = Some(r.read_bool()?),
518            _ => r.skip_value(wire_type)?,
519        }
520    }
521    Ok(frame)
522}
523
524fn parse_morph_keyframe(data: &[u8]) -> Result<NmdMorphKeyframe, ImportError> {
525    let mut r = ProtoReader { data, pos: 0 };
526    let mut frame = NmdMorphKeyframe::default();
527    while !r.is_eof() {
528        let Some((field, wire_type)) = r.read_key()? else {
529            break;
530        };
531        match (field, wire_type) {
532            (1, WIRE_LEN) => frame.common = parse_common(r.read_len()?)?,
533            (2, WIRE_VARINT) => frame.track_index = r.read_varint()?,
534            (3, WIRE_FIXED32) => frame.weight = r.read_f32()?,
535            (4, WIRE_LEN) => frame.interpolation = Some(parse_morph_interpolation(r.read_len()?)?),
536            _ => r.skip_value(wire_type)?,
537        }
538    }
539    Ok(frame)
540}
541
542fn parse_camera_keyframe(data: &[u8]) -> Result<NmdCameraKeyframe, ImportError> {
543    let mut r = ProtoReader { data, pos: 0 };
544    let mut frame = NmdCameraKeyframe::default();
545    while !r.is_eof() {
546        let Some((field, wire_type)) = r.read_key()? else {
547            break;
548        };
549        match (field, wire_type) {
550            (1, WIRE_LEN) => frame.common = parse_common(r.read_len()?)?,
551            (2, WIRE_LEN) => frame.look_at = parse_vec3(r.read_len()?)?,
552            (3, WIRE_LEN) => frame.angle = parse_vec3(r.read_len()?)?,
553            (4, WIRE_FIXED32) => frame.fov = r.read_f32()?,
554            (5, WIRE_FIXED32) => frame.distance = r.read_f32()?,
555            (6, WIRE_LEN) => frame.interpolation = Some(parse_camera_interpolation(r.read_len()?)?),
556            (7, WIRE_VARINT) => frame.stage_index = Some(read_u32_varint(&mut r)?),
557            (8, WIRE_VARINT) => frame.perspective_view_enabled = Some(r.read_bool()?),
558            _ => r.skip_value(wire_type)?,
559        }
560    }
561    Ok(frame)
562}
563
564fn parse_light_keyframe(data: &[u8]) -> Result<NmdLightKeyframe, ImportError> {
565    let mut r = ProtoReader { data, pos: 0 };
566    let mut frame = NmdLightKeyframe::default();
567    while !r.is_eof() {
568        let Some((field, wire_type)) = r.read_key()? else {
569            break;
570        };
571        match (field, wire_type) {
572            (1, WIRE_LEN) => frame.common = parse_common(r.read_len()?)?,
573            (2, WIRE_LEN) => frame.color = parse_vec3(r.read_len()?)?,
574            (3, WIRE_LEN) => frame.direction = parse_vec3(r.read_len()?)?,
575            _ => r.skip_value(wire_type)?,
576        }
577    }
578    Ok(frame)
579}
580
581fn parse_model_keyframe(data: &[u8]) -> Result<NmdModelKeyframe, ImportError> {
582    let mut r = ProtoReader { data, pos: 0 };
583    let mut frame = NmdModelKeyframe::default();
584    while !r.is_eof() {
585        let Some((field, wire_type)) = r.read_key()? else {
586            break;
587        };
588        match (field, wire_type) {
589            (1, WIRE_LEN) => frame.common = parse_common(r.read_len()?)?,
590            (2, WIRE_VARINT) => frame.visible = r.read_bool()?,
591            (3, WIRE_LEN) => {
592                frame.constraint_state_count += 1;
593                frame
594                    .constraint_states
595                    .push(parse_constraint_state(r.read_len()?)?);
596            }
597            (4, WIRE_LEN) => {
598                frame.effect_parameter_count += 1;
599                frame
600                    .effect_parameters
601                    .push(parse_effect_parameter(r.read_len()?)?);
602            }
603            (5, WIRE_LEN) => {
604                frame.binding_count += 1;
605                frame.bindings.push(parse_model_binding(r.read_len()?)?);
606            }
607            (6, WIRE_LEN) => frame.edge = Some(parse_edge(r.read_len()?)?),
608            (7, WIRE_VARINT) => frame.add_blending_enabled = Some(r.read_bool()?),
609            (8, WIRE_VARINT) => frame.physics_simulation_enabled = Some(r.read_bool()?),
610            _ => r.skip_value(wire_type)?,
611        }
612    }
613    Ok(frame)
614}
615
616fn parse_self_shadow_keyframe(data: &[u8]) -> Result<NmdSelfShadowKeyframe, ImportError> {
617    let mut r = ProtoReader { data, pos: 0 };
618    let mut frame = NmdSelfShadowKeyframe::default();
619    while !r.is_eof() {
620        let Some((field, wire_type)) = r.read_key()? else {
621            break;
622        };
623        match (field, wire_type) {
624            (1, WIRE_LEN) => frame.common = parse_common(r.read_len()?)?,
625            (2, WIRE_VARINT) => frame.enabled = r.read_bool()?,
626            (3, WIRE_VARINT) => frame.mode = read_i32_varint(&mut r)?,
627            (4, WIRE_FIXED32) => frame.distance = r.read_f32()?,
628            _ => r.skip_value(wire_type)?,
629        }
630    }
631    Ok(frame)
632}
633
634fn parse_bone_interpolation(data: &[u8]) -> Result<NmdBoneKeyframeInterpolation, ImportError> {
635    let mut r = ProtoReader { data, pos: 0 };
636    let mut interpolation = NmdBoneKeyframeInterpolation::default();
637    while !r.is_eof() {
638        let Some((field, wire_type)) = r.read_key()? else {
639            break;
640        };
641        match (field, wire_type) {
642            (1, WIRE_LEN) => interpolation.x = Some(parse_interpolation_unit(r.read_len()?)?),
643            (2, WIRE_LEN) => interpolation.y = Some(parse_interpolation_unit(r.read_len()?)?),
644            (3, WIRE_LEN) => interpolation.z = Some(parse_interpolation_unit(r.read_len()?)?),
645            (4, WIRE_LEN) => {
646                interpolation.orientation = Some(parse_interpolation_unit(r.read_len()?)?)
647            }
648            _ => r.skip_value(wire_type)?,
649        }
650    }
651    Ok(interpolation)
652}
653
654fn parse_morph_interpolation(data: &[u8]) -> Result<NmdInterpolationUnit, ImportError> {
655    let mut r = ProtoReader { data, pos: 0 };
656    let mut interpolation = None;
657    while !r.is_eof() {
658        let Some((field, wire_type)) = r.read_key()? else {
659            break;
660        };
661        match (field, wire_type) {
662            (1, WIRE_LEN) => interpolation = Some(parse_interpolation_unit(r.read_len()?)?),
663            _ => r.skip_value(wire_type)?,
664        }
665    }
666    Ok(interpolation.unwrap_or_default())
667}
668
669fn parse_camera_interpolation(data: &[u8]) -> Result<NmdCameraKeyframeInterpolation, ImportError> {
670    let mut r = ProtoReader { data, pos: 0 };
671    let mut interpolation = NmdCameraKeyframeInterpolation::default();
672    while !r.is_eof() {
673        let Some((field, wire_type)) = r.read_key()? else {
674            break;
675        };
676        match (field, wire_type) {
677            (1, WIRE_LEN) => interpolation.x = Some(parse_interpolation_unit(r.read_len()?)?),
678            (2, WIRE_LEN) => interpolation.y = Some(parse_interpolation_unit(r.read_len()?)?),
679            (3, WIRE_LEN) => interpolation.z = Some(parse_interpolation_unit(r.read_len()?)?),
680            (4, WIRE_LEN) => interpolation.angle = Some(parse_interpolation_unit(r.read_len()?)?),
681            (5, WIRE_LEN) => interpolation.fov = Some(parse_interpolation_unit(r.read_len()?)?),
682            (6, WIRE_LEN) => {
683                interpolation.distance = Some(parse_interpolation_unit(r.read_len()?)?)
684            }
685            _ => r.skip_value(wire_type)?,
686        }
687    }
688    Ok(interpolation)
689}
690
691fn parse_interpolation_unit(data: &[u8]) -> Result<NmdInterpolationUnit, ImportError> {
692    let mut r = ProtoReader { data, pos: 0 };
693    let mut unit = NmdInterpolationUnit::default();
694    while !r.is_eof() {
695        let Some((field, wire_type)) = r.read_key()? else {
696            break;
697        };
698        match (field, wire_type) {
699            (1, WIRE_LEN) => unit.integer = Some(parse_integer_interpolation(r.read_len()?)?),
700            (2, WIRE_LEN) => unit.float = Some(parse_float_interpolation(r.read_len()?)?),
701            _ => r.skip_value(wire_type)?,
702        }
703    }
704    Ok(unit)
705}
706
707fn parse_integer_interpolation(data: &[u8]) -> Result<[u32; 4], ImportError> {
708    let mut r = ProtoReader { data, pos: 0 };
709    let mut values = [0; 4];
710    while !r.is_eof() {
711        let Some((field, wire_type)) = r.read_key()? else {
712            break;
713        };
714        match (field, wire_type) {
715            (1, WIRE_VARINT) => values[0] = read_u32_varint(&mut r)?,
716            (2, WIRE_VARINT) => values[1] = read_u32_varint(&mut r)?,
717            (3, WIRE_VARINT) => values[2] = read_u32_varint(&mut r)?,
718            (4, WIRE_VARINT) => values[3] = read_u32_varint(&mut r)?,
719            _ => r.skip_value(wire_type)?,
720        }
721    }
722    Ok(values)
723}
724
725fn parse_float_interpolation(data: &[u8]) -> Result<[f32; 4], ImportError> {
726    let mut r = ProtoReader { data, pos: 0 };
727    let mut values = [0.0; 4];
728    while !r.is_eof() {
729        let Some((field, wire_type)) = r.read_key()? else {
730            break;
731        };
732        match (field, wire_type) {
733            (1, WIRE_FIXED32) => values[0] = r.read_f32()?,
734            (2, WIRE_FIXED32) => values[1] = r.read_f32()?,
735            (3, WIRE_FIXED32) => values[2] = r.read_f32()?,
736            (4, WIRE_FIXED32) => values[3] = r.read_f32()?,
737            _ => r.skip_value(wire_type)?,
738        }
739    }
740    Ok(values)
741}
742
743fn parse_constraint_state(data: &[u8]) -> Result<NmdConstraintState, ImportError> {
744    let mut r = ProtoReader { data, pos: 0 };
745    let mut state = NmdConstraintState::default();
746    while !r.is_eof() {
747        let Some((field, wire_type)) = r.read_key()? else {
748            break;
749        };
750        match (field, wire_type) {
751            (1, WIRE_VARINT) => state.track_index = r.read_varint()?,
752            (2, WIRE_VARINT) => state.enabled = r.read_bool()?,
753            _ => r.skip_value(wire_type)?,
754        }
755    }
756    Ok(state)
757}
758
759fn parse_effect_parameter(data: &[u8]) -> Result<NmdEffectParameter, ImportError> {
760    let mut r = ProtoReader { data, pos: 0 };
761    let mut parameter = NmdEffectParameter::default();
762    while !r.is_eof() {
763        let Some((field, wire_type)) = r.read_key()? else {
764            break;
765        };
766        match (field, wire_type) {
767            (1, WIRE_VARINT) => parameter.track_index = r.read_varint()?,
768            (2, WIRE_VARINT) => parameter.bool_value = Some(r.read_bool()?),
769            (3, WIRE_VARINT) => parameter.int_value = Some(read_i32_varint(&mut r)?),
770            (4, WIRE_FIXED32) => parameter.float_value = Some(r.read_f32()?),
771            (5, WIRE_LEN) => parameter.vector_value = Some(parse_vec4(r.read_len()?)?),
772            _ => r.skip_value(wire_type)?,
773        }
774    }
775    Ok(parameter)
776}
777
778fn parse_model_binding(data: &[u8]) -> Result<NmdModelBinding, ImportError> {
779    let mut r = ProtoReader { data, pos: 0 };
780    let mut binding = NmdModelBinding::default();
781    while !r.is_eof() {
782        let Some((field, wire_type)) = r.read_key()? else {
783            break;
784        };
785        match (field, wire_type) {
786            (1, WIRE_VARINT) => binding.local_bone_track_index = Some(r.read_varint()?),
787            (2, WIRE_VARINT) => binding.global_object_track_index = r.read_varint()?,
788            (3, WIRE_VARINT) => binding.global_bone_track_index = r.read_varint()?,
789            _ => r.skip_value(wire_type)?,
790        }
791    }
792    Ok(binding)
793}
794
795fn parse_edge(data: &[u8]) -> Result<NmdEdge, ImportError> {
796    let mut r = ProtoReader { data, pos: 0 };
797    let mut edge = NmdEdge::default();
798    while !r.is_eof() {
799        let Some((field, wire_type)) = r.read_key()? else {
800            break;
801        };
802        match (field, wire_type) {
803            (1, WIRE_LEN) => edge.color = parse_vec4(r.read_len()?)?,
804            (2, WIRE_FIXED32) => edge.scale_factor = r.read_f32()?,
805            _ => r.skip_value(wire_type)?,
806        }
807    }
808    Ok(edge)
809}
810
811fn parse_vec3(data: &[u8]) -> Result<[f32; 3], ImportError> {
812    let mut r = ProtoReader { data, pos: 0 };
813    let mut values = [0.0; 3];
814    while !r.is_eof() {
815        let Some((field, wire_type)) = r.read_key()? else {
816            break;
817        };
818        match (field, wire_type) {
819            (1, WIRE_FIXED32) => values[0] = r.read_f32()?,
820            (2, WIRE_FIXED32) => values[1] = r.read_f32()?,
821            (3, WIRE_FIXED32) => values[2] = r.read_f32()?,
822            _ => r.skip_value(wire_type)?,
823        }
824    }
825    Ok(values)
826}
827
828fn parse_vec4(data: &[u8]) -> Result<[f32; 4], ImportError> {
829    let mut r = ProtoReader { data, pos: 0 };
830    let mut values = [0.0; 4];
831    while !r.is_eof() {
832        let Some((field, wire_type)) = r.read_key()? else {
833            break;
834        };
835        match (field, wire_type) {
836            (1, WIRE_FIXED32) => values[0] = r.read_f32()?,
837            (2, WIRE_FIXED32) => values[1] = r.read_f32()?,
838            (3, WIRE_FIXED32) => values[2] = r.read_f32()?,
839            (4, WIRE_FIXED32) => values[3] = r.read_f32()?,
840            _ => r.skip_value(wire_type)?,
841        }
842    }
843    Ok(values)
844}
845
846fn read_u32_varint(r: &mut ProtoReader<'_>) -> Result<u32, ImportError> {
847    let value = r.read_varint()?;
848    if value > u64::from(u32::MAX) {
849        return Err(ImportError::UnsupportedFormat {
850            format: "NMD",
851            detail: "uint32 value overflows u32",
852        });
853    }
854    Ok(value as u32)
855}
856
857fn read_i32_varint(r: &mut ProtoReader<'_>) -> Result<i32, ImportError> {
858    let value = r.read_varint()?;
859    if value > u64::from(u32::MAX) {
860        return Err(ImportError::UnsupportedFormat {
861            format: "NMD",
862            detail: "int32 varint value overflows u32",
863        });
864    }
865    Ok(value as u32 as i32)
866}
867
868const WIRE_VARINT: u8 = 0;
869const WIRE_FIXED64: u8 = 1;
870const WIRE_LEN: u8 = 2;
871const WIRE_FIXED32: u8 = 5;
872
873type ProtoReader<'a> = ByteReader<'a>;
874
875impl<'a> ByteReader<'a> {
876    fn is_eof(&self) -> bool {
877        self.remaining() == 0
878    }
879
880    fn read_key(&mut self) -> Result<Option<(u32, u8)>, ImportError> {
881        if self.is_eof() {
882            return Ok(None);
883        }
884        let key = self.read_varint()?;
885        let field = key >> 3;
886        if field == 0 {
887            return Err(ImportError::UnsupportedFormat {
888                format: "NMD",
889                detail: "protobuf field number must be non-zero",
890            });
891        }
892        if field > 0x1fff_ffff {
893            return Err(ImportError::UnsupportedFormat {
894                format: "NMD",
895                detail: "protobuf field number exceeds the supported range",
896            });
897        }
898        Ok(Some((field as u32, (key & 0x7) as u8)))
899    }
900
901    fn read_varint(&mut self) -> Result<u64, ImportError> {
902        let mut value = 0u64;
903        for shift in (0..64).step_by(7) {
904            let byte = self.read_u8()?;
905            if shift == 63 && byte > 1 {
906                return Err(ImportError::UnsupportedFormat {
907                    format: "NMD",
908                    detail: "varint overflows u64",
909                });
910            }
911            value |= u64::from(byte & 0x7f) << shift;
912            if byte & 0x80 == 0 {
913                return Ok(value);
914            }
915        }
916        Err(ImportError::UnsupportedFormat {
917            format: "NMD",
918            detail: "varint is too long",
919        })
920    }
921
922    fn read_len(&mut self) -> Result<&'a [u8], ImportError> {
923        let raw_len = self.read_varint()?;
924        if raw_len > usize::MAX as u64 {
925            return Err(ImportError::UnsupportedFormat {
926                format: "NMD",
927                detail: "length does not fit in usize",
928            });
929        }
930        let len = raw_len as usize;
931        self.read_bytes(len)
932    }
933
934    fn peek_len(&self) -> Result<&'a [u8], ImportError> {
935        let mut copy = ProtoReader {
936            data: self.data,
937            pos: self.pos,
938        };
939        copy.read_len()
940    }
941
942    fn skip_len(&mut self) -> Result<(), ImportError> {
943        self.read_len().map(|_| ())
944    }
945
946    fn read_f32(&mut self) -> Result<f32, ImportError> {
947        let value = self.read_f32_le()?;
948        if !value.is_finite() {
949            return Err(ImportError::UnsupportedFormat {
950                format: "NMD",
951                detail: "float value is not finite",
952            });
953        }
954        Ok(value)
955    }
956
957    fn read_bool(&mut self) -> Result<bool, ImportError> {
958        Ok(self.read_varint()? != 0)
959    }
960
961    fn skip_value(&mut self, wire_type: u8) -> Result<(), ImportError> {
962        match wire_type {
963            WIRE_VARINT => {
964                self.read_varint()?;
965                Ok(())
966            }
967            WIRE_FIXED64 => {
968                self.skip_bytes(8)?;
969                Ok(())
970            }
971            WIRE_LEN => self.skip_len(),
972            WIRE_FIXED32 => {
973                self.skip_bytes(4)?;
974                Ok(())
975            }
976            _ => Err(ImportError::UnsupportedFormat {
977                format: "NMD",
978                detail: "unsupported protobuf wire type",
979            }),
980        }
981    }
982
983    fn skip_bytes(&mut self, len: usize) -> Result<(), ImportError> {
984        self.skip(len)
985    }
986}
987
988fn default_nmd_format() -> &'static str {
989    "nmd"
990}
991
992#[cfg(test)]
993mod tests {
994    use super::*;
995
996    fn key(field: u32, wire_type: u8) -> u8 {
997        ((field << 3) | u32::from(wire_type)) as u8
998    }
999
1000    fn push_len(out: &mut Vec<u8>, field: u32, bytes: &[u8]) {
1001        out.push(key(field, WIRE_LEN));
1002        push_varint(out, bytes.len() as u64);
1003        out.extend_from_slice(bytes);
1004    }
1005
1006    fn push_varint(out: &mut Vec<u8>, mut value: u64) {
1007        while value >= 0x80 {
1008            out.push((value as u8 & 0x7f) | 0x80);
1009            value >>= 7;
1010        }
1011        out.push(value as u8);
1012    }
1013
1014    fn push_varint_field(out: &mut Vec<u8>, field: u32, value: u64) {
1015        out.push(key(field, WIRE_VARINT));
1016        push_varint(out, value);
1017    }
1018
1019    fn push_f32_field(out: &mut Vec<u8>, field: u32, value: f32) {
1020        out.push(key(field, WIRE_FIXED32));
1021        out.extend_from_slice(&value.to_le_bytes());
1022    }
1023
1024    fn common(frame_index: u64) -> Vec<u8> {
1025        let mut out = Vec::new();
1026        push_varint_field(&mut out, 2, frame_index);
1027        out
1028    }
1029
1030    fn vec3(x: f32, y: f32, z: f32) -> Vec<u8> {
1031        let mut out = Vec::new();
1032        push_f32_field(&mut out, 1, x);
1033        push_f32_field(&mut out, 2, y);
1034        push_f32_field(&mut out, 3, z);
1035        out
1036    }
1037
1038    fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec<u8> {
1039        let mut out = vec3(x, y, z);
1040        push_f32_field(&mut out, 4, w);
1041        out
1042    }
1043
1044    fn integer_interp(x0: u32, y0: u32, x1: u32, y1: u32) -> Vec<u8> {
1045        let mut out = Vec::new();
1046        push_varint_field(&mut out, 1, u64::from(x0));
1047        push_varint_field(&mut out, 2, u64::from(y0));
1048        push_varint_field(&mut out, 3, u64::from(x1));
1049        push_varint_field(&mut out, 4, u64::from(y1));
1050        out
1051    }
1052
1053    fn float_interp(x0: f32, y0: f32, x1: f32, y1: f32) -> Vec<u8> {
1054        let mut out = Vec::new();
1055        push_f32_field(&mut out, 1, x0);
1056        push_f32_field(&mut out, 2, y0);
1057        push_f32_field(&mut out, 3, x1);
1058        push_f32_field(&mut out, 4, y1);
1059        out
1060    }
1061
1062    fn interp_unit_integer(values: [u32; 4]) -> Vec<u8> {
1063        let mut out = Vec::new();
1064        push_len(
1065            &mut out,
1066            1,
1067            &integer_interp(values[0], values[1], values[2], values[3]),
1068        );
1069        out
1070    }
1071
1072    fn interp_unit_float(values: [f32; 4]) -> Vec<u8> {
1073        let mut out = Vec::new();
1074        push_len(
1075            &mut out,
1076            2,
1077            &float_interp(values[0], values[1], values[2], values[3]),
1078        );
1079        out
1080    }
1081
1082    fn push_bundle(out: &mut Vec<u8>, field: u32) {
1083        let bundle = vec![key(field, WIRE_LEN), 0];
1084        push_len(out, 5, &bundle);
1085    }
1086
1087    fn push_bone_bundle(out: &mut Vec<u8>, local_track_count: usize, keyframe_count: usize) {
1088        let mut bone = Vec::new();
1089        for _ in 0..local_track_count {
1090            push_len(&mut bone, 2, &[]);
1091        }
1092        for _ in 0..keyframe_count {
1093            push_len(&mut bone, 3, &[]);
1094        }
1095        let mut unit = Vec::new();
1096        push_len(&mut unit, 2, &bone);
1097        push_len(out, 5, &unit);
1098    }
1099
1100    fn push_morph_bundle(out: &mut Vec<u8>, local_track_count: usize, keyframe_count: usize) {
1101        let mut morph = Vec::new();
1102        for _ in 0..local_track_count {
1103            push_len(&mut morph, 2, &[]);
1104        }
1105        for _ in 0..keyframe_count {
1106            push_len(&mut morph, 3, &[]);
1107        }
1108        let mut unit = Vec::new();
1109        push_len(&mut unit, 7, &morph);
1110        push_len(out, 5, &unit);
1111    }
1112
1113    fn push_len_keyframe_payload(out: &mut Vec<u8>, field: u32, keyframe_count: usize) {
1114        let mut payload = Vec::new();
1115        for _ in 0..keyframe_count {
1116            push_len(&mut payload, 2, &[]);
1117        }
1118        let mut unit = Vec::new();
1119        push_len(&mut unit, field, &payload);
1120        push_len(out, 5, &unit);
1121    }
1122
1123    #[test]
1124    fn parses_nmd_top_level_motion_manifest() {
1125        let mut data = Vec::new();
1126        push_len(&mut data, 2, b"main-model");
1127        data.push(key(3, WIRE_FIXED32));
1128        data.extend_from_slice(&60.0f32.to_le_bytes());
1129        push_len(&mut data, 4, &[key(1, WIRE_VARINT), 1]);
1130        push_bone_bundle(&mut data, 2, 3);
1131        push_bundle(&mut data, 3);
1132        push_morph_bundle(&mut data, 1, 2);
1133        push_len_keyframe_payload(&mut data, 5, 4);
1134        push_len_keyframe_payload(&mut data, 6, 5);
1135        push_len_keyframe_payload(&mut data, 9, 6);
1136
1137        let parsed = parse_nmd_manifest(&data).unwrap();
1138
1139        assert_eq!(parsed.format, "nmd");
1140        assert_eq!(parsed.byte_length, data.len());
1141        assert_eq!(
1142            parsed.metadata.main_object_name.as_deref(),
1143            Some("main-model")
1144        );
1145        assert_eq!(parsed.metadata.preferred_fps, Some(60.0));
1146        assert_eq!(parsed.global_track_count, 1);
1147        assert_eq!(parsed.keyframe_bundles.bone, 1);
1148        assert_eq!(parsed.keyframe_bundles.camera, 1);
1149        assert_eq!(parsed.keyframe_bundles.light, 1);
1150        assert_eq!(parsed.keyframe_bundles.model, 1);
1151        assert_eq!(parsed.keyframe_bundles.morph, 1);
1152        assert_eq!(parsed.keyframe_bundles.self_shadow, 1);
1153        assert_eq!(parsed.payload.bone_local_tracks, 2);
1154        assert_eq!(parsed.payload.bone_keyframes, 3);
1155        assert_eq!(parsed.payload.light_keyframes, 4);
1156        assert_eq!(parsed.payload.model_keyframes, 5);
1157        assert_eq!(parsed.payload.morph_local_tracks, 1);
1158        assert_eq!(parsed.payload.morph_keyframes, 2);
1159        assert_eq!(parsed.payload.self_shadow_keyframes, 6);
1160        assert_eq!(parsed.diagnostics[0].code, "NMD_MOTION_DTO");
1161    }
1162
1163    #[test]
1164    fn parses_nmd_keyframe_value_payloads() {
1165        let mut data = Vec::new();
1166
1167        let mut accessory_frame = Vec::new();
1168        push_len(&mut accessory_frame, 1, &common(9));
1169        push_varint_field(&mut accessory_frame, 2, 2);
1170        push_len(&mut accessory_frame, 3, &vec3(7.0, 8.0, 9.0));
1171        push_len(&mut accessory_frame, 4, &vec4(0.0, 0.0, 0.0, 1.0));
1172        push_f32_field(&mut accessory_frame, 5, 1.25);
1173        push_f32_field(&mut accessory_frame, 6, 0.75);
1174        let mut accessory_effect = Vec::new();
1175        push_varint_field(&mut accessory_effect, 1, 8);
1176        push_f32_field(&mut accessory_effect, 4, 0.5);
1177        push_len(&mut accessory_frame, 7, &accessory_effect);
1178        let mut accessory_binding = Vec::new();
1179        push_varint_field(&mut accessory_binding, 1, 1);
1180        push_varint_field(&mut accessory_binding, 2, 2);
1181        push_varint_field(&mut accessory_binding, 3, 3);
1182        push_len(&mut accessory_frame, 8, &accessory_binding);
1183        push_varint_field(&mut accessory_frame, 9, 1);
1184        push_varint_field(&mut accessory_frame, 10, 0);
1185        push_varint_field(&mut accessory_frame, 11, 1);
1186        let mut accessory_bundle = Vec::new();
1187        push_len(&mut accessory_bundle, 2, &accessory_frame);
1188        let mut accessory_unit = Vec::new();
1189        push_len(&mut accessory_unit, 1, &accessory_bundle);
1190        push_len(&mut data, 5, &accessory_unit);
1191
1192        let mut bone_frame = Vec::new();
1193        push_len(&mut bone_frame, 1, &common(10));
1194        push_varint_field(&mut bone_frame, 2, 3);
1195        push_len(&mut bone_frame, 3, &vec3(1.0, 2.0, 3.0));
1196        push_len(&mut bone_frame, 4, &vec4(0.0, 0.0, 0.0, 1.0));
1197        let mut bone_interpolation = Vec::new();
1198        push_len(
1199            &mut bone_interpolation,
1200            1,
1201            &interp_unit_integer([1, 2, 3, 4]),
1202        );
1203        push_len(
1204            &mut bone_interpolation,
1205            4,
1206            &interp_unit_float([0.1, 0.2, 0.3, 0.4]),
1207        );
1208        push_len(&mut bone_frame, 5, &bone_interpolation);
1209        push_varint_field(&mut bone_frame, 6, 2);
1210        push_varint_field(&mut bone_frame, 7, 1);
1211        let mut bone_bundle = Vec::new();
1212        push_len(&mut bone_bundle, 3, &bone_frame);
1213        let mut bone_unit = Vec::new();
1214        push_len(&mut bone_unit, 2, &bone_bundle);
1215        push_len(&mut data, 5, &bone_unit);
1216
1217        let mut morph_frame = Vec::new();
1218        push_len(&mut morph_frame, 1, &common(11));
1219        push_varint_field(&mut morph_frame, 2, 4);
1220        push_f32_field(&mut morph_frame, 3, 0.5);
1221        let mut morph_interpolation = Vec::new();
1222        push_len(
1223            &mut morph_interpolation,
1224            1,
1225            &interp_unit_integer([5, 6, 7, 8]),
1226        );
1227        push_len(&mut morph_frame, 4, &morph_interpolation);
1228        let mut morph_bundle = Vec::new();
1229        push_len(&mut morph_bundle, 3, &morph_frame);
1230        let mut morph_unit = Vec::new();
1231        push_len(&mut morph_unit, 7, &morph_bundle);
1232        push_len(&mut data, 5, &morph_unit);
1233
1234        let mut camera_frame = Vec::new();
1235        push_len(&mut camera_frame, 1, &common(12));
1236        push_len(&mut camera_frame, 2, &vec3(4.0, 5.0, 6.0));
1237        push_len(&mut camera_frame, 3, &vec3(0.1, 0.2, 0.3));
1238        push_f32_field(&mut camera_frame, 4, 45.0);
1239        push_f32_field(&mut camera_frame, 5, 20.0);
1240        let mut camera_interpolation = Vec::new();
1241        push_len(
1242            &mut camera_interpolation,
1243            6,
1244            &interp_unit_float([1.1, 1.2, 1.3, 1.4]),
1245        );
1246        push_len(&mut camera_frame, 6, &camera_interpolation);
1247        push_varint_field(&mut camera_frame, 8, 1);
1248        let mut camera_bundle = Vec::new();
1249        push_len(&mut camera_bundle, 2, &camera_frame);
1250        let mut camera_unit = Vec::new();
1251        push_len(&mut camera_unit, 3, &camera_bundle);
1252        push_len(&mut data, 5, &camera_unit);
1253
1254        let mut light_frame = Vec::new();
1255        push_len(&mut light_frame, 1, &common(13));
1256        push_len(&mut light_frame, 2, &vec3(0.8, 0.7, 0.6));
1257        push_len(&mut light_frame, 3, &vec3(-1.0, -2.0, -3.0));
1258        let mut light_bundle = Vec::new();
1259        push_len(&mut light_bundle, 2, &light_frame);
1260        let mut light_unit = Vec::new();
1261        push_len(&mut light_unit, 5, &light_bundle);
1262        push_len(&mut data, 5, &light_unit);
1263
1264        let mut model_frame = Vec::new();
1265        push_len(&mut model_frame, 1, &common(14));
1266        push_varint_field(&mut model_frame, 2, 1);
1267        let mut constraint = Vec::new();
1268        push_varint_field(&mut constraint, 1, 9);
1269        push_varint_field(&mut constraint, 2, 1);
1270        push_len(&mut model_frame, 3, &constraint);
1271        let mut effect = Vec::new();
1272        push_varint_field(&mut effect, 1, 10);
1273        push_len(&mut effect, 5, &vec4(0.1, 0.2, 0.3, 0.4));
1274        push_len(&mut model_frame, 4, &effect);
1275        let mut binding = Vec::new();
1276        push_varint_field(&mut binding, 1, 11);
1277        push_varint_field(&mut binding, 2, 12);
1278        push_varint_field(&mut binding, 3, 13);
1279        push_len(&mut model_frame, 5, &binding);
1280        let mut edge = Vec::new();
1281        push_len(&mut edge, 1, &vec4(1.0, 0.5, 0.25, 0.75));
1282        push_f32_field(&mut edge, 2, 1.5);
1283        push_len(&mut model_frame, 6, &edge);
1284        push_varint_field(&mut model_frame, 8, 0);
1285        let mut model_bundle = Vec::new();
1286        push_len(&mut model_bundle, 2, &model_frame);
1287        let mut model_unit = Vec::new();
1288        push_len(&mut model_unit, 6, &model_bundle);
1289        push_len(&mut data, 5, &model_unit);
1290
1291        let mut shadow_frame = Vec::new();
1292        push_len(&mut shadow_frame, 1, &common(15));
1293        push_varint_field(&mut shadow_frame, 2, 1);
1294        push_varint_field(&mut shadow_frame, 3, 2);
1295        push_f32_field(&mut shadow_frame, 4, 30.0);
1296        let mut shadow_bundle = Vec::new();
1297        push_len(&mut shadow_bundle, 2, &shadow_frame);
1298        let mut shadow_unit = Vec::new();
1299        push_len(&mut shadow_unit, 9, &shadow_bundle);
1300        push_len(&mut data, 5, &shadow_unit);
1301
1302        let parsed = parse_nmd_manifest(&data).unwrap();
1303
1304        assert_eq!(parsed.payload.accessory_keyframes, 1);
1305        assert_eq!(parsed.payload.accessory_frames[0].common.frame_index, 9);
1306        assert_eq!(parsed.payload.accessory_frames[0].track_index, 2);
1307        assert_eq!(
1308            parsed.payload.accessory_frames[0].translation,
1309            [7.0, 8.0, 9.0]
1310        );
1311        assert_eq!(parsed.payload.accessory_frames[0].scale_factor, 1.25);
1312        assert_eq!(parsed.payload.accessory_frames[0].opacity, 0.75);
1313        assert_eq!(
1314            parsed.payload.accessory_frames[0].effect_parameters[0].float_value,
1315            Some(0.5)
1316        );
1317        assert_eq!(
1318            parsed.payload.accessory_frames[0]
1319                .binding
1320                .as_ref()
1321                .map(|binding| binding.global_bone_track_index),
1322            Some(3)
1323        );
1324        assert_eq!(parsed.payload.accessory_frames[0].visible, Some(true));
1325        assert_eq!(
1326            parsed.payload.accessory_frames[0].shadow_enabled,
1327            Some(false)
1328        );
1329        assert_eq!(
1330            parsed.payload.accessory_frames[0].add_blending_enabled,
1331            Some(true)
1332        );
1333        assert_eq!(parsed.payload.bone_frames[0].common.frame_index, 10);
1334        assert_eq!(parsed.payload.bone_frames[0].track_index, 3);
1335        assert_eq!(
1336            parsed.payload.bone_frames[0].local_translation,
1337            [1.0, 2.0, 3.0]
1338        );
1339        assert_eq!(
1340            parsed.payload.bone_frames[0].local_orientation,
1341            [0.0, 0.0, 0.0, 1.0]
1342        );
1343        assert_eq!(
1344            parsed.payload.bone_frames[0]
1345                .interpolation
1346                .as_ref()
1347                .and_then(|interpolation| interpolation.x.as_ref())
1348                .and_then(|unit| unit.integer),
1349            Some([1, 2, 3, 4])
1350        );
1351        assert_eq!(
1352            parsed.payload.bone_frames[0]
1353                .interpolation
1354                .as_ref()
1355                .and_then(|interpolation| interpolation.orientation.as_ref())
1356                .and_then(|unit| unit.float),
1357            Some([0.1, 0.2, 0.3, 0.4])
1358        );
1359        assert_eq!(parsed.payload.bone_frames[0].stage_index, Some(2));
1360        assert_eq!(
1361            parsed.payload.bone_frames[0].physics_simulation_enabled,
1362            Some(true)
1363        );
1364        assert_eq!(parsed.payload.morph_frames[0].weight, 0.5);
1365        assert_eq!(
1366            parsed.payload.morph_frames[0]
1367                .interpolation
1368                .as_ref()
1369                .and_then(|unit| unit.integer),
1370            Some([5, 6, 7, 8])
1371        );
1372        assert_eq!(parsed.payload.camera_frames[0].look_at, [4.0, 5.0, 6.0]);
1373        assert_eq!(parsed.payload.camera_frames[0].fov, 45.0);
1374        assert_eq!(
1375            parsed.payload.camera_frames[0]
1376                .interpolation
1377                .as_ref()
1378                .and_then(|interpolation| interpolation.distance.as_ref())
1379                .and_then(|unit| unit.float),
1380            Some([1.1, 1.2, 1.3, 1.4])
1381        );
1382        assert_eq!(
1383            parsed.payload.camera_frames[0].perspective_view_enabled,
1384            Some(true)
1385        );
1386        assert_eq!(parsed.payload.light_frames[0].color, [0.8, 0.7, 0.6]);
1387        assert!(parsed.payload.model_frames[0].visible);
1388        assert_eq!(parsed.payload.model_frames[0].constraint_state_count, 1);
1389        assert_eq!(
1390            parsed.payload.model_frames[0].constraint_states[0].track_index,
1391            9
1392        );
1393        assert!(parsed.payload.model_frames[0].constraint_states[0].enabled);
1394        assert_eq!(
1395            parsed.payload.model_frames[0].effect_parameters[0].track_index,
1396            10
1397        );
1398        assert_eq!(
1399            parsed.payload.model_frames[0].effect_parameters[0].vector_value,
1400            Some([0.1, 0.2, 0.3, 0.4])
1401        );
1402        assert_eq!(
1403            parsed.payload.model_frames[0].bindings[0].local_bone_track_index,
1404            Some(11)
1405        );
1406        assert_eq!(
1407            parsed.payload.model_frames[0].bindings[0].global_object_track_index,
1408            12
1409        );
1410        assert_eq!(
1411            parsed.payload.model_frames[0]
1412                .edge
1413                .as_ref()
1414                .map(|edge| edge.scale_factor),
1415            Some(1.5)
1416        );
1417        assert_eq!(
1418            parsed.payload.model_frames[0].physics_simulation_enabled,
1419            Some(false)
1420        );
1421        assert_eq!(parsed.payload.self_shadow_frames[0].mode, 2);
1422        assert_eq!(parsed.payload.self_shadow_frames[0].distance, 30.0);
1423    }
1424
1425    #[test]
1426    fn rejects_truncated_nmd_len_field() {
1427        let result = parse_nmd_manifest(&[key(2, WIRE_LEN), 5, b'a']);
1428
1429        assert!(matches!(result, Err(ImportError::UnexpectedEof(4))));
1430    }
1431
1432    #[test]
1433    fn rejects_empty_nmd_manifest() {
1434        let result = parse_nmd_manifest(&[]);
1435
1436        assert!(matches!(result, Err(ImportError::UnexpectedEof(1))));
1437    }
1438
1439    #[test]
1440    fn rejects_overflowing_varint_without_panicking() {
1441        let result = parse_nmd_manifest(&[0xff; 10]);
1442
1443        assert!(matches!(
1444            result,
1445            Err(ImportError::UnsupportedFormat {
1446                format: "NMD",
1447                detail: "varint overflows u64"
1448            })
1449        ));
1450    }
1451
1452    #[test]
1453    fn rejects_zero_protobuf_field_number() {
1454        let result = parse_nmd_manifest(&[0]);
1455
1456        assert!(matches!(
1457            result,
1458            Err(ImportError::UnsupportedFormat {
1459                format: "NMD",
1460                detail: "protobuf field number must be non-zero"
1461            })
1462        ));
1463    }
1464
1465    #[test]
1466    fn rejects_oversized_protobuf_field_number() {
1467        let mut data = Vec::new();
1468        push_varint(&mut data, (0x2000_0000u64 << 3) | u64::from(WIRE_VARINT));
1469
1470        let result = parse_nmd_manifest(&data);
1471
1472        assert!(matches!(
1473            result,
1474            Err(ImportError::UnsupportedFormat {
1475                format: "NMD",
1476                detail: "protobuf field number exceeds the supported range"
1477            })
1478        ));
1479    }
1480
1481    #[test]
1482    fn keyframe_bundle_uses_last_oneof_field() {
1483        let mut bone = Vec::new();
1484        push_len(&mut bone, 3, &[]);
1485        let mut morph = Vec::new();
1486        push_len(&mut morph, 3, &[]);
1487        push_len(&mut morph, 3, &[]);
1488
1489        let mut unit = Vec::new();
1490        push_len(&mut unit, 2, &bone);
1491        push_len(&mut unit, 7, &morph);
1492        let mut data = Vec::new();
1493        push_len(&mut data, 5, &unit);
1494
1495        let parsed = parse_nmd_manifest(&data).unwrap();
1496
1497        assert_eq!(parsed.keyframe_bundles.bone, 0);
1498        assert_eq!(parsed.keyframe_bundles.morph, 1);
1499        assert_eq!(parsed.payload.bone_keyframes, 0);
1500        assert_eq!(parsed.payload.morph_keyframes, 2);
1501    }
1502
1503    #[test]
1504    fn unknown_len_field_does_not_override_known_keyframe_bundle_oneof() {
1505        let mut bone = Vec::new();
1506        push_len(&mut bone, 3, &[]);
1507
1508        let mut unit = Vec::new();
1509        push_len(&mut unit, 2, &bone);
1510        push_len(&mut unit, 10, b"unknown");
1511        let mut data = Vec::new();
1512        push_len(&mut data, 5, &unit);
1513
1514        let parsed = parse_nmd_manifest(&data).unwrap();
1515
1516        assert_eq!(parsed.keyframe_bundles.bone, 1);
1517        assert_eq!(parsed.keyframe_bundles.unknown, 0);
1518        assert_eq!(parsed.payload.bone_keyframes, 1);
1519    }
1520
1521    #[test]
1522    fn parses_negative_int32_varint_values() {
1523        let mut shadow_frame = Vec::new();
1524        push_len(&mut shadow_frame, 1, &common(1));
1525        push_varint_field(&mut shadow_frame, 3, u64::from(u32::MAX));
1526
1527        let mut shadow_bundle = Vec::new();
1528        push_len(&mut shadow_bundle, 2, &shadow_frame);
1529        let mut shadow_unit = Vec::new();
1530        push_len(&mut shadow_unit, 9, &shadow_bundle);
1531        let mut data = Vec::new();
1532        push_len(&mut data, 5, &shadow_unit);
1533
1534        let parsed = parse_nmd_manifest(&data).unwrap();
1535
1536        assert_eq!(parsed.payload.self_shadow_frames[0].mode, -1);
1537    }
1538
1539    #[test]
1540    fn rejects_int32_varint_values_that_exceed_u32() {
1541        let mut shadow_frame = Vec::new();
1542        push_len(&mut shadow_frame, 1, &common(1));
1543        push_varint_field(&mut shadow_frame, 3, u64::from(u32::MAX) + 1);
1544
1545        let mut shadow_bundle = Vec::new();
1546        push_len(&mut shadow_bundle, 2, &shadow_frame);
1547        let mut shadow_unit = Vec::new();
1548        push_len(&mut shadow_unit, 9, &shadow_bundle);
1549        let mut data = Vec::new();
1550        push_len(&mut data, 5, &shadow_unit);
1551
1552        let result = parse_nmd_manifest(&data);
1553
1554        assert!(matches!(
1555            result,
1556            Err(ImportError::UnsupportedFormat {
1557                format: "NMD",
1558                detail: "int32 varint value overflows u32"
1559            })
1560        ));
1561    }
1562
1563    #[test]
1564    fn rejects_nonfinite_keyframe_float_values() {
1565        let mut accessory_frame = Vec::new();
1566        push_len(&mut accessory_frame, 1, &common(1));
1567        push_f32_field(&mut accessory_frame, 5, f32::NAN);
1568
1569        let mut accessory_bundle = Vec::new();
1570        push_len(&mut accessory_bundle, 2, &accessory_frame);
1571        let mut accessory_unit = Vec::new();
1572        push_len(&mut accessory_unit, 1, &accessory_bundle);
1573        let mut data = Vec::new();
1574        push_len(&mut data, 5, &accessory_unit);
1575
1576        let result = parse_nmd_manifest(&data);
1577
1578        assert!(matches!(
1579            result,
1580            Err(ImportError::UnsupportedFormat {
1581                format: "NMD",
1582                detail: "float value is not finite"
1583            })
1584        ));
1585    }
1586
1587    #[test]
1588    fn rejects_nonfinite_preferred_fps() {
1589        let mut data = Vec::new();
1590        data.push(key(3, WIRE_FIXED32));
1591        data.extend_from_slice(&f32::INFINITY.to_le_bytes());
1592
1593        let result = parse_nmd_manifest(&data);
1594
1595        assert!(matches!(
1596            result,
1597            Err(ImportError::UnsupportedFormat {
1598                format: "NMD",
1599                detail: "float value is not finite"
1600            })
1601        ));
1602    }
1603
1604    #[test]
1605    fn parses_multibyte_length_delimited_fields() {
1606        let mut data = Vec::new();
1607        let name = vec![b'a'; 130];
1608        push_len(&mut data, 2, &name);
1609
1610        let parsed = parse_nmd_manifest(&data).unwrap();
1611        let expected = "a".repeat(130);
1612
1613        assert_eq!(
1614            parsed.metadata.main_object_name.as_deref(),
1615            Some(expected.as_str())
1616        );
1617    }
1618}