Skip to main content

windows_registry/
value.rs

1use super::*;
2
3/// A registry value.
4#[derive(Clone, PartialEq, Eq, Debug)]
5pub struct Value {
6    pub(crate) data: Data,
7    pub(crate) ty: Type,
8}
9
10impl Value {
11    /// Gets the type of the registry value.
12    pub fn ty(&self) -> Type {
13        self.ty
14    }
15
16    /// Sets the type of the registry value. This does not change the value.
17    pub fn set_ty(&mut self, ty: Type) {
18        self.ty = ty;
19    }
20
21    /// Gets the value as a slice of u16 for raw wide characters.
22    pub fn as_wide(&self) -> &[u16] {
23        self.data.as_wide()
24    }
25}
26
27impl core::ops::Deref for Value {
28    type Target = [u8];
29
30    fn deref(&self) -> &[u8] {
31        &self.data
32    }
33}
34
35impl AsRef<[u8]> for Value {
36    fn as_ref(&self) -> &[u8] {
37        &self.data
38    }
39}
40
41impl From<u32> for Value {
42    fn from(from: u32) -> Self {
43        Self {
44            data: from.to_le_bytes().into(),
45            ty: Type::U32,
46        }
47    }
48}
49
50impl TryFrom<Value> for u32 {
51    type Error = Error;
52    fn try_from(from: Value) -> Result<Self> {
53        Ok(from_le_bytes(from.ty, &from)?.try_into()?)
54    }
55}
56
57impl From<u64> for Value {
58    fn from(from: u64) -> Self {
59        Self {
60            data: from.to_le_bytes().into(),
61            ty: Type::U64,
62        }
63    }
64}
65
66impl TryFrom<Value> for u64 {
67    type Error = Error;
68    fn try_from(from: Value) -> Result<Self> {
69        from_le_bytes(from.ty, &from)
70    }
71}
72
73impl TryFrom<Value> for String {
74    type Error = Error;
75    fn try_from(from: Value) -> Result<Self> {
76        match from.ty {
77            Type::String | Type::ExpandString => Ok(Self::from_utf16(trim(from.data.as_wide()))?),
78            _ => Err(invalid_data()),
79        }
80    }
81}
82
83impl From<&str> for Value {
84    fn from(from: &str) -> Self {
85        Self {
86            data: Data::from_slice(pcwstr(from).as_bytes()),
87            ty: Type::String,
88        }
89    }
90}
91
92impl TryFrom<Value> for Vec<String> {
93    type Error = Error;
94    fn try_from(from: Value) -> Result<Self> {
95        match from.ty {
96            Type::MultiString => Ok(from
97                .data
98                .as_wide()
99                .split(|c| *c == 0)
100                .map(String::from_utf16_lossy)
101                .collect()),
102            _ => Ok(vec![String::try_from(from)?]),
103        }
104    }
105}
106
107impl TryFrom<Value> for HSTRING {
108    type Error = Error;
109    fn try_from(from: Value) -> Result<Self> {
110        match from.ty {
111            Type::String | Type::ExpandString => Ok(Self::from_wide(trim(from.data.as_wide()))),
112            _ => Err(invalid_data()),
113        }
114    }
115}
116
117impl From<&HSTRING> for Value {
118    fn from(from: &HSTRING) -> Self {
119        Self {
120            data: Data::from_slice(as_bytes(from)),
121            ty: Type::String,
122        }
123    }
124}
125
126impl From<&[u8]> for Value {
127    fn from(from: &[u8]) -> Self {
128        Self {
129            data: Data::from_slice(from),
130            ty: Type::Bytes,
131        }
132    }
133}
134
135impl<const N: usize> From<[u8; N]> for Value {
136    fn from(from: [u8; N]) -> Self {
137        Self {
138            data: Data::from_slice(&from),
139            ty: Type::Bytes,
140        }
141    }
142}
143
144fn trim(mut wide: &[u16]) -> &[u16] {
145    while wide.last() == Some(&0) {
146        wide = &wide[..wide.len() - 1];
147    }
148
149    wide
150}