ronantakizawa/codereview-bench huggingface dataset:
Repository: awslabs/llrt
File: modules/llrt_assert/src/lib.rs (Rust)

Code before:
    match value.type_of() {
        Type::Bool => {
            if value.as_bool().unwrap() {
                return Ok(());
            }
        },
        Type::Float | Type::Int => {
            if value.as_number().unwrap() != 0.0 {
                return Ok(());
            }
        },
        Type::String => {
            if !value.as_string().unwrap().to_string().unwrap().is_empty() {
                return Ok(());
            }
        },
        Type::Array | Type::Object => {
            return Ok(());
        },
        _ => {},
    }

    if let Some(obj) = message.0 {
        match obj.type_of() {
            Type::String => {
                let msg = obj.as_string().unwrap().to_string().unwrap();
                return Err(Exception::throw_message(&ctx, &msg));
            },
            Type::Exception => return Err(obj.as_exception().cloned().unwrap().throw()),
            _ => {},
        };
    }

    Err(Exception::throw_message(
        &ctx,
        "The expression was evaluated to a falsy value",
    ))
}

pub struct AssertModule;

impl ModuleDef for AssertModule {
    fn declare(declare: &Declarations) -> Result<()> {
        declare.declare("ok")?;

        declare.declare("default")?;
        Ok(())
    }

    fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> {
        let ok_function = Function::new(ctx.clone(), ok)?.with_name("ok")?;

Review comment (suggestion):
Some missing cases. What about `constructor`,`function`, `bigint`, `symbol`, `Exception`.

Code after:
    match value.type_of() {
        Type::Bool => {
            if value.as_bool().unwrap() {
                return Ok(());
            }
        },
        Type::Float | Type::Int => {
            if value.as_number().unwrap() != 0.0 {
                return Ok(());
            }
        },
        Type::String => {
            if !value.as_string().unwrap().to_string().unwrap().is_empty() {
                return Ok(());
            }
        },
        Type::Array
        | Type::BigInt
        | Type::Constructor
        | Type::Exception
        | Type::Function
        | Type::Symbol
        | Type::Object => {
            return Ok(());
        },
        _ => {},
    }

    if let Some(obj) = message.0 {
        match obj.type_of() {
            Type::String => {
                let msg = obj.as_string().unwrap().to_string().unwrap();
                return Err(Exception::throw_message(&ctx, &msg));
            },
            Type::Exception => return Err(obj.as_exception().cloned().unwrap().throw()),
            _ => {},
        };
    }

    Err(Exception::throw_message(
        &ctx,
        "AssertionError: The expression was evaluated to a falsy value",
    ))
}

pub struct AssertModule;

impl ModuleDef for AssertModule {
    fn declare(declare: &Declarations) -> Result<()> {
        declare.declare("ok")?;
Repository: awslabs/llrt
File: modules/llrt_assert/src/lib.rs (Rust)

Code before:
            return Ok(());
        },
        _ => {},
    }

    if let Some(obj) = message.0 {
        match obj.type_of() {
            Type::String => {
                let msg = obj.as_string().unwrap().to_string().unwrap();
                return Err(Exception::throw_message(&ctx, &msg));
            },
            Type::Exception => return Err(obj.as_exception().cloned().unwrap().throw()),
            _ => {},
        };
    }

    Err(Exception::throw_message(
        &ctx,
        "The expression was evaluated to a falsy value",
    ))
}

pub struct AssertModule;

impl ModuleDef for AssertModule {
    fn declare(declare: &Declarations) -> Result<()> {
        declare.declare("ok")?;

        declare.declare("default")?;
        Ok(())
    }

    fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> {
        let ok_function = Function::new(ctx.clone(), ok)?.with_name("ok")?;
        ok_function.set("ok", ok_function.clone())?;

        exports.export("ok", ok_function.clone())?;
        exports.export("default", ok_function)?;
        Ok(())
    }
}

impl From<AssertModule> for ModuleInfo<AssertModule> {
    fn from(val: AssertModule) -> Self {
        ModuleInfo {
            name: "assert",
            module: val,
        }
    }
}


Review comment (suggestion):
Ideally we should ha an `AssertionError` but that can be added later. It might be good to show wha the value was by coercing it to string

