1use crate::conversions::Converter;
2use crate::Error::CannotReadFile;
3use crate::{Error, Output, Result};
4use openapi_types::yaml::{load_from_str, ToOpenApi, YamlMap};
5use std::fmt::Debug;
6use std::fs;
7use std::path::PathBuf;
8use tracing::instrument;
9
10#[derive(Debug)]
11pub struct Reader {
12 path: PathBuf,
13}
14
15impl Reader {
16 pub fn new(path: impl Into<PathBuf>) -> Self {
17 Self { path: path.into() }
18 }
19
20 #[instrument]
21 pub fn open_target_type<A>(&self, converter: &A) -> Result<Output<A::TargetType>>
22 where
23 A: Converter + Debug,
24 {
25 let yaml = self.as_yaml_map()?;
26 let (from, errors) = ToOpenApi::apply(yaml)
27 .map_err(Error::openapi(&self.path))?
28 .into_tuple();
29
30 let to = converter
31 .convert(from)
32 .map_err(Error::conversion(&self.path))?;
33
34 let errors = if errors.is_empty() {
35 vec![]
36 } else {
37 let openapi_error = openapi_types::Error::multiple(errors);
38 let error = Error::openapi(&self.path)(openapi_error);
39 vec![error]
40 };
41 Ok(Output::new(to, errors))
42 }
43
44 pub(crate) fn as_string(&self) -> Result<String> {
45 let content = fs::read_to_string(&self.path).map_err(|cause| CannotReadFile {
46 path: PathBuf::from(&self.path),
47 detail: format!("{:?}", cause),
48 })?;
49 Ok(content)
50 }
51
52 fn as_yaml_map(&self) -> Result<YamlMap> {
53 let content = self.as_string()?;
54 let map = load_from_str(&content).map_err(Error::openapi(&self.path))?;
55 Ok(map)
56 }
57}