1use std::{borrow::Cow, collections::HashMap, fmt::Debug, io, mem, path::Path};
4
5use anyhow::{bail, Result};
6use layout::ValueRep;
7
8mod coding;
9mod layout;
10mod reader;
11
12pub use layout::{version, Version};
13pub use reader::{CrateFile, ReadExt};
14
15use crate::sdf;
16
17#[derive(Default, Debug)]
18struct Spec {
19 ty: sdf::SpecType,
21 fields: HashMap<String, ValueRep>,
23}
24
25#[derive(Debug)]
27pub struct CrateData<R> {
28 file: CrateFile<R>,
29 data: HashMap<sdf::Path, Spec>,
30}
31
32impl<R> CrateData<R>
33where
34 R: io::Read + io::Seek,
35{
36 pub fn open(reader: R, safe: bool) -> Result<Self> {
38 let mut file = CrateFile::open(reader)?;
39
40 if safe {
41 file.validate()?;
42 }
43
44 let mut data = HashMap::default();
47 let specs = mem::take(&mut file.specs);
48
49 for filespec in specs {
50 let path = file.paths[filespec.path_index].clone();
51 let ty = filespec.spec_type;
52
53 let mut fields = HashMap::default();
54 let mut index = filespec.fieldset_index;
55
56 while index < file.fieldsets.len() {
57 let current = match file.fieldsets[index] {
58 Some(value) => value,
59 None => break,
60 };
61
62 index += 1;
63
64 let field = &file.fields[current];
65 let name = file.tokens[field.token_index].clone();
66
67 fields.insert(name, field.value_rep);
68 }
69
70 data.insert(path, Spec { ty, fields });
71 }
72
73 Ok(Self { file, data })
74 }
75}
76
77impl<R> sdf::AbstractData for CrateData<R>
78where
79 R: io::Read + io::Seek,
80{
81 #[inline]
82 fn has_spec(&self, path: &sdf::Path) -> bool {
83 self.data.contains_key(path)
84 }
85
86 #[inline]
87 fn has_field(&self, path: &sdf::Path, field: &str) -> bool {
88 self.data.get(path).is_some_and(|spec| spec.fields.contains_key(field))
89 }
90
91 #[inline]
92 fn spec_type(&self, path: &sdf::Path) -> Option<sdf::SpecType> {
93 self.data.get(path).map(|spec| spec.ty)
94 }
95
96 fn get(&mut self, path: &sdf::Path, field: &str) -> Result<Cow<sdf::Value>> {
97 let Some(spec) = self.data.get(path) else {
98 bail!("No spec found for path: {}", path)
99 };
100
101 let Some(value_rep) = spec.fields.get(field).cloned() else {
102 bail!("No field found for path '{}' and field '{}'", path, field)
103 };
104
105 let value = self.file.value(value_rep)?;
106
107 Ok(Cow::Owned(value))
108 }
109
110 #[inline]
111 fn list(&self, path: &sdf::Path) -> Option<Vec<String>> {
112 self.data.get(path).map(|spec| spec.fields.keys().cloned().collect())
113 }
114}
115
116pub fn read_file(path: impl AsRef<Path>) -> Result<Box<dyn sdf::AbstractData>> {
118 let file = std::fs::File::open(path)?;
119 let data = CrateData::open(file, true)?;
120
121 Ok(Box::new(data))
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use half::f16;
128
129 #[test]
130 fn test_crate_hierarchy() -> Result<()> {
131 let mut data =
132 read_file("./extern/usd-wg-assets/full_assets/ElephantWithMonochord/SoC-ElephantWithMonochord.usdc")?;
133
134 let prim_children: Vec<String> = data
135 .get(&sdf::Path::abs_root(), "primChildren")?
136 .into_owned()
137 .try_as_token_vec()
138 .unwrap();
139 assert_eq!(prim_children, vec!["SoC_ElephantWithMonochord".to_string()]);
140
141 let elephant: Vec<String> = data
142 .get(&sdf::path("/SoC_ElephantWithMonochord")?, "primChildren")?
143 .into_owned()
144 .try_as_token_vec()
145 .unwrap();
146
147 assert_eq!(
148 elephant,
149 vec![
150 "Materials".to_string(),
151 "Object".to_string(),
152 "CharacterAudioSource".to_string()
153 ]
154 );
155
156 let materials: Vec<String> = data
157 .get(&sdf::path("/SoC_ElephantWithMonochord/Materials")?, "primChildren")?
158 .into_owned()
159 .try_as_token_vec()
160 .unwrap();
161
162 assert_eq!(
163 materials,
164 vec!["Elefant_Mat_68050".to_string(), "Monochord_Mat_68062".to_string()]
165 );
166
167 Ok(())
168 }
169
170 #[test]
171 fn test_read_custom_layer_data() {
172 let mut data = read_file("fixtures/fields.usdc").unwrap();
173
174 let custom_layer_data = data.get(&sdf::Path::abs_root(), "customLayerData").unwrap();
175
176 let copyright = custom_layer_data
180 .try_as_dictionary_ref()
181 .unwrap()
182 .get("test")
183 .unwrap()
184 .try_as_string_ref()
185 .unwrap();
186
187 assert_eq!(copyright, "Test string");
188 }
189
190 #[test]
191 fn test_read_bool() -> Result<()> {
192 let mut data = read_file("fixtures/fields.usdc")?;
193
194 let single = data
195 .get(&sdf::path("/World.flipNormals")?, "default")?
196 .into_owned()
197 .try_as_bool()
198 .unwrap();
199
200 assert!(single);
201
202 let bool_array = data
203 .get(&sdf::path("/World.boolArray")?, "default")?
204 .into_owned()
205 .try_as_bool_vec()
206 .unwrap();
207
208 assert_eq!(bool_array, vec![true, true, false, false, true, false]);
209
210 Ok(())
211 }
212
213 #[test]
214 fn test_read_chars() -> Result<()> {
215 let mut data = read_file("fixtures/fields.usdc")?;
216
217 let single_char = data
218 .get(&sdf::path("/World.singleChar")?, "default")?
219 .into_owned()
220 .try_as_uchar()
221 .unwrap();
222
223 assert_eq!(single_char, 128);
224
225 let char_array = data
226 .get(&sdf::path("/World.chars")?, "default")?
227 .into_owned()
228 .try_as_uchar_vec()
229 .unwrap();
230
231 assert_eq!(char_array, vec![128, 129, 130, 131, 132, 133, 134, 135, 136, 137]);
232
233 Ok(())
234 }
235
236 #[test]
237 fn test_read_quat_floats() -> Result<()> {
238 let mut data = read_file("fixtures/fields.usdc")?;
239
240 let quat = data
241 .get(&sdf::path("/World.quatfSingle")?, "default")?
242 .into_owned()
243 .try_as_quatf()
244 .unwrap();
245
246 assert_eq!(quat, vec![2.9, 8.5, 4.6, 1.4]);
247
248 let quat = data
249 .get(&sdf::path("/World.quatfArr")?, "default")?
250 .into_owned()
251 .try_as_quatf()
252 .unwrap();
253
254 assert_eq!(
255 quat,
256 vec![
257 3.5, 2.6, 3.6, 4.2, 5.3, 6.3, 5.2, 2.4, 4.3, 2.4, 6.4, 7.1, ]
261 );
262
263 Ok(())
264 }
265
266 #[test]
267 fn test_read_quat_doubles() -> Result<()> {
268 let mut data = read_file("fixtures/fields.usdc")?;
269
270 let quat = data
271 .get(&sdf::path("/World.quatdSingle")?, "default")?
272 .into_owned()
273 .try_as_quatd()
274 .unwrap();
275
276 assert_eq!(quat, vec![5.3, 6.3, 5.2, 2.4]);
277
278 let quat = data
279 .get(&sdf::path("/World.quatdArr")?, "default")?
280 .into_owned()
281 .try_as_quatd()
282 .unwrap();
283
284 assert_eq!(
285 quat,
286 vec![
287 3.5, 2.6, 3.6, 4.2, 4.3, 2.4, 6.4, 7.1, ]
290 );
291
292 Ok(())
293 }
294
295 #[test]
296 fn test_read_quat_half() -> Result<()> {
297 let mut data = read_file("fixtures/fields.usdc")?;
298
299 let quat = data
300 .get(&sdf::path("/World.quathSingle")?, "default")?
301 .into_owned()
302 .try_as_quath()
303 .unwrap();
304
305 assert_eq!(
306 quat,
307 [4.6, 2.5, 7.6, 3.5].into_iter().map(f16::from_f32).collect::<Vec<_>>()
308 );
309
310 let quat = data
311 .get(&sdf::path("/World.quathArr")?, "default")?
312 .into_owned()
313 .try_as_quath()
314 .unwrap();
315
316 assert_eq!(
317 quat,
318 [
319 2.4, 7.8, 8.5, 4.7, 6.7, 5.6, 5.3, 4.6, ]
322 .into_iter()
323 .map(f16::from_f32)
324 .collect::<Vec<_>>()
325 );
326
327 Ok(())
328 }
329
330 #[test]
331 fn test_read_sub_layers() -> Result<()> {
332 let mut data = read_file("fixtures/expressions.usdc")?;
333
334 let sub_layer_offsets = data
335 .get(&sdf::path("/")?, "subLayerOffsets")?
336 .into_owned()
337 .try_as_layer_offset_vec()
338 .unwrap()
339 .into_iter()
340 .next()
341 .unwrap();
342
343 assert_eq!(sub_layer_offsets.offset, 0.0);
344 assert_eq!(sub_layer_offsets.scale, 1.0);
345
346 let sub_layers = data
347 .get(&sdf::path("/")?, "subLayers")?
348 .into_owned()
349 .try_as_string_vec()
350 .unwrap();
351 assert_eq!(sub_layers, vec!["`\"render_pass_${RENDER_PASS}.usd\"`"]);
352
353 Ok(())
354 }
355
356 #[test]
357 fn test_read_variant_selection() -> Result<()> {
358 let mut data = read_file("fixtures/expressions.usdc")?;
359
360 let variant_set_names = data
362 .get(&sdf::path("/asset1")?, "variantSetNames")?
363 .into_owned()
364 .try_as_string_list_op()
365 .unwrap();
366 assert_eq!(variant_set_names.prepended_items, vec!["displayVariantSet".to_string()]);
367
368 let variant_selection = data
369 .get(&sdf::path("/asset1")?, "variantSelection")?
370 .into_owned()
371 .try_as_variant_selection_map()
372 .unwrap();
373
374 assert_eq!(variant_selection.len(), 1);
375 assert_eq!(
376 variant_selection.get("displayVariantSet").unwrap(),
377 "`${VARIANT_CHOICE}`"
378 );
379
380 Ok(())
381 }
382
383 #[test]
384 fn test_read_connection() -> Result<()> {
385 let mut data = read_file("fixtures/connection.usdc")?;
386
387 let conn = data
388 .get(&sdf::path("/boardMat/stReader.inputs:varname")?, "connectionPaths")?
389 .into_owned()
390 .try_as_path_list_op()
391 .unwrap();
392
393 assert!(conn.explicit);
394 assert_eq!(
395 conn.explicit_items,
396 vec![sdf::path("/TexModel/boardMat.inputs:frame:stPrimvarName")?]
397 );
398
399 let conn = data
400 .get(&sdf::path("/boardMat.outputs:surface")?, "connectionPaths")?
401 .into_owned()
402 .try_as_path_list_op()
403 .unwrap();
404
405 assert!(conn.explicit);
406 assert_eq!(
407 conn.explicit_items,
408 vec![sdf::path("/TexModel/boardMat/PBRShader.outputs:surface")?]
409 );
410
411 Ok(())
412 }
413
414 #[test]
415 fn test_read_reference() -> Result<()> {
416 let mut data = read_file("fixtures/reference.usdc")?;
417
418 let references = data
419 .get(&sdf::path("/MarbleCollection/Marble_Red")?, "references")?
420 .into_owned()
421 .try_as_reference_list_op()
422 .unwrap();
423
424 assert!(references.appended_items.is_empty());
425 assert!(references.deleted_items.is_empty());
426 assert!(references.ordered_items.is_empty());
427
428 assert!(references.explicit);
429 assert_eq!(references.explicit_items.len(), 1);
430
431 assert_eq!(references.explicit_items[0].asset_path, "Marble.usd");
432 assert_eq!(references.explicit_items[0].prim_path, sdf::path("/Foo/Bar")?);
433
434 Ok(())
435 }
436
437 #[test]
438 fn test_read_payload() -> Result<()> {
439 let mut data = read_file("fixtures/payload.usdc")?;
440
441 let payload = data
442 .get(&sdf::path("/MySphere1")?, "payload")?
443 .into_owned()
444 .try_as_payload()
445 .unwrap();
446
447 assert_eq!(payload.asset_path, "./payload.usda");
448 assert_eq!(payload.prim_path, sdf::path("/MySphere")?);
449
450 assert!(payload.layer_offset.is_some());
451
452 let layer_offset = payload.layer_offset.unwrap();
453 assert_eq!(layer_offset.offset, 0.0);
454 assert_eq!(layer_offset.scale, 1.0);
455
456 let payload_list_op = data
457 .get(&sdf::path("/MySphere2")?, "payload")?
458 .into_owned()
459 .try_as_payload_list_op()
460 .unwrap();
461
462 assert!(!payload_list_op.explicit);
463
464 assert!(payload_list_op.explicit_items.is_empty());
465 assert!(payload_list_op.added_items.is_empty());
466 assert!(payload_list_op.appended_items.is_empty());
467 assert!(payload_list_op.deleted_items.is_empty());
468 assert!(payload_list_op.ordered_items.is_empty());
469
470 assert_eq!(payload_list_op.prepended_items.len(), 1);
471 assert_eq!(payload_list_op.prepended_items[0].asset_path, "./cube_payload.usda");
472 assert_eq!(payload_list_op.prepended_items[0].prim_path, sdf::path("/PayloadCube")?);
473
474 Ok(())
475 }
476
477 #[test]
478 fn test_read_doubles() -> Result<()> {
479 let mut data = read_file("fixtures/floats.usdc")?;
480
481 let single = data
482 .get(&sdf::path("/PrimD.single")?, "default")?
483 .into_owned()
484 .try_as_double()
485 .unwrap();
486 assert_eq!(single, 4.3_f64);
487
488 let array = data
489 .get(&sdf::path("/PrimD.simple")?, "default")?
490 .into_owned()
491 .try_as_double_vec()
492 .unwrap();
493 assert_eq!(array, vec![0.5, 1.7, 2.4, 3.5, 4.9, 5.3, 6.2, 7.8, 8.6, 9.3]);
494
495 let compressed = data
496 .get(&sdf::path("/PrimD.copressed")?, "default")?
497 .into_owned()
498 .try_as_double_vec()
499 .unwrap();
500 assert_eq!(
501 compressed,
502 vec![
503 0.5, 1.7, 2.4, 3.5, 4.9, 5.3, 6.2, 7.8, 8.6, 9.3, 5.3, 6.2, 7.8, 8.6, 9.3, 0.5, 1.7, 2.4, 3.5, 4.9,
504 0.5, 1.7, 2.4, 3.5, 4.9, 5.3, 6.2, 7.8, 8.6, 9.3, 5.3, 6.2, 7.8, 8.6, 9.3, 0.5, 1.7, 2.4, 3.5, 4.9,
505 0.5, 1.7, 2.4, 3.5, 4.9, 5.3, 6.2, 7.8, 8.6, 9.3, 5.3, 6.2, 7.8, 8.6, 9.3, 0.5, 1.7, 2.4, 3.5, 4.9,
506 0.5, 1.7, 2.4, 3.5, 4.9, 5.3, 6.2, 7.8, 8.6, 9.3, 5.3, 6.2, 7.8, 8.6, 9.3, 0.5, 1.7, 2.4, 3.5, 4.9,
507 0.5, 1.7, 2.4, 3.5, 4.9, 5.3, 6.2, 7.8, 8.6, 9.3, 5.3, 6.2, 7.8, 8.6, 9.3, 0.5, 1.7, 2.4, 3.5, 4.9,
508 ]
509 );
510
511 Ok(())
512 }
513
514 #[test]
515 fn test_read_floats() -> Result<()> {
516 let mut data = read_file("fixtures/floats.usdc")?;
517
518 let single = data
519 .get(&sdf::path("/PrimF.single")?, "default")?
520 .into_owned()
521 .try_as_float()
522 .unwrap();
523 assert_eq!(single, 3.5);
524
525 let array = data
526 .get(&sdf::path("/PrimF.simple")?, "default")?
527 .into_owned()
528 .try_as_float_vec()
529 .unwrap();
530 assert_eq!(array, vec![9.1, 2.3, 6.4, 7.4, 3.6, 4.3, 5.3, 5.6, 8.7, 4.7]);
531
532 let compressed = data
533 .get(&sdf::path("/PrimF.copressed")?, "default")?
534 .into_owned()
535 .try_as_float_vec()
536 .unwrap();
537
538 assert_eq!(
539 compressed,
540 vec![
541 9.1, 2.3, 6.4, 7.4, 3.6, 4.3, 5.3, 5.6, 8.7, 4.7, 4.7, 9.1, 2.3, 6.4, 7.4, 3.6, 4.3, 5.3, 5.6, 8.7,
542 8.7, 4.7, 9.1, 2.3, 6.4, 7.4, 3.6, 4.3, 5.3, 5.6, 5.6, 8.7, 4.7, 9.1, 2.3, 6.4, 7.4, 3.6, 4.3, 5.3,
543 5.3, 5.6, 8.7, 4.7, 9.1, 2.3, 6.4, 7.4, 3.6, 4.3,
544 ]
545 );
546
547 Ok(())
548 }
549
550 #[test]
551 fn test_read_halfs() -> Result<()> {
552 let mut data = read_file("fixtures/floats.usdc")?;
553
554 let single = data
555 .get(&sdf::path("/PrimH.single")?, "default")?
556 .into_owned()
557 .try_as_half()
558 .unwrap();
559
560 assert_eq!(single, f16::from_f32(2.9));
561
562 let array = data
563 .get(&sdf::path("/PrimH.simple")?, "default")?
564 .into_owned()
565 .try_as_half_vec()
566 .unwrap();
567
568 assert_eq!(
569 array,
570 [4.3, 5.3, 5.6, 8.7, 4.7, 9.1, 2.3, 6.4, 7.4, 3.6]
571 .into_iter()
572 .map(f16::from_f32)
573 .collect::<Vec<_>>()
574 );
575
576 let compressed = data
577 .get(&sdf::path("/PrimH.copressed")?, "default")?
578 .into_owned()
579 .try_as_half_vec()
580 .unwrap();
581
582 assert_eq!(
583 compressed,
584 [
585 4.3, 5.3, 5.6, 8.7, 4.7, 9.1, 2.3, 6.4, 7.4, 3.6, 3.6, 4.3, 5.3, 5.6, 8.7, 4.7, 9.1, 2.3, 6.4, 7.4,
586 7.4, 3.6, 4.3, 5.3, 5.6, 8.7, 4.7, 9.1, 2.3, 6.4, 6.4, 7.4, 3.6, 4.3, 5.3, 5.6, 8.7, 4.7, 9.1, 2.3,
587 2.3, 6.4, 7.4, 3.6, 4.3, 5.3, 5.6, 8.7, 4.7, 9.1,
588 ]
589 .into_iter()
590 .map(f16::from_f32)
591 .collect::<Vec<_>>()
592 );
593
594 Ok(())
595 }
596
597 #[test]
598 fn test_read_time_series() -> Result<()> {
599 let mut data = read_file("fixtures/timesamples.usdc")?;
600
601 let samples = data
602 .get(&sdf::path("/Prim.prop")?, "timeSamples")?
603 .into_owned()
604 .try_as_time_samples()
605 .unwrap();
606 assert_eq!(samples.len(), 2);
607
608 let keys = samples.iter().map(|(d, _)| d).copied().collect::<Vec<_>>();
609 assert_eq!(keys, vec![4.0, 5.0]);
610
611 assert!(matches!(&samples[0].1, sdf::Value::Double(x) if *x == 40.0_f64));
612 assert!(matches!(samples[1].1, sdf::Value::ValueBlock));
613
614 Ok(())
615 }
616
617 #[test]
618 fn test_read_ints_i32() -> Result<()> {
619 let mut data = read_file("fixtures/ints.usdc")?;
620
621 assert_eq!(
622 data.get(&sdf::path("/Prim32.single")?, "default")?
623 .into_owned()
624 .try_as_int()
625 .unwrap(),
626 12938
627 );
628
629 assert_eq!(
630 data.get(&sdf::path("/Prim32.compressed")?, "default")?
631 .into_owned()
632 .try_as_int_vec()
633 .unwrap(),
634 vec![
635 1, 2, 4, 5, -3, 4, 5, -2, 3, -0, 3, 2, 4, -2, 4, 1, 8, -1, 5, -5, 2, 6, -3, 4, 6, 3, -7, 2, -3, 3, 6,
636 2, 6, 6, -4, 2, -4, 6, -2, 4
637 ]
638 );
639
640 Ok(())
641 }
642
643 #[test]
644 fn test_read_ints_i64() -> Result<()> {
645 let mut data = read_file("fixtures/ints.usdc")?;
646
647 assert_eq!(
648 data.get(&sdf::path("/Prim64.single")?, "default")?
649 .into_owned()
650 .try_as_int_64()
651 .unwrap(),
652 1234567890
653 );
654
655 assert_eq!(
656 data.get(&sdf::path("/Prim64.compressed")?, "default")?
657 .into_owned()
658 .try_as_int_64_vec()
659 .unwrap(),
660 vec![
661 10, 23, 48, 45, -23, 43, 65, -23, 23, -10, 34, 23, 45, -12, 34, 16, 18, -12, 65, -65, 21, 67, -43, 34,
662 36, 34, -67, 25, -23, 63, 65, 23, 65, 63, -54, 23, -44, 65, -62, 54
663 ]
664 );
665
666 Ok(())
667 }
668
669 #[test]
670 fn test_read_ints_u32() -> Result<()> {
671 let mut data = read_file("fixtures/ints.usdc")?;
672
673 assert_eq!(
674 data.get(&sdf::path("/PrimU32.single")?, "default")?
675 .into_owned()
676 .try_as_uint()
677 .unwrap(),
678 80129
679 );
680
681 assert_eq!(
682 data.get(&sdf::path("/PrimU32.compressed")?, "default")?
683 .into_owned()
684 .try_as_uint_vec()
685 .unwrap(),
686 vec![
687 1, 2, 4, 5, 3, 4, 5, 2, 3, 0, 3, 2, 4, 2, 4, 1, 8, 1, 5, 5, 2, 6, 3, 4, 6, 3, 7, 2, 3, 3, 6, 2, 6, 6,
688 4, 2, 4, 6, 2, 4
689 ]
690 );
691
692 Ok(())
693 }
694
695 #[test]
696 fn test_read_ints_u64() -> Result<()> {
697 let mut data = read_file("fixtures/ints.usdc")?;
698
699 assert_eq!(
700 data.get(&sdf::path("/PrimU64.single")?, "default")?
701 .into_owned()
702 .try_as_uint_64()
703 .unwrap(),
704 432423654
705 );
706
707 assert_eq!(
708 data.get(&sdf::path("/PrimU64.compressed")?, "default")?
709 .into_owned()
710 .try_as_uint_64_vec()
711 .unwrap(),
712 vec![
713 34, 23, 45, 12, 34, 16, 18, 12, 65, 65, 10, 23, 48, 45, 23, 43, 65, 23, 23, 10, 65, 23, 65, 63, 54, 23,
714 44, 65, 62, 54, 21, 67, 43, 34, 36, 34, 67, 25, 23, 63,
715 ]
716 );
717
718 Ok(())
719 }
720
721 #[test]
722 fn test_read_array_fields() -> Result<()> {
723 let mut data = read_file("fixtures/fields.usdc")?;
724
725 let default_prim = data.get(&sdf::Path::abs_root(), "defaultPrim")?;
727 assert_eq!(default_prim.try_as_token_ref().unwrap(), "World");
728
729 let clipping_planes = data.get(&sdf::path("/World.clippingPlanes")?, "default")?;
731 assert!(clipping_planes.into_owned().try_as_vec_4f_ref().unwrap().is_empty());
732
733 let clipping_range = data.get(&sdf::path("/World.clippingRange")?, "default")?;
735 assert_eq!(
736 &clipping_range.into_owned().try_as_vec_2f().unwrap(),
737 &[1.0, 10000000.0]
738 );
739
740 let diffuse_color = data.get(&sdf::path("/World.diffuseColor")?, "default")?;
742 assert_eq!(
743 &diffuse_color.into_owned().try_as_vec_3f().unwrap(),
744 &[0.18, 0.18, 0.18]
745 );
746
747 let face_vertex_counts = data.get(&sdf::path("/World.faceVertexCounts")?, "default")?;
749 assert_eq!(
750 &face_vertex_counts.into_owned().try_as_int_vec().unwrap(),
751 &[1, 2, 3, 4, 5, 6]
752 );
753
754 let normals = data.get(&sdf::path("/World.normals")?, "default")?;
756 assert_eq!(
757 normals.try_as_vec_3f_ref().unwrap(),
758 &[0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0]
759 );
760
761 let xform_op_rotate_xyz = data.get(&sdf::path("/World.xformOp:rotateXYZ")?, "default")?;
763 assert_eq!(xform_op_rotate_xyz.try_as_vec_3d_ref().unwrap(), &[0.0, 0.0, 0.0]);
764
765 let xform_op_scale = data.get(&sdf::path("/World.xformOp:scale")?, "default")?;
767 assert_eq!(xform_op_scale.try_as_vec_3d_ref().unwrap(), &[1.0, 1.0, 1.0]);
768
769 let xform_op_translate = data.get(&sdf::path("/World.xformOp:translate")?, "default")?;
771 assert_eq!(xform_op_translate.try_as_vec_3d_ref().unwrap(), &[0.0, 1.0, 0.0]);
772
773 Ok(())
774 }
775}