Code after:
        | Type::BigInt
        | Type::Constructor
        | Type::Exception
        | Type::Function
        | Type::Symbol
        | Type::Object => {
            return Ok(());
        },
        _ => {},
    }

    if let Some(obj) = message.0 {
        match obj.type_of() {
            Type::String => {
                let msg = obj.as_string().unwrap().to_string().unwrap();
                return Err(Exception::throw_message(&ctx, &msg));
            },
            Type::Exception => return Err(obj.as_exception().cloned().unwrap().throw()),
            _ => {},
        };
    }

    Err(Exception::throw_message(
        &ctx,
        "AssertionError: The expression was evaluated to a falsy value",
    ))
}

pub struct AssertModule;

impl ModuleDef for AssertModule {
    fn declare(declare: &Declarations) -> Result<()> {
        declare.declare("ok")?;

        declare.declare("default")?;
        Ok(())
    }

    fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> {
        let ok_function = Function::new(ctx.clone(), ok)?.with_name("ok")?;
        ok_function.set("ok", ok_function.clone())?;

        exports.export("ok", ok_function.clone())?;
        exports.export("default", ok_function)?;
        Ok(())
    }
}

impl From<AssertModule> for ModuleInfo<AssertModule> {
    fn from(val: AssertModule) -> Self {
        ModuleInfo {
Repository: awslabs/llrt
File: modules/llrt_tty/src/lib.rs (Rust)

Code before:
mod tests {
    use crate::TtyModule;
    use llrt_test::{call_test, test_async_with, ModuleEvaluator};

    #[tokio::test]
    async fn test_isatty() {
        test_async_with(|ctx| {
            Box::pin(async move {
                ModuleEvaluator::eval_rust::<TtyModule>(ctx.clone(), "tty")
                    .await
                    .unwrap();

                let module = ModuleEvaluator::eval_js(
                    ctx.clone(),
                    "test",
                    r#"
                        import { isatty } from 'tty';

                        export async function test() {
                            return new Array(5).fill(0).map((_, i) => +isatty(i)).join('')
                        }
                    "#,
                )
                .await
                .unwrap();
                let expect = if std::env::var("GITHUB_ACTIONS").unwrap_or_default() == "true" {
                    "00000"
                } else {
                    "11100"
                };
                let result = call_test::<String, _>(&ctx, &module, ()).await;
                assert_eq!(result, expect);
            })
        })
        .await;
    }
}


Review comment (suggestion):
We can't hard code GITHUB_ACTIONS to test this. Better would be to run the `test -t` command as a subcommand and test this on posix only for now. See comment

Code after:
mod tests {
    use crate::TtyModule;
    use llrt_test::{call_test, test_async_with, ModuleEvaluator};
    use std::io::{stderr, stdin, stdout, IsTerminal};

    #[tokio::test]
    async fn test_isatty() {
        test_async_with(|ctx| {
            Box::pin(async move {
                ModuleEvaluator::eval_rust::<TtyModule>(ctx.clone(), "tty")
                    .await
                    .unwrap();

                let module = ModuleEvaluator::eval_js(
                    ctx.clone(),
                    "test",
                    r#"
                        import { isatty } from 'tty';

                        export async function test() {
                            return new Array(3).fill(0).map((_, i) => +isatty(i)).join('')
                        }
                    "#,
                )
                .await
                .unwrap();
                let expect = [
                    stdin().is_terminal(),
                    stdout().is_terminal(),
                    stderr().is_terminal(),
                ]
                .map(|i| (i as u8).to_string())
                .join("");
                let result = call_test::<String, _>(&ctx, &module, ()).await;
                assert_eq!(result, expect);
            })
        })
        .await;
    }
}
Repository: awslabs/llrt
File: llrt_core/src/module_loader/mod.rs (Rust)

Code before:
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use std::env;

use once_cell::sync::Lazy;

use crate::environment;

pub mod loader;
pub mod resolver;

// added when .cjs files are imported
pub const CJS_IMPORT_PREFIX: &str = "__cjs:";
// added to force CJS imports in loader
pub const CJS_LOADER_PREFIX: &str = "__cjsm:";

pub static LLRT_PLATFORM: Lazy<String> = Lazy::new(|| {
    let platform =
        env::var(environment::ENV_LLRT_PLATFORM).unwrap_or_else(|_| "browser".to_string());
    if platform == "node" {
        "node".to_string()
    } else {
        "browser".to_string()
    }
});


Review comment (suggestion):
```rust
pub static LLRT_PLATFORM: Lazy<String> = Lazy::new(|| {
    env::var(environment::ENV_LLRT_PLATFORM)
        .ok()
        .filter(|platform| platform == "node")
        .unwrap_or_else(|| "browser".to_string())
});
```

Code after:
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use std::env;

use once_cell::sync::Lazy;

use crate::environment;

pub mod loader;
pub mod resolver;

// added when .cjs files are imported
pub const CJS_IMPORT_PREFIX: &str = "__cjs:";
// added to force CJS imports in loader
pub const CJS_LOADER_PREFIX: &str = "__cjsm:";

pub static LLRT_PLATFORM: Lazy<String> = Lazy::new(|| {
    env::var(environment::ENV_LLRT_PLATFORM)
        .ok()
        .filter(|platform| platform == "node")
        .unwrap_or_else(|| "browser".to_string())
});
Repository: awslabs/llrt
File: modules/llrt_buffer/src/buffer.rs (Rust)

Code before:
    }

    if value.is_array() {
        let array = value.as_array().unwrap();

        for val in array.iter::<u8>() {
            val.or_throw_msg(&ctx, "array value is not u8")?;
        }

        return Ok(array.len());
    }

    if let Some(obj) = value.as_object() {
        if let Some(ob) = ObjectBytes::from_array_buffer(obj)? {
            return Ok(ob.as_bytes().len());
        }
    }

    Err(Exception::throw_message(
        &ctx,
        "value must be typed DataView, Buffer, ArrayBuffer, Uint8Array or string",
    ))
}

fn is_buffer<'js>(ctx: Ctx<'js>, value: Value<'js>) -> Result<bool> {
    let class: Function = ctx.globals().get(stringify!(Buffer))?;
    if let Some(object) = value.as_object() {
        return Ok(object.is_instance_of(class));
    }

