sass_embedded_host_rust/
embedded.rs1use std::{ffi::OsStr, path::Path};
2
3use atty::Stream;
4
5use crate::{
6 channel::Channel,
7 host::ImporterRegistry,
8 host::{Host, LoggerRegistry},
9 protocol::inbound_message::{
10 compile_request::{Input, StringInput},
11 CompileRequest,
12 },
13 CompileResult, Options, Result, StringOptions,
14};
15#[cfg(feature = "legacy")]
16use crate::{
17 legacy::LEGACY_IMPORTER_PROTOCOL, protocol::inbound_message::compile_request,
18};
19
20#[derive(Debug)]
21pub struct Embedded {
22 channel: Channel,
23}
24
25impl Embedded {
26 pub fn new(exe_path: impl AsRef<OsStr>) -> Self {
27 Self {
28 channel: Channel::new(exe_path),
29 }
30 }
31
32 pub fn compile(
33 &mut self,
34 path: impl AsRef<Path>,
35 options: Options,
36 ) -> Result<CompileResult> {
37 let mut logger_registry = LoggerRegistry::default();
38 let mut importer_registry = ImporterRegistry::default();
39 let importers = importer_registry
40 .register_all(options.importers, options.load_paths)
41 .collect();
42 if let Some(l) = options.logger {
43 logger_registry.register(l);
44 }
45
46 let request = CompileRequest {
47 style: options.style as i32,
48 source_map: options.source_map,
49 alert_color: options
50 .alert_color
51 .unwrap_or_else(|| atty::is(Stream::Stdout)),
52 alert_ascii: options.alert_ascii,
53 verbose: options.verbose,
54 quiet_deps: options.quiet_deps,
55 source_map_include_sources: options.source_map_include_sources,
56 charset: options.charset,
57 importers,
58 input: Some(Input::Path(path.as_ref().to_str().unwrap().to_string())),
59 ..Default::default()
62 };
63
64 let host = Host::new(importer_registry, logger_registry);
65 let conn = self.channel.connect(host);
66 let response = conn.compile_request(request)?;
67 CompileResult::try_from(response)
68 }
69
70 pub fn compile_string(
71 &mut self,
72 source: impl Into<String>,
73 options: StringOptions,
74 ) -> Result<CompileResult> {
75 let mut logger_registry = LoggerRegistry::default();
76 let mut importer_registry = ImporterRegistry::default();
77 let importers = importer_registry
78 .register_all(options.common.importers, options.common.load_paths)
79 .collect();
80 if let Some(l) = options.common.logger {
81 logger_registry.register(l);
82 }
83
84 #[cfg(feature = "legacy")]
85 let importer = if let Some(input_importer) = options.input_importer {
86 Some(importer_registry.register(input_importer))
87 } else if matches!(&options.url, Some(u) if u.to_string() == LEGACY_IMPORTER_PROTOCOL)
88 {
89 Some(compile_request::Importer {
90 importer: Some(compile_request::importer::Importer::Path(
91 std::env::current_dir()
92 .unwrap()
93 .to_str()
94 .unwrap()
95 .to_string(),
96 )),
97 })
98 } else {
99 None
100 };
101
102 #[cfg(feature = "legacy")]
103 let url = options
104 .url
105 .map(|url| url.to_string())
106 .filter(|url| url != LEGACY_IMPORTER_PROTOCOL)
107 .unwrap_or_default();
108
109 #[cfg(not(feature = "legacy"))]
110 let importer = options
111 .input_importer
112 .map(|i| importer_registry.register(i));
113
114 #[cfg(not(feature = "legacy"))]
115 let url = options.url.map(|url| url.to_string()).unwrap_or_default();
116
117 let request = CompileRequest {
118 style: options.common.style as i32,
119 source_map: options.common.source_map,
120 alert_color: options
121 .common
122 .alert_color
123 .unwrap_or_else(|| atty::is(Stream::Stdout)),
124 alert_ascii: options.common.alert_ascii,
125 verbose: options.common.verbose,
126 quiet_deps: options.common.quiet_deps,
127 source_map_include_sources: options.common.source_map_include_sources,
128 charset: options.common.charset,
129 importers,
130 input: Some(Input::String(StringInput {
131 source: source.into(),
132 url,
133 syntax: options.syntax as i32,
134 importer,
135 })),
136 ..Default::default()
139 };
140
141 let host = Host::new(importer_registry, logger_registry);
142 let conn = self.channel.connect(host);
143 let response = conn.compile_request(request)?;
144 CompileResult::try_from(response)
145 }
146
147 pub fn info(&mut self) -> Result<String> {
148 let logger_registry = LoggerRegistry::default();
149 let importer_registry = ImporterRegistry::default();
150 let host = Host::new(importer_registry, logger_registry);
151 let conn = self.channel.connect(host);
152 let response = conn.version_request()?;
153 Ok(format!(
154 "sass-embedded\t#{}",
155 response.implementation_version
156 ))
157 }
158}