sass_rs/bindings/
context.rs1use std::ffi;
5use std::sync::{Arc, RwLock};
6use std::path::Path;
7use libc::strdup;
8
9use sass_sys;
10use bindings::util;
11use bindings::ptr::Unique;
12use options::{OutputStyle, Options};
13use bindings::SassOptions;
14
15
16pub struct SassContext {
17 pub raw: Unique<sass_sys::Sass_Context>,
19 pub options: Arc<RwLock<SassOptions>>
20}
21
22pub struct SassFileContext {
23 context: Unique<sass_sys::Sass_File_Context>,
25 pub sass_context: SassContext
26}
27
28pub struct SassDataContext {
29 context: Unique<sass_sys::Sass_Data_Context>,
31 pub sass_context: SassContext
32}
33
34pub enum Context {
35 File(SassFileContext),
36 Data(SassDataContext),
37}
38
39
40impl Context {
41 fn make_sass_context(c_sass_context: *mut sass_sys::Sass_Context) -> SassContext {;
42 let options = unsafe { sass_sys::sass_context_get_options(c_sass_context) };
43 let sass_options = Arc::new(RwLock::new(SassOptions {
44 raw: unsafe { Unique::new(options) }
45 }));
46
47 SassContext {
48 raw: unsafe { Unique::new(c_sass_context) },
49 options: sass_options
50 }
51 }
52
53 pub fn new_data(data: &str) -> Context {
54 let c_str = ffi::CString::new(data).unwrap();
55 let data_context = unsafe { sass_sys::sass_make_data_context(strdup(c_str.as_ptr())) };
56 let data_sass_context = unsafe { sass_sys::sass_data_context_get_context(data_context) };
57 let sass_context = Context::make_sass_context(data_sass_context);
58
59 Context::Data(SassDataContext {
60 context: unsafe { Unique::new(data_context) },
61 sass_context,
62 })
63 }
64
65 pub fn new_file<P: AsRef<Path>>(path: P) -> Result<Context, String> {
66 let c_str = ffi::CString::new(
67 path.as_ref().to_str().ok_or_else(|| "str conversation failed".to_string())?
68 ).map_err(|e| format!("Failed to create CString: {}", e))?;
69 let file_context = unsafe { sass_sys::sass_make_file_context(c_str.as_ptr()) };
70 let file_sass_context = unsafe { sass_sys::sass_file_context_get_context(file_context) };
71 let sass_context = Context::make_sass_context(file_sass_context);
72
73 Ok(Context::File(SassFileContext {
74 context: unsafe { Unique::new(file_context) },
75 sass_context,
76 }))
77 }
78
79 pub fn set_options(&mut self, options: Options) {
80 let mut sass_options = match *self {
81 Context::File(ref mut s) => {
82 (*s.sass_context.options).write().unwrap()
83 },
84 Context::Data(ref mut s) => {
85 (*s.sass_context.options).write().unwrap()
86 },
87 };
88 sass_options.set_output_style(options.output_style);
89 sass_options.set_precision(options.precision);
90 if options.indented_syntax {
91 sass_options.set_is_indented_syntax();
92 }
93 if !options.include_paths.is_empty() {
94 sass_options.set_include_path(options.include_paths);
95 }
96 }
97
98 pub fn compile(&mut self) -> Result<String, String> {
99 let ctx_out = match *self {
100 Context::File(ref mut s) => unsafe {
101 sass_sys::sass_compile_file_context(s.context.get_mut());
102 s.sass_context.raw.get_mut()
103 },
104 Context::Data(ref mut s) => unsafe {
105 sass_sys::sass_compile_data_context(s.context.get_mut());
106 s.sass_context.raw.get_mut()
107 },
108 };
109
110 let error_status = unsafe { sass_sys::sass_context_get_error_status(ctx_out) };
111 let error_message = unsafe { sass_sys::sass_context_get_error_message(ctx_out) };
112 let output_string = unsafe { sass_sys::sass_context_get_output_string(ctx_out) };
113
114 if error_status != 0 {
115 if !error_message.is_null() {
116 Result::Err(util::to_string(error_message))
117 } else {
118 Result::Err("An error occurred; no error message available.".to_string())
119 }
120 } else {
121 Result::Ok(util::to_string(output_string))
122 }
123 }
124
125 pub fn set_output_style(&mut self, output_style: OutputStyle) {
126 match *self {
127 Context::File(ref mut s) => {
128 let mut options = (*s.sass_context.options).write().unwrap();
129 options.set_output_style(output_style);
130 },
131 Context::Data(ref mut s) => {
132 let mut options = (*s.sass_context.options).write().unwrap();
133 options.set_output_style(output_style);
134 },
135 };
136 }
137}
138
139impl Drop for Context {
140 fn drop(&mut self) {
141 match *self {
142 Context::File(ref mut s) => unsafe {
143 sass_sys::sass_delete_file_context(s.context.get_mut())
144 },
145 Context::Data(ref mut s) => unsafe {
146 sass_sys::sass_delete_data_context(s.context.get_mut())
147 },
148 };
149 }
150}