    Ok(false)
}

fn is_encoding(value: Value) -> Result<bool> {
    if let Some(js_string) = value.as_string() {
        if let Ok(std_string) = js_string.to_string() {
            return Ok(Encoder::from_str(std_string.as_str()).is_ok());
        }
    }

    Ok(false)
}

fn to_string(this: This<Object<'_>>, ctx: Ctx, encoding: Opt<String>) -> Result<String> {
    let typed_array = TypedArray::<u8>::from_object(this.0)?;
    let bytes: &[u8] = typed_array.as_ref();

    let encoder = Encoder::from_optional_str(encoding.as_deref()).or_throw(&ctx)?;
    encoder.encode_to_string(bytes, true).or_throw(&ctx)
}


Review comment (suggestion):
Use primordials here:
```rust
let constructor = BufferPrimordials::get(ctx)?.consturctor
```

Code after:
    }

    if value.is_array() {
        let array = value.as_array().unwrap();

        for val in array.iter::<u8>() {
            val.or_throw_msg(&ctx, "array value is not u8")?;
        }

        return Ok(array.len());
    }

    if let Some(obj) = value.as_object() {
        if let Some(ob) = ObjectBytes::from_array_buffer(obj)? {
            return Ok(ob.as_bytes().len());
        }
    }

    Err(Exception::throw_message(
        &ctx,
        "value must be typed DataView, Buffer, ArrayBuffer, Uint8Array or string",
    ))
}

fn is_buffer<'js>(ctx: Ctx<'js>, value: Value<'js>) -> Result<bool> {
    if let Some(object) = value.as_object() {
        let constructor = BufferPrimordials::get(&ctx)?;
        return Ok(object.is_instance_of(&constructor.constructor));
    }

    Ok(false)
}

fn is_encoding(value: Value) -> Result<bool> {
    if let Some(js_string) = value.as_string() {
        let std_string = js_string.to_string()?;
        return Ok(Encoder::from_str(std_string.as_str()).is_ok());
    }

    Ok(false)
}

