summaryrefslogtreecommitdiffstats
path: root/third_party/rust/guid_win/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/guid_win/src
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/guid_win/src')
-rw-r--r--third_party/rust/guid_win/src/lib.rs189
1 files changed, 189 insertions, 0 deletions
diff --git a/third_party/rust/guid_win/src/lib.rs b/third_party/rust/guid_win/src/lib.rs
new file mode 100644
index 0000000000..157df8e57a
--- /dev/null
+++ b/third_party/rust/guid_win/src/lib.rs
@@ -0,0 +1,189 @@
+// Licensed under the Apache License, Version 2.0
+// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// All files in the project carrying such notice may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Windows GUID/CLSID/IID string and binary serialization
+//!
+//! [`Guid`](struct.Guid.html) transparently wraps
+//! [`GUID`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa373931(v=vs.85).aspx).
+//!
+//! Implements `Display` and `FromStr` string conversion, also `Hash` and `Eq`.
+//!
+//! Curly braces (`{}`) are optional for `FromStr`.
+//!
+//! # serde #
+//!
+//! Use the `guid_serde` feature to derive `Serialize` and `Deserialize`, you can then
+//! derive them for structs containing `GUID` like so:
+//!
+//! ```
+//! # fn main() {}
+//! #
+//! # #[cfg(feature = "guid_serde")]
+//! # extern crate serde_derive;
+//! # extern crate winapi;
+//! #
+//! # #[cfg(feature = "guid_serde")]
+//! # mod test {
+//! use guid_win::GUIDSerde;
+//! use serde_derive::{Deserialize, Serialize};
+//! use winapi::shared::guiddef::GUID;
+//!
+//! #[derive(Serialize, Deserialize)]
+//! struct SerdeTest {
+//! #[serde(with = "GUIDSerde")]
+//! guid: GUID,
+//! }
+//! # }
+//! ```
+
+extern crate comedy;
+#[cfg(feature = "guid_serde")]
+extern crate serde;
+#[cfg(feature = "guid_serde")]
+extern crate serde_derive;
+extern crate winapi;
+
+use std::ffi::{OsStr, OsString};
+use std::fmt::{Debug, Display, Error, Formatter, Result};
+use std::hash::{Hash, Hasher};
+use std::mem;
+use std::os::windows::ffi::{OsStrExt, OsStringExt};
+use std::result;
+use std::str::FromStr;
+
+use comedy::check_succeeded;
+
+use winapi::ctypes;
+use winapi::shared::guiddef::GUID;
+use winapi::um::combaseapi::{CLSIDFromString, StringFromGUID2};
+
+#[cfg(feature = "guid_serde")]
+use serde_derive::{Deserialize, Serialize};
+
+const GUID_STRING_CHARACTERS: usize = 38;
+
+#[cfg(feature = "guid_serde")]
+#[allow(non_snake_case)]
+#[derive(Serialize, Deserialize)]
+#[serde(remote = "GUID")]
+pub struct GUIDSerde {
+ Data1: ctypes::c_ulong,
+ Data2: ctypes::c_ushort,
+ Data3: ctypes::c_ushort,
+ Data4: [ctypes::c_uchar; 8],
+}
+
+/// Wraps `GUID`
+#[derive(Clone)]
+#[cfg_attr(feature = "guid_serde", derive(Serialize, Deserialize))]
+#[repr(transparent)]
+pub struct Guid(#[cfg_attr(feature = "guid_serde", serde(with = "GUIDSerde"))] pub GUID);
+
+impl PartialEq for Guid {
+ fn eq(&self, other: &Guid) -> bool {
+ self.0.Data1 == other.0.Data1
+ && self.0.Data2 == other.0.Data2
+ && self.0.Data3 == other.0.Data3
+ && self.0.Data4 == other.0.Data4
+ }
+}
+
+impl Eq for Guid {}
+
+impl Hash for Guid {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.0.Data1.hash(state);
+ self.0.Data2.hash(state);
+ self.0.Data3.hash(state);
+ self.0.Data4.hash(state);
+ }
+}
+
+impl Debug for Guid {
+ fn fmt(&self, f: &mut Formatter) -> Result {
+ write!(f, "{:?}", unsafe {
+ &mem::transmute::<Guid, [u8; mem::size_of::<Guid>()]>(self.clone())
+ })
+ }
+}
+
+/// Output a string via `StringFromGUID2()`
+impl Display for Guid {
+ fn fmt(&self, f: &mut Formatter) -> Result {
+ let mut s: [u16; GUID_STRING_CHARACTERS + 1] = unsafe { mem::uninitialized() };
+
+ let len = unsafe {
+ StringFromGUID2(
+ &(*self).0 as *const _ as *mut _,
+ s.as_mut_ptr(),
+ s.len() as ctypes::c_int,
+ )
+ };
+
+ if len <= 0 {
+ return Err(Error);
+ }
+ // len is number of characters, including the null terminator
+
+ let s = &s[..len as usize - 1];
+ // TODO: no reason to expect this to fail, maybe just unwrap()
+ if let Ok(s) = OsString::from_wide(&s).into_string() {
+ f.write_str(&s)
+ } else {
+ Err(Error)
+ }
+ }
+}
+
+/// Read from a string via `CLSIDFromString()`
+///
+/// Braces (`{}`) are added if missing.
+impl FromStr for Guid {
+ type Err = comedy::error::HResult;
+
+ fn from_str(s: &str) -> result::Result<Self, Self::Err> {
+ let mut guid = unsafe { mem::uninitialized() };
+
+ let braced;
+ let s = if s.starts_with('{') {
+ s
+ } else {
+ braced = format!("{{{}}}", s);
+ braced.as_str()
+ };
+ let s: Vec<_> = OsStr::new(s).encode_wide().chain(Some(0)).collect();
+
+ unsafe { check_succeeded!(CLSIDFromString(s.as_ptr(), &mut guid)) }?;
+
+ Ok(Guid(guid))
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::Guid;
+ use std::str::FromStr;
+
+ #[test]
+ fn without_braces() {
+ let uuid = "F1BD1079-9F01-4BDC-8036-F09B70095066";
+ let guid = Guid::from_str(uuid).unwrap();
+ assert_eq!(format!("{}", guid), format!("{{{}}}", uuid));
+ }
+
+ #[test]
+ fn with_braces() {
+ let uuid = "{F1BD1079-9F01-4BDC-8036-F09B70095066}";
+ let guid = Guid::from_str(uuid).unwrap();
+ assert_eq!(format!("{}", guid), uuid);
+ }
+
+ #[test]
+ fn format_error() {
+ let uuid = "foo";
+ Guid::from_str(uuid).unwrap_err();
+ }
+}