winereg 0.1.0

Rust library for parsing, writing, diffing, patching, and scripting Wine/Windows registry files.
Documentation
use std::fmt;

#[allow(dead_code)]
pub const REG_NONE: u32 = 0;
pub const REG_SZ: u32 = 1;
pub const REG_EXPAND_SZ: u32 = 2;
pub const REG_BINARY: u32 = 3;
pub const REG_DWORD: u32 = 4;
#[allow(dead_code)]
pub const REG_LINK: u32 = 6;
pub const REG_MULTI_SZ: u32 = 7;
pub const REG_QWORD: u32 = 11;

#[derive(Debug, Clone, PartialEq)]
pub enum RegistryValueData {
    String(String),
    ExpandString(String),
    MultiString(Vec<String>),
    Dword(u32),
    Qword(u64),
    Binary(Vec<u8>, u32),
}

#[derive(Debug, Clone, PartialEq)]
pub struct RegistryValue {
    pub name: String,
    pub data: RegistryValueData,
}

impl RegistryValue {
    pub fn new(name: impl Into<String>, data: RegistryValueData) -> Self {
        Self {
            name: name.into(),
            data,
        }
    }

    pub fn reg_type(&self) -> u32 {
        match self.data {
            RegistryValueData::String(_) => REG_SZ,
            RegistryValueData::ExpandString(_) => REG_EXPAND_SZ,
            RegistryValueData::MultiString(_) => REG_MULTI_SZ,
            RegistryValueData::Dword(_) => REG_DWORD,
            RegistryValueData::Qword(_) => REG_QWORD,
            RegistryValueData::Binary(_, ty) => ty,
        }
    }

    pub fn raw_bytes(&self) -> Vec<u8> {
        match &self.data {
            RegistryValueData::String(v) | RegistryValueData::ExpandString(v) => {
                let mut bytes = v.encode_utf16().flat_map(|c| c.to_le_bytes()).collect::<Vec<_>>();
                bytes.extend_from_slice(&[0, 0]);
                bytes
            }
            RegistryValueData::MultiString(values) => {
                let mut bytes = Vec::new();
                for part in values {
                    bytes.extend(part.encode_utf16().flat_map(|c| c.to_le_bytes()));
                    bytes.extend_from_slice(&[0, 0]);
                }
                bytes.extend_from_slice(&[0, 0]);
                bytes
            }
            RegistryValueData::Dword(v) => v.to_le_bytes().to_vec(),
            RegistryValueData::Qword(v) => v.to_le_bytes().to_vec(),
            RegistryValueData::Binary(v, _) => v.clone(),
        }
    }
}

impl fmt::Display for RegistryValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self.data {
            RegistryValueData::String(v) => write!(f, "string:\"{}\"", v),
            RegistryValueData::ExpandString(v) => write!(f, "expand_string:\"{}\"", v),
            RegistryValueData::MultiString(v) => write!(f, "multi_string:{:?}", v),
            RegistryValueData::Dword(v) => write!(f, "dword:{:#010x}", v),
            RegistryValueData::Qword(v) => write!(f, "qword:{:#018x}", v),
            RegistryValueData::Binary(v, t) => write!(f, "hex({}):{}", t, v.len()),
        }
    }
}