fn to_string(this: This<Object<'_>>, ctx: Ctx, encoding: Opt<String>) -> Result<String> {
    let typed_array = TypedArray::<u8>::from_object(this.0)?;
    let bytes: &[u8] = typed_array.as_ref();

    let encoder = Encoder::from_optional_str(encoding.as_deref()).or_throw(&ctx)?;
    encoder.encode_to_string(bytes, true).or_throw(&ctx)
}

fn subarray<'js>(
Repository: awslabs/llrt
File: modules/llrt_crypto/src/sha_hash.rs (Rust)

Code before:
    }
}

#[rquickjs::class]
#[derive(rquickjs::class::Trace, rquickjs::JsLifetime)]
pub struct ShaHash {
    #[qjs(skip_trace)]
    secret: Option<Vec<u8>>,
    #[qjs(skip_trace)]
    bytes: Vec<u8>,
    #[qjs(skip_trace)]
    algorithm: ShaAlgorithm,
}

#[rquickjs::methods]
impl ShaHash {
    #[qjs(skip)]
    pub fn new<'js>(
        ctx: &Ctx<'js>,
        algorithm: ShaAlgorithm,
        secret: Opt<ObjectBytes<'js>>,
    ) -> Result<Self> {
        let secret = secret
            .0
            .map(|bytes| bytes.into_bytes(ctx))
            .and_then(|res| res.ok());

        Ok(ShaHash {
            secret,
            bytes: Vec::new(),
            algorithm,
        })
    }

    #[qjs(skip)]
    pub fn default(algorithm: ShaAlgorithm) -> Result<Self> {
        Ok(ShaHash {
            secret: None,
            bytes: Vec::new(),
            algorithm,
        })
    }

    #[qjs(rename = "digest")]
    fn sha_digest<'js>(&self, ctx: Ctx<'js>) -> Result<Value<'js>> {
        if let Some(secret) = &self.secret {
            let key_value = secret;
            let key = hmac::Key::new(*self.algorithm.hmac_algorithm(), key_value);

            return bytes_to_typed_array(ctx, hmac::sign(&key, &self.bytes).as_ref());
        }

Review comment (suggestion):
That is effectively silencing the error which is likely not what we want use transpose instead and return the error

Code after:
    }
}

#[rquickjs::class]
#[derive(rquickjs::class::Trace, rquickjs::JsLifetime)]
pub struct ShaHash {
    #[qjs(skip_trace)]
    secret: Option<Vec<u8>>,
    #[qjs(skip_trace)]
    bytes: Vec<u8>,
    #[qjs(skip_trace)]
    algorithm: ShaAlgorithm,
}

#[rquickjs::methods]
impl ShaHash {
    #[qjs(skip)]
    pub fn new(ctx: Ctx, algorithm: ShaAlgorithm, secret: Opt<ObjectBytes<'_>>) -> Result<Self> {
        let secret = secret.0.map(|bytes| bytes.into_bytes(&ctx)).transpose()?;

        Ok(ShaHash {
            secret,
            bytes: Vec::new(),
            algorithm,
        })
    }

    #[qjs(rename = "digest")]
    fn sha_digest<'js>(&self, ctx: Ctx<'js>) -> Result<Value<'js>> {
        if let Some(secret) = &self.secret {
            let key_value = secret;
            let key = hmac::Key::new(*self.algorithm.hmac_algorithm(), key_value);

            return bytes_to_typed_array(ctx, hmac::sign(&key, &self.bytes).as_ref());
        }

        bytes_to_typed_array(
            ctx,
            digest::digest(self.algorithm.digest_algorithm(), &self.bytes).as_ref(),
        )
    }

    #[qjs(rename = "update")]
    fn sha_update<'js>(
        this: This<Class<'js, Self>>,
        ctx: Ctx<'js>,
        bytes: ObjectBytes<'js>,
    ) -> Result<Class<'js, Self>> {
        this.0.borrow_mut().bytes = bytes.try_into().or_throw(&ctx)?;
        Ok(this.0)
    }
Repository: awslabs/llrt
File: modules/llrt_util/src/text_decoder.rs (Rust)

