Skip to main content

stylex_evaluator/
common.rs

1use std::collections::hash_map::DefaultHasher;
2use std::hash::{Hash, Hasher};
3use std::path::PathBuf;
4
5use radix_fmt::radix;
6use stylex_macros::stylex_panic;
7use swc_core::ecma::{
8  ast::{BinaryOp, Expr, VarDeclarator},
9  utils::drop_span,
10};
11
12pub fn create_hash(value: &str) -> String {
13  radix(murmur2::murmur2(value.as_bytes(), 1), 36).to_string()
14}
15
16pub fn wrap_key_in_quotes(key: &str, should_wrap_in_quotes: bool) -> String {
17  if should_wrap_in_quotes {
18    format!("\"{}\"", key)
19  } else {
20    key.to_string()
21  }
22}
23
24pub fn get_expr_from_var_decl(var_decl: &VarDeclarator) -> &Expr {
25  match &var_decl.init {
26    Some(var_decl_init) => var_decl_init,
27    None => stylex_panic!("Variable declaration must be initialized with an expression."),
28  }
29}
30
31pub fn evaluate_bin_expr(op: BinaryOp, left: f64, right: f64) -> f64 {
32  match &op {
33    BinaryOp::Add => left + right,
34    BinaryOp::Sub => left - right,
35    BinaryOp::Div => left / right,
36    BinaryOp::Mul => left * right,
37    BinaryOp::Mod => left % right,
38    BinaryOp::Exp => left.powf(right),
39    BinaryOp::BitOr => (left as i64 | right as i64) as f64,
40    BinaryOp::BitXor => (left as i64 ^ right as i64) as f64,
41    BinaryOp::BitAnd => (left as i64 & right as i64) as f64,
42    BinaryOp::LShift => ((left as i64) << (right as u64)) as f64,
43    BinaryOp::RShift => ((left as i64) >> (right as u64)) as f64,
44    BinaryOp::ZeroFillRShift => ((left as u64) >> (right as u64)) as f64,
45    _ => stylex_panic!("Unsupported binary operator: {:?}", op),
46  }
47}
48
49pub fn hash_f64(value: f64) -> u64 {
50  let bits = value.to_bits();
51  let mut hasher = DefaultHasher::new();
52  bits.hash(&mut hasher);
53  hasher.finish()
54}
55
56pub fn round_f64(value: f64, decimal_places: u32) -> f64 {
57  let multiplier = 10f64.powi(decimal_places as i32);
58  (value * multiplier).round() / multiplier
59}
60
61pub fn normalize_expr(expr: &mut Expr) -> &mut Expr {
62  match expr {
63    Expr::Paren(paren) => normalize_expr(paren.expr.as_mut()),
64    _ => {
65      *expr = drop_span(expr.clone());
66      expr
67    },
68  }
69}
70
71pub fn sort_numbers_factory() -> impl FnMut(&f64, &f64) -> std::cmp::Ordering {
72  |a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)
73}
74
75pub fn char_code_at(s: &str, index: usize) -> Option<u32> {
76  s.chars().nth(index).map(|c| c as u32)
77}
78
79pub fn stable_hash<T: Hash>(t: &T) -> u64 {
80  let mut hasher = DefaultHasher::new();
81  t.hash(&mut hasher);
82  hasher.finish()
83}
84
85pub fn find_and_swap_remove<T, F>(vec: &mut Vec<T>, predicate: F) -> Option<T>
86where
87  F: FnMut(&T) -> bool,
88{
89  vec
90    .iter()
91    .position(predicate)
92    .map(|index| vec.swap_remove(index))
93}
94
95pub fn create_short_hash(value: &str) -> String {
96  let hash = murmur2::murmur2(value.as_bytes(), 1) % (62u32.pow(5));
97  base62::encode(hash)
98}
99
100pub fn resolve_node_package_path(package_name: &str) -> Result<PathBuf, String> {
101  match node_resolve::Resolver::default()
102    .with_basedir(PathBuf::from("./cwd"))
103    .preserve_symlinks(true)
104    .with_extensions([".ts", ".tsx", ".js", ".jsx", ".json"])
105    .with_main_fields(vec![String::from("main"), String::from("module")])
106    .resolve(package_name)
107  {
108    Ok(path) => Ok(path),
109    Err(error) => Err(format!(
110      "Error resolving package {}: {:?}",
111      package_name, error
112    )),
113  }
114}