modules/path/
path.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use std::path::{Path, PathBuf};
8
9use ion::flags::PropertyFlags;
10use ion::function::Rest;
11use ion::spec::create_property_spec_string;
12use ion::{Context, Error, Object, Result, function_spec, js_fn};
13use mozjs::jsapi::{JSFunctionSpec, JSPropertySpec};
14use runtime::module::NativeModule;
15
16#[cfg(windows)]
17const SEPARATOR: &str = "\\\0";
18#[cfg(unix)]
19const SEPARATOR: &str = "/\0";
20
21#[cfg(windows)]
22const DELIMITER: &str = ";\0";
23#[cfg(unix)]
24const DELIMITER: &str = ":\0";
25
26#[js_fn]
27fn join(Rest(segments): Rest<String>) -> String {
28	let mut path = PathBuf::new();
29	path.extend(segments.into_vec());
30	String::from(path.to_str().unwrap())
31}
32
33#[js_fn]
34fn strip_prefix(path: String, prefix: String) -> Result<String> {
35	let path = Path::new(&path);
36
37	if let Ok(path) = path.strip_prefix(&prefix) {
38		Ok(String::from(path.to_str().unwrap()))
39	} else {
40		Err(Error::new("Failed to strip prefix from path.", None))
41	}
42}
43
44#[js_fn]
45fn file_stem(path: String) -> Option<String> {
46	let path = Path::new(&path);
47	path.file_stem().map(|s| String::from(s.to_str().unwrap()))
48}
49
50#[js_fn]
51fn parent(path: String) -> Option<String> {
52	let path = Path::new(&path);
53	path.parent().map(|s| String::from(s.to_str().unwrap()))
54}
55
56#[js_fn]
57fn file_name(path: String) -> Option<String> {
58	let path = Path::new(&path);
59	path.file_name().map(|s| String::from(s.to_str().unwrap()))
60}
61
62#[js_fn]
63fn extension(path: String) -> Option<String> {
64	let path = Path::new(&path);
65	path.extension().map(|s| String::from(s.to_str().unwrap()))
66}
67
68#[js_fn]
69fn with_file_name(path: String, file_name: String) -> String {
70	let path = Path::new(&path);
71	String::from(path.with_file_name(file_name).to_str().unwrap())
72}
73
74#[js_fn]
75fn with_externsion(path: String, extension: String) -> String {
76	let path = Path::new(&path);
77	String::from(path.with_extension(extension).to_str().unwrap())
78}
79
80#[js_fn]
81fn is_absolute(path: String) -> bool {
82	Path::new(&path).is_absolute()
83}
84
85#[js_fn]
86fn is_relative(path: String) -> bool {
87	Path::new(&path).is_relative()
88}
89
90#[js_fn]
91fn has_root(path: String) -> bool {
92	Path::new(&path).has_root()
93}
94
95#[js_fn]
96fn starts_with(path: String, prefix: String) -> bool {
97	Path::new(&path).starts_with(prefix)
98}
99
100#[js_fn]
101fn ends_with(path: String, prefix: String) -> bool {
102	Path::new(&path).ends_with(prefix)
103}
104
105const FUNCTIONS: &[JSFunctionSpec] = &[
106	function_spec!(join, 0),
107	function_spec!(strip_prefix, c"stripPrefix", 2),
108	function_spec!(file_stem, c"fileStem", 1),
109	function_spec!(parent, 1),
110	function_spec!(file_name, c"fileName", 1),
111	function_spec!(extension, 1),
112	function_spec!(with_file_name, c"withFileName", 2),
113	function_spec!(with_externsion, c"withExtension", 2),
114	function_spec!(is_absolute, c"isAbsolute", 1),
115	function_spec!(is_relative, c"isRelative", 1),
116	function_spec!(has_root, c"hasRoot", 1),
117	function_spec!(starts_with, c"startsWith", 2),
118	function_spec!(ends_with, c"endsWith", 2),
119	JSFunctionSpec::ZERO,
120];
121
122const PROPERTIES: &[JSPropertySpec] = &[
123	create_property_spec_string("separator", SEPARATOR, PropertyFlags::CONSTANT_ENUMERATED),
124	create_property_spec_string("delimiter", DELIMITER, PropertyFlags::CONSTANT_ENUMERATED),
125	JSPropertySpec::ZERO,
126];
127
128pub struct PathM;
129
130impl<'cx> NativeModule<'cx> for PathM {
131	const NAME: &'static str = "path";
132	const VARIABLE_NAME: &'static str = "path";
133	const SOURCE: &'static str = include_str!("path.js");
134
135	fn module(&self, cx: &'cx Context) -> Option<Object<'cx>> {
136		let path = Object::new(cx);
137		if unsafe { path.define_methods(cx, FUNCTIONS) && path.define_properties(cx, PROPERTIES) } {
138			return Some(path);
139		}
140		None
141	}
142}