Code before:

    #[qjs(get)]
    fn encoding(&self) -> &str {
        self.encoder.as_label()
    }

    #[qjs(get)]
    fn fatal(&self) -> bool {
        self.fatal
    }

    #[qjs(get, rename = "ignoreBOM")]
    fn ignore_bom(&self) -> bool {
        self.ignore_bom
    }

    pub fn decode(&self, ctx: Ctx<'js>, bytes: ObjectBytes<'js>) -> Result<String> {
        let bytes = bytes.as_bytes(&ctx)?;
        let start_pos = if !self.ignore_bom {
            match bytes.get(..3) {
                Some([0xFF, 0xFE, ..]) if self.encoder == Encoder::Utf16le => 2,
                Some([0xFE, 0xFF, ..]) if self.encoder == Encoder::Utf16be => 2,
                Some([0xEF, 0xBB, 0xBF]) if self.encoder == Encoder::Utf8 => 3,
                _ => 0,
            }
        } else {
            0
        };

        self.encoder
            .encode_to_string(&bytes[start_pos..], !self.fatal)
            .or_throw_type(&ctx, "")
    }
}


Review comment (suggestion):
I think we can rewrite this entire snippet as:
```rust
let start_pos = if !self.ignore_bom {
    match (self.encoder, bytes) {
        (Encoder::Utf16le, [0xFF, 0xFE, ..]) => 2,
        (Encoder::Utf16be, [0xFE, 0xFF, ..]) => 2,
        (Encoder::Utf8, [0xEF, 0xBB, 0xBF, ..]) => 3,
        _ => 0,
    }
} else {
    0
};
```

Code after:

    #[qjs(get)]
    fn encoding(&self) -> &str {
        self.encoder.as_label()
    }

    #[qjs(get)]
    fn fatal(&self) -> bool {
        self.fatal
    }

    #[qjs(get, rename = "ignoreBOM")]
    fn ignore_bom(&self) -> bool {
        self.ignore_bom
    }

    pub fn decode(&self, ctx: Ctx<'js>, bytes: ObjectBytes<'js>) -> Result<String> {
        let bytes = bytes.as_bytes(&ctx)?;
        let start_pos = if !self.ignore_bom {
            match (&self.encoder, bytes.get(..3)) {
                (Encoder::Utf16le, Some([0xFF, 0xFE, ..])) => 2,
                (Encoder::Utf16be, Some([0xFE, 0xFF, ..])) => 2,
                (Encoder::Utf8, Some([0xEF, 0xBB, 0xBF])) => 3,
                _ => 0,
            }
        } else {
            0
        };

        self.encoder
            .encode_to_string(&bytes[start_pos..], !self.fatal)
            .or_throw_type(&ctx, "")
    }
}
Repository: awslabs/llrt
File: llrt/src/minimal_tracer.rs (Rust)

Code before:
        false
    }

    fn new_span(&self, _span: &span::Attributes<'_>) -> span::Id {
        Id::from_u64(AUTO_ID.fetch_add(1, Ordering::Relaxed) as u64)
    }

    fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}

    fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}

    fn event(&self, event: &tracing::Event<'_>) {
        let metadata = event.metadata();

        let level = metadata.level();
        let target = metadata.target();

        let mut text = String::new();

        let mut visitor = StringVisitor::new(&mut text);
        event.record(&mut visitor);

        let current_time = Timestamp::now();
        let timestamp = current_time.strftime("%Y-%m-%dT%H:%M:%S%.3fZ");

        println!("{timestamp} {level} {target}: {text}");
    }

    fn enter(&self, _span: &span::Id) {}

    fn exit(&self, _span: &span::Id) {}
}


Review comment (suggestion):
```suggestion
println!("{timestamp:.3} {level} {target}: {text}");
```

