summaryrefslogtreecommitdiffstats
path: root/third_party/rust/winreg/src/types.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/winreg/src/types.rs')
-rw-r--r--third_party/rust/winreg/src/types.rs199
1 files changed, 199 insertions, 0 deletions
diff --git a/third_party/rust/winreg/src/types.rs b/third_party/rust/winreg/src/types.rs
new file mode 100644
index 0000000000..37439354eb
--- /dev/null
+++ b/third_party/rust/winreg/src/types.rs
@@ -0,0 +1,199 @@
+// Copyright 2015, Igor Shaula
+// Licensed under the MIT License <LICENSE or
+// http://opensource.org/licenses/MIT>. This file
+// may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Traits for loading/saving Registry values
+use super::enums::*;
+use super::winapi::shared::winerror;
+use super::RegValue;
+use super::{to_utf16, v16_to_v8};
+use std::ffi::{OsStr, OsString};
+use std::io;
+use std::os::windows::ffi::OsStringExt;
+use std::slice;
+
+/// A trait for types that can be loaded from registry values.
+///
+/// **NOTE:** Uses `from_utf16_lossy` when converting to `String`.
+///
+/// **NOTE:** When converting to `String` or `OsString`, trailing `NULL` characters are trimmed
+/// and line separating `NULL` characters in `REG_MULTI_SZ` are replaced by `\n`
+/// effectively representing the value as a multiline string.
+/// When converting to `Vec<String>` or `Vec<OsString>` `NULL` is used as a strings separator.
+pub trait FromRegValue: Sized {
+ fn from_reg_value(val: &RegValue) -> io::Result<Self>;
+}
+
+impl FromRegValue for String {
+ fn from_reg_value(val: &RegValue) -> io::Result<String> {
+ match val.vtype {
+ REG_SZ | REG_EXPAND_SZ | REG_MULTI_SZ => {
+ let words = unsafe {
+ #[allow(clippy::cast_ptr_alignment)]
+ slice::from_raw_parts(val.bytes.as_ptr() as *const u16, val.bytes.len() / 2)
+ };
+ let mut s = String::from_utf16_lossy(words);
+ while s.ends_with('\u{0}') {
+ s.pop();
+ }
+ if val.vtype == REG_MULTI_SZ {
+ return Ok(s.replace("\u{0}", "\n"));
+ }
+ Ok(s)
+ }
+ _ => werr!(winerror::ERROR_BAD_FILE_TYPE),
+ }
+ }
+}
+
+impl FromRegValue for Vec<String> {
+ fn from_reg_value(val: &RegValue) -> io::Result<Vec<String>> {
+ match val.vtype {
+ REG_MULTI_SZ => {
+ let words = unsafe {
+ slice::from_raw_parts(val.bytes.as_ptr() as *const u16, val.bytes.len() / 2)
+ };
+ let mut s = String::from_utf16_lossy(words);
+ while s.ends_with('\u{0}') {
+ s.pop();
+ }
+ let v: Vec<String> = s.split('\u{0}').map(|x| x.to_owned()).collect();
+ Ok(v)
+ }
+ _ => werr!(winerror::ERROR_BAD_FILE_TYPE),
+ }
+ }
+}
+
+impl FromRegValue for OsString {
+ fn from_reg_value(val: &RegValue) -> io::Result<OsString> {
+ match val.vtype {
+ REG_SZ | REG_EXPAND_SZ | REG_MULTI_SZ => {
+ let mut words = unsafe {
+ #[allow(clippy::cast_ptr_alignment)]
+ slice::from_raw_parts(val.bytes.as_ptr() as *const u16, val.bytes.len() / 2)
+ };
+ while let Some(0) = words.last() {
+ words = &words[0..words.len() - 1];
+ }
+ let s = OsString::from_wide(words);
+ Ok(s)
+ }
+ _ => werr!(winerror::ERROR_BAD_FILE_TYPE),
+ }
+ }
+}
+
+impl FromRegValue for Vec<OsString> {
+ fn from_reg_value(val: &RegValue) -> io::Result<Vec<OsString>> {
+ match val.vtype {
+ REG_MULTI_SZ => {
+ let mut words = unsafe {
+ slice::from_raw_parts(val.bytes.as_ptr() as *const u16, val.bytes.len() / 2)
+ };
+ while let Some(0) = words.last() {
+ words = &words[0..words.len() - 1];
+ }
+ let v: Vec<OsString> = words
+ .split(|ch| *ch == 0u16)
+ .map(|x| OsString::from_wide(x))
+ .collect();
+ Ok(v)
+ }
+ _ => werr!(winerror::ERROR_BAD_FILE_TYPE),
+ }
+ }
+}
+
+impl FromRegValue for u32 {
+ fn from_reg_value(val: &RegValue) -> io::Result<u32> {
+ match val.vtype {
+ #[allow(clippy::cast_ptr_alignment)]
+ REG_DWORD => Ok(unsafe { *(val.bytes.as_ptr() as *const u32) }),
+ _ => werr!(winerror::ERROR_BAD_FILE_TYPE),
+ }
+ }
+}
+
+impl FromRegValue for u64 {
+ fn from_reg_value(val: &RegValue) -> io::Result<u64> {
+ match val.vtype {
+ #[allow(clippy::cast_ptr_alignment)]
+ REG_QWORD => Ok(unsafe { *(val.bytes.as_ptr() as *const u64) }),
+ _ => werr!(winerror::ERROR_BAD_FILE_TYPE),
+ }
+ }
+}
+
+/// A trait for types that can be written into registry values.
+///
+/// **NOTE:** Adds trailing `NULL` character to `str`, `String`, `OsStr` and `OsString` values
+pub trait ToRegValue {
+ fn to_reg_value(&self) -> RegValue;
+}
+
+macro_rules! to_reg_value_sz {
+ ($t:ty$(, $l:lifetime)*) => {
+ impl<$($l,)*> ToRegValue for $t {
+ fn to_reg_value(&self) -> RegValue {
+ RegValue {
+ bytes: v16_to_v8(&to_utf16(self)),
+ vtype: REG_SZ,
+ }
+ }
+ }
+ }
+}
+
+to_reg_value_sz!(String);
+to_reg_value_sz!(&'a str, 'a);
+to_reg_value_sz!(OsString);
+to_reg_value_sz!(&'a OsStr, 'a);
+
+macro_rules! to_reg_value_multi_sz {
+ ($t:ty$(, $l:lifetime)*) => {
+ impl<$($l,)*> ToRegValue for Vec<$t> {
+ fn to_reg_value(&self) -> RegValue {
+ let mut os_strings = self
+ .into_iter()
+ .map(to_utf16)
+ .collect::<Vec<_>>()
+ .concat();
+ os_strings.push(0);
+ RegValue {
+ bytes: v16_to_v8(&os_strings),
+ vtype: REG_MULTI_SZ,
+ }
+ }
+ }
+ }
+}
+
+to_reg_value_multi_sz!(String);
+to_reg_value_multi_sz!(&'a str, 'a);
+to_reg_value_multi_sz!(OsString);
+to_reg_value_multi_sz!(&'a OsStr, 'a);
+
+impl ToRegValue for u32 {
+ fn to_reg_value(&self) -> RegValue {
+ let bytes: Vec<u8> =
+ unsafe { slice::from_raw_parts((self as *const u32) as *const u8, 4).to_vec() };
+ RegValue {
+ bytes,
+ vtype: REG_DWORD,
+ }
+ }
+}
+
+impl ToRegValue for u64 {
+ fn to_reg_value(&self) -> RegValue {
+ let bytes: Vec<u8> =
+ unsafe { slice::from_raw_parts((self as *const u64) as *const u8, 8).to_vec() };
+ RegValue {
+ bytes,
+ vtype: REG_QWORD,
+ }
+ }
+}