powercap 0.3.5

Library for reading powercap files
Documentation
use std::fs;
use std::io::Result;
use std::path::Path;

fn default_socket_generator(_socket: usize) -> u64 {
    1234
}

fn default_domain_generator(_socket: usize, _domain: usize) -> u64 {
    1234
}

type SocketEnergyGenerator = Box<dyn Fn(usize) -> u64>;
type DomainEnergyGenerator = Box<dyn Fn(usize, usize) -> u64>;

pub struct MockBuilder {
    enabled: bool,
    sockets: usize,
    socket_energy_generator: SocketEnergyGenerator,
    socket_max_energy_range_generator: SocketEnergyGenerator,
    domain_energy_generator: Box<dyn Fn(usize, usize) -> u64>,
    domain_max_energy_range_generator: Box<dyn Fn(usize, usize) -> u64>,
}

impl Default for MockBuilder {
    fn default() -> Self {
        Self {
            enabled: true,
            sockets: 1,
            socket_energy_generator: Box::new(default_socket_generator),
            socket_max_energy_range_generator: Box::new(default_socket_generator),
            domain_energy_generator: Box::new(default_domain_generator),
            domain_max_energy_range_generator: Box::new(default_domain_generator),
        }
    }
}

impl MockBuilder {
    pub fn with_enabled(mut self, value: bool) -> Self {
        self.enabled = value;
        self
    }

    pub fn with_sockets(mut self, value: usize) -> Self {
        self.sockets = value;
        self
    }

    pub fn with_socket_energy_generator(mut self, value: SocketEnergyGenerator) -> Self {
        self.socket_energy_generator = value;
        self
    }

    pub fn with_socket_max_energy_range_generator(mut self, value: SocketEnergyGenerator) -> Self {
        self.socket_max_energy_range_generator = value;
        self
    }

    pub fn with_domain_energy_generator(mut self, value: DomainEnergyGenerator) -> Self {
        self.domain_energy_generator = value;
        self
    }

    pub fn with_domain_max_energy_range_generator(mut self, value: DomainEnergyGenerator) -> Self {
        self.domain_max_energy_range_generator = value;
        self
    }

    fn build_domain(&self, path: &Path, socket: usize, domain: usize, name: &str) -> Result<()> {
        fs::create_dir_all(&path)?;
        fs::write(&path.join("name"), name)?;
        fs::write(&path.join("enabled"), if self.enabled { "1" } else { "0" })?;
        fs::write(
            &path.join("energy_uj"),
            (self.domain_energy_generator)(socket, domain).to_string(),
        )?;
        fs::write(
            &path.join("max_energy_range_uj"),
            (self.domain_max_energy_range_generator)(socket, domain).to_string(),
        )?;
        Ok(())
    }

    fn build_socket(&self, path: &Path, socket: usize) -> Result<()> {
        fs::create_dir_all(&path)?;
        fs::write(&path.join("name"), format!("package-{}", socket))?;
        fs::write(&path.join("enabled"), if self.enabled { "1" } else { "0" })?;
        fs::write(
            &path.join("energy_uj"),
            (self.socket_energy_generator)(socket).to_string(),
        )?;
        fs::write(
            &path.join("max_energy_range_uj"),
            (self.socket_max_energy_range_generator)(socket).to_string(),
        )?;
        for (i, name) in ["core", "nocore", "dram"].iter().enumerate() {
            let domain_path = path.join(format!("intel-rapl:{}:{}", socket, i));
            self.build_domain(&domain_path, socket, i, name)?;
        }
        Ok(())
    }

    fn build_intel_rapl(&self, path: &Path) -> Result<()> {
        fs::create_dir_all(&path)?;
        fs::write(&path.join("enabled"), if self.enabled { "1" } else { "0" })?;
        for i in 0..self.sockets {
            let socket_path = path.join(format!("intel-rapl:{}", i));
            self.build_socket(&socket_path, i)?;
        }
        Ok(())
    }

    pub fn build(&self, path: &Path) -> Result<()> {
        let intel_rapl = path.join("intel-rapl");
        self.build_intel_rapl(&intel_rapl)
    }
}