Code after:
        false
    }

    fn new_span(&self, _span: &span::Attributes<'_>) -> span::Id {
        Id::from_u64(AUTO_ID.fetch_add(1, Ordering::Relaxed) as u64)
    }

    fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}

    fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}

    fn event(&self, event: &tracing::Event<'_>) {
        let metadata = event.metadata();

        let level = metadata.level();
        let target = metadata.target();

        let mut text = String::new();

        let mut visitor = StringVisitor::new(&mut text);
        event.record(&mut visitor);

        let timestamp = Timestamp::now();

        println!("{timestamp:.3} {level} {target}: {text}");
    }

    fn enter(&self, _span: &span::Id) {}

    fn exit(&self, _span: &span::Id) {}
}
Repository: basecamp/omarchy
File: install/config/powerprofilesctl-rules.sh (Shell)

Code before:
battery_present() {
  for bat in /sys/class/power_supply/BAT*; do
    [[ -r "$bat/present" ]] &&
    [[ "$(cat "$bat/present")" == "1" ]] &&
    [[ "$(cat "$bat/type")" == "Battery" ]] &&
    return 0
  done
  return 1
}

if battery_present; then
  sudo mkdir -p /etc/udev/rules.d

  cat <<'EOF' | sudo tee "/etc/udev/rules.d/99-power-profile.rules"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="0", RUN+="/usr/bin/powerprofilesctl set power-saver"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="1", RUN+="/usr/bin/powerprofilesctl set balanced"
EOF
  sudo udevadm control --reload
fi


Review comment (refactor):
Think we should extract this into `omarchy-battery-present` since we use a similar check in a few other places.

Code after:
if omarchy-battery-present; then
  mapfile -t profiles < <(omarchy-powerprofiles-list)

  if [[ ${#profiles[@]} -gt 0 ]]; then

    # Default AC profile:
    # 3 profiles → performance
    # 2 profiles → balanced
    # 1 profile  → profiles[0]
    ac_profile="${profiles[2]:-${profiles[1]:-${profiles[0]}}}"

    # Default Battery profile:
    # 3 profiles → balanced
    # 2 profiles → balanced
    # 1 profile  → profiles[0]
    battery_profile="${profiles[1]:-${profiles[0]}}"

    cat <<EOF | sudo tee "/etc/udev/rules.d/99-power-profile.rules"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="0", RUN+="/usr/bin/powerprofilesctl set $battery_profile"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="1", RUN+="/usr/bin/powerprofilesctl set $ac_profile"
EOF

    sudo udevadm control --reload
    sudo udevadm trigger --subsystem-match=power_supply
  fi
fi
Repository: basecamp/omarchy
File: install/config/powerprofilesctl-rules.sh (Shell)

Code before:
battery_present() {
  for bat in /sys/class/power_supply/BAT*; do
    [[ -r "$bat/present" ]] &&
    [[ "$(cat "$bat/present")" == "1" ]] &&
    [[ "$(cat "$bat/type")" == "Battery" ]] &&
    return 0
  done
  return 1
}

if battery_present; then
  sudo mkdir -p /etc/udev/rules.d

  cat <<'EOF' | sudo tee "/etc/udev/rules.d/99-power-profile.rules"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="0", RUN+="/usr/bin/powerprofilesctl set power-saver"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="1", RUN+="/usr/bin/powerprofilesctl set balanced"
EOF
  sudo udevadm control --reload
fi


Review comment (performance):
I'd rather see a default where we're running in balanced on battery, but performance (when available) on mains. Not all laptops have the performance setting, though?

Code after:
if omarchy-battery-present; then
  mapfile -t profiles < <(omarchy-powerprofiles-list)

  if [[ ${#profiles[@]} -gt 0 ]]; then

    # Default AC profile:
    # 3 profiles → performance
    # 2 profiles → balanced
    # 1 profile  → profiles[0]
    ac_profile="${profiles[2]:-${profiles[1]:-${profiles[0]}}}"

    # Default Battery profile:
    # 3 profiles → balanced
    # 2 profiles → balanced
    # 1 profile  → profiles[0]
    battery_profile="${profiles[1]:-${profiles[0]}}"

    cat <<EOF | sudo tee "/etc/udev/rules.d/99-power-profile.rules"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="0", RUN+="/usr/bin/powerprofilesctl set $battery_profile"
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ATTR{online}=="1", RUN+="/usr/bin/powerprofilesctl set $ac_profile"
EOF

    sudo udevadm control --reload
    sudo udevadm trigger --subsystem-match=power_supply
  fi
fi