use std::fs;
use std::io;
use std::path::Path;
mod cursor;
mod error;
pub mod parser;
pub mod token;
mod types;
mod writer;
use parser::Parser;
pub use error::ParseError;
pub use writer::TextWriter;
use crate::{ar, sdf, tf};
pub fn parse(text: &str) -> Result<sdf::Data, ParseError> {
let specs = Parser::new(text).parse()?;
Ok(sdf::Data::from_specs(specs))
}
pub fn read_file(path: impl AsRef<Path>) -> crate::Result<sdf::Data> {
let path = path.as_ref();
let text = fs::read_to_string(path)
.map_err(|error| io::Error::new(error.kind(), format!("unable to read {}: {error}", path.display())))?;
Ok(parse(&text).map_err(|error| error.with_source_name(path.display().to_string()))?)
}
pub struct UsdaFileFormat;
impl sdf::FileFormat for UsdaFileFormat {
fn format_id(&self) -> tf::Token {
tf::Token::new("usda")
}
fn extensions(&self) -> &[&str] {
&["usda"]
}
fn read(
&self,
resolver: &dyn ar::Resolver,
resolved: &ar::ResolvedPath,
) -> Result<sdf::LayerData, sdf::FormatError> {
let bytes = resolver.open_asset(resolved)?.read_all()?;
let text = String::from_utf8(bytes).map_err(|error| sdf::FormatError::Decode(Box::new(error)))?;
let data = parse(&text)
.map_err(|error| sdf::FormatError::Decode(Box::new(error.with_source_name(resolved.to_string()))))?;
Ok(Box::new(data))
}
fn write(&self, data: &dyn sdf::AbstractData, mut sink: &mut dyn sdf::WriteSeek) -> Result<(), sdf::FormatError> {
TextWriter::write(data, &mut sink)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::sdf::{AbstractData, SpecType};
#[test]
fn parse_builds_data() {
let data = parse("#usda 1.0\ndef \"Root\"\n{\n float size = 2.5\n}\n").expect("parse");
let root = sdf::path("/Root").unwrap();
assert_eq!(data.spec_type(&root), Some(SpecType::Prim));
let size = root.append_property("size").unwrap();
assert_eq!(data.spec_type(&size), Some(SpecType::Attribute));
assert_eq!(
data.get_field(&size, "default").unwrap().into_owned(),
sdf::Value::Float(2.5)
);
}
}