diff --git a/crates/tools/lib/src/lib.rs b/crates/tools/lib/src/lib.rs index b57d4b13da..d4ed60d0c6 100644 --- a/crates/tools/lib/src/lib.rs +++ b/crates/tools/lib/src/lib.rs @@ -9,15 +9,15 @@ pub enum CallingConvention { pub fn default_metadata() -> Vec { vec![ metadata::File::new( - std::include_bytes!("../../../libs/metadata/default/Windows.winmd").to_vec(), + std::include_bytes!("../../../libs/bindgen/default/Windows.winmd").to_vec(), ) .expect("invalid winmd"), metadata::File::new( - std::include_bytes!("../../../libs/metadata/default/Windows.Win32.winmd").to_vec(), + std::include_bytes!("../../../libs/bindgen/default/Windows.Win32.winmd").to_vec(), ) .expect("invalid winmd"), metadata::File::new( - std::include_bytes!("../../../libs/metadata/default/Windows.Wdk.winmd").to_vec(), + std::include_bytes!("../../../libs/bindgen/default/Windows.Wdk.winmd").to_vec(), ) .expect("invalid winmd"), ] diff --git a/crates/tools/metadata/bindings.txt b/crates/tools/metadata/bindings.txt index 27db4445e7..e49710e6f0 100644 --- a/crates/tools/metadata/bindings.txt +++ b/crates/tools/metadata/bindings.txt @@ -1,6 +1,6 @@ ---in crates/libs/metadata/default +--in crates/libs/bindgen/default --out crates/libs/metadata/src/imp/bindings.rs ---config FLATTEN SYS MINIMAL +--config flatten sys minimal --filter Windows.Win32.System.Diagnostics.Debug.IMAGE_COR20_HEADER diff --git a/crates/tools/riddle/Cargo.toml b/crates/tools/riddle/Cargo.toml index 9c4e1ca8ca..37a76fb5b4 100644 --- a/crates/tools/riddle/Cargo.toml +++ b/crates/tools/riddle/Cargo.toml @@ -7,15 +7,7 @@ license = "MIT OR Apache-2.0" description = "Windows metadata compiler" repository = "https://github.com/microsoft/windows-rs" -[dependencies] -windows-metadata = { path = "../../libs/metadata", version = "0.49.0" } -rayon = "1.7" - -[dependencies.syn] -version = "2.0" -features = ["full", "extra-traits"] - -[dependencies.proc-macro2] -version = "1.0" -features = ["span-locations"] - +[dependencies.windows-bindgen] +path = "../../libs/bindgen" +version = "0.49.0" +default-features = false diff --git a/crates/tools/riddle/src/args.rs b/crates/tools/riddle/src/args.rs deleted file mode 100644 index 9dffbff051..0000000000 --- a/crates/tools/riddle/src/args.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::Result; - -pub fn from_process() -> Result> { - let mut result = vec![]; - from_iter(&mut result, std::env::args().skip(1))?; - Ok(result) -} - -fn from_string(result: &mut Vec, value: &str) -> Result<()> { - let value = if let Some((value, _)) = value.split_once('#') { - value - } else { - value - }; - - from_iter(result, value.split_whitespace().map(|arg| arg.to_string()))?; - Ok(()) -} - -fn from_iter>(result: &mut Vec, args: T) -> Result<()> { - let mut expand = false; - - for arg in args { - if arg.starts_with('-') { - expand = false; - } - if expand { - for args in crate::read_file_lines(&arg)? { - from_string(result, &args)?; - } - } else if arg == "--etc" { - expand = true; - } else { - result.push(arg); - } - } - - Ok(()) -} diff --git a/crates/tools/riddle/src/error.rs b/crates/tools/riddle/src/error.rs deleted file mode 100644 index 94205c3033..0000000000 --- a/crates/tools/riddle/src/error.rs +++ /dev/null @@ -1,65 +0,0 @@ -pub type Result = std::result::Result; - -#[derive(Default, Debug)] -pub struct Error { - message: String, - path: String, - span: Option<(usize, usize)>, -} - -impl std::error::Error for Error {} - -impl From for std::io::Error { - fn from(error: Error) -> Self { - std::io::Error::new(std::io::ErrorKind::Other, error.message.as_str()) - } -} - -impl From for Error { - fn from(error: syn::Error) -> Self { - let start = error.span().start(); - Self { - message: error.to_string(), - span: Some((start.line, start.column)), - ..Self::default() - } - } -} - -impl std::fmt::Display for Error { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(fmt, "error: {}", self.message)?; - if !self.path.is_empty() { - if let Some((line, column)) = self.span { - writeln!(fmt, " --> {}:{line}:{column}", self.path)?; - } else { - writeln!(fmt, " --> {}", self.path)?; - } - } - Ok(()) - } -} - -impl Error { - pub fn new(message: &str) -> Self { - Self { - message: message.to_string(), - ..Self::default() - } - } - - pub fn with_path(self, path: &str) -> Self { - Self { - path: path.to_string(), - ..self - } - } - - pub fn with_span(self, span: proc_macro2::Span) -> Self { - let start = span.start(); - Self { - span: Some((start.line, start.column)), - ..self - } - } -} diff --git a/crates/tools/riddle/src/main.rs b/crates/tools/riddle/src/main.rs index ff7657e2e2..1794dfa95f 100644 --- a/crates/tools/riddle/src/main.rs +++ b/crates/tools/riddle/src/main.rs @@ -1,33 +1,5 @@ -mod args; -mod error; -mod metadata; -mod rdl; -mod rust; -mod tokens; -mod tree; -mod winmd; - -use error::{Error, Result}; -use tree::Tree; - -enum ArgKind { - None, - Input, - Output, - Filter, - Config, -} - fn main() { - if let Err(error) = run() { - eprintln!("{}", error); - std::process::exit(1); - } -} - -fn run() -> Result<()> { - let time = std::time::Instant::now(); - let args = args::from_process()?; + let args: Vec = std::env::args().skip(1).collect(); if args.is_empty() { println!( @@ -42,272 +14,13 @@ Options: --etc File containing command line options "# ); - return Ok(()); - } - - let mut kind = ArgKind::None; - let mut output = None; - let mut input = Vec::<&str>::new(); - let mut include = Vec::<&str>::new(); - let mut exclude = Vec::<&str>::new(); - let mut config = std::collections::BTreeMap::<&str, &str>::new(); - let mut format = false; - - for arg in &args { - if arg.starts_with('-') { - kind = ArgKind::None; - } - - match kind { - ArgKind::None => match arg.as_str() { - "-i" | "--in" => kind = ArgKind::Input, - "-o" | "--out" => kind = ArgKind::Output, - "-f" | "--filter" => kind = ArgKind::Filter, - "--config" => kind = ArgKind::Config, - "--format" => format = true, - _ => return Err(Error::new(&format!("invalid option `{arg}`"))), - }, - ArgKind::Output => { - if output.is_none() { - output = Some(arg.as_str()); - } else { - return Err(Error::new("too many outputs")); - } - } - ArgKind::Input => input.push(arg.as_str()), - ArgKind::Filter => { - if let Some(rest) = arg.strip_prefix('!') { - exclude.push(rest); - } else { - include.push(arg.as_str()); - } - } - ArgKind::Config => { - if let Some((key, value)) = arg.split_once('=') { - config.insert(key, value); - } else { - config.insert(arg, ""); - } - } - } - } - - if format { - if output.is_some() || !include.is_empty() || !exclude.is_empty() { - return Err(Error::new( - "`--format` cannot be combined with `--out` or `--filter`", - )); - } - - let input = filter_input(&input, &["rdl"])?; - - if input.is_empty() { - return Err(Error::new("no .rdl inputs")); - } - - for path in &input { - read_file_text(path) - .and_then(|source| rdl::File::parse_str(&source)) - .and_then(|file| write_to_file(path, file.fmt())) - .map_err(|err| err.with_path(path))?; - } - - return Ok(()); - } - - let Some(output) = output else { - return Err(Error::new("no output")); - }; - - // This isn't strictly necessary but avoids a common newbie pitfall where all metadata - // would be generated when building a component for a specific API. - if include.is_empty() { - return Err(Error::new("at least one `--filter` must be specified")); - } - - let output = canonicalize(output)?; - - let input = read_input(&input)?; - let reader = metadata::Reader::new(&input); - let filter = metadata::Filter::new(&include, &exclude); - - winmd::verify(&reader, &filter)?; - - match extension(&output) { - "rdl" => rdl::from_reader(&reader, &filter, config, &output)?, - "winmd" => winmd::from_reader(&reader, &filter, config, &output)?, - "rs" => rust::from_reader(&reader, &filter, config, &output)?, - _ => return Err(Error::new("output extension must be one of winmd/rdl/rs")), - } - - let elapsed = time.elapsed().as_secs_f32(); - - if elapsed > 0.1 { - println!( - " Finished writing `{}` in {:.2}s", - output, - time.elapsed().as_secs_f32() - ); } else { - println!(" Finished writing `{}`", output,); - } - - Ok(()) -} - -fn filter_input(input: &[&str], extensions: &[&str]) -> Result> { - fn try_push(path: &str, extensions: &[&str], results: &mut Vec) -> Result<()> { - // First canonicalize input so that the extension check below will match the case of the path. - let path = canonicalize(path)?; - - if extensions.contains(&extension(&path)) { - results.push(path); - } - - Ok(()) - } - - let mut results = vec![]; - - for input in input { - let path = std::path::Path::new(input); - - if !path.exists() { - return Err(Error::new("failed to read input").with_path(input)); - } - - if path.is_dir() { - for entry in path - .read_dir() - .map_err(|_| Error::new("failed to read directory").with_path(input))? - .flatten() - { - let path = entry.path(); - - if path.is_file() { - try_push(&path.to_string_lossy(), extensions, &mut results)?; - } + match windows_bindgen::bindgen(args) { + Ok(ok) => println!("{}", ok), + Err(error) => { + eprintln!("{}", error); + std::process::exit(1); } - } else { - try_push(&path.to_string_lossy(), extensions, &mut results)?; } } - Ok(results) -} - -fn read_input(input: &[&str]) -> Result> { - let input = filter_input(input, &["winmd", "rdl"])?; - - if input.is_empty() { - return Err(Error::new("no inputs")); - } - - let mut results = vec![]; - - for input in &input { - let file = if extension(input) == "winmd" { - read_winmd_file(input)? - } else { - read_rdl_file(input)? - }; - - results.push(file); - } - - Ok(results) -} - -fn read_file_text(path: &str) -> Result { - std::fs::read_to_string(path).map_err(|_| Error::new("failed to read text file")) -} - -fn read_file_bytes(path: &str) -> Result> { - std::fs::read(path).map_err(|_| Error::new("failed to read binary file")) -} - -fn read_file_lines(path: &str) -> Result> { - use std::io::BufRead; - fn error(path: &str) -> Error { - Error::new("failed to read lines").with_path(path) - } - let file = std::io::BufReader::new(std::fs::File::open(path).map_err(|_| error(path))?); - let mut lines = vec![]; - for line in file.lines() { - lines.push(line.map_err(|_| error(path))?); - } - Ok(lines) -} - -fn read_rdl_file(path: &str) -> Result { - read_file_text(path) - .and_then(|source| rdl::File::parse_str(&source)) - .and_then(|file| file.into_winmd()) - .map(|bytes| { - // TODO: Write bytes to file if you need to debug the intermediate .winmd file like so: - _ = write_to_file("temp.winmd", &bytes); - - // Unwrapping here is fine since `rdl_to_winmd` should have produced a valid winmd - metadata::File::new(bytes).unwrap() - }) - .map_err(|err| err.with_path(path)) -} - -fn read_winmd_file(path: &str) -> Result { - read_file_bytes(path).and_then(|bytes| { - metadata::File::new(bytes) - .ok_or_else(|| Error::new("failed to read .winmd format").with_path(path)) - }) -} - -fn write_to_file>(path: &str, contents: C) -> Result<()> { - if let Some(parent) = std::path::Path::new(path).parent() { - std::fs::create_dir_all(parent) - .map_err(|_| Error::new("failed to create directory").with_path(path))?; - } - - std::fs::write(path, contents).map_err(|_| Error::new("failed to write file").with_path(path)) -} - -fn canonicalize(value: &str) -> Result { - let temp = !std::path::Path::new(value).exists(); - - // `std::fs::canonicalize` only works if the file exists so we temporarily create it here. - if temp { - write_to_file(value, "")?; - } - - let path = std::fs::canonicalize(value) - .map_err(|_| Error::new("failed to find path").with_path(value))?; - - if temp { - std::fs::remove_file(value) - .map_err(|_| Error::new("failed to remove temporary file").with_path(value))?; - } - - let path = path - .to_string_lossy() - .trim_start_matches(r"\\?\") - .to_string(); - - match path.rsplit_once('.') { - Some((file, extension)) => Ok(format!("{file}.{}", extension.to_lowercase())), - _ => Ok(path), - } -} - -fn extension(path: &str) -> &str { - path.rsplit_once('.').map_or("", |(_, extension)| extension) -} - -fn directory(path: &str) -> &str { - path.rsplit_once(&['/', '\\']) - .map_or("", |(directory, _)| directory) -} - -fn trim_tick(name: &str) -> &str { - if name.as_bytes().iter().rev().nth(1) == Some(&b'`') { - &name[..name.len() - 2] - } else { - name - } } diff --git a/crates/tools/riddle/src/metadata/mod.rs b/crates/tools/riddle/src/metadata/mod.rs deleted file mode 100644 index 5c4af7afeb..0000000000 --- a/crates/tools/riddle/src/metadata/mod.rs +++ /dev/null @@ -1,589 +0,0 @@ -use std::collections::*; -pub use windows_metadata::*; - -#[derive(Clone)] -pub struct Interface { - pub ty: Type, - pub kind: InterfaceKind, -} - -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum InterfaceKind { - None, - Default, - Overridable, - Static, - Base, -} - -#[derive(Copy, Clone, PartialEq, Eq)] -pub struct QueryPosition { - pub object: usize, - pub guid: usize, -} - -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum SignatureKind { - Query(QueryPosition), - QueryOptional(QueryPosition), - ResultValue, - ResultVoid, - ReturnStruct, - ReturnValue, - ReturnVoid, - PreserveSig, -} - -#[derive(Copy, Clone, Eq, PartialEq)] -pub enum SignatureParamKind { - ArrayFixed(usize), - ArrayRelativeLen(usize), - ArrayRelativeByteLen(usize), - ArrayRelativePtr(usize), - TryInto, - IntoParam, - OptionalPointer, - ValueType, - Blittable, - Other, -} - -impl SignatureParamKind { - fn is_array(&self) -> bool { - matches!( - self, - Self::ArrayFixed(_) - | Self::ArrayRelativeLen(_) - | Self::ArrayRelativeByteLen(_) - | Self::ArrayRelativePtr(_) - ) - } -} - -pub struct Signature { - pub def: MethodDef, - pub params: Vec, - pub return_type: Type, - pub call_flags: MethodCallAttributes, -} - -pub struct SignatureParam { - pub def: Param, - pub ty: Type, - pub kind: SignatureParamKind, -} - -#[derive(PartialEq, Eq, Debug)] -pub enum AsyncKind { - None, - Action, - ActionWithProgress, - Operation, - OperationWithProgress, -} - -pub fn type_def_invoke_method(reader: &Reader, row: TypeDef) -> MethodDef { - reader - .type_def_methods(row) - .find(|method| reader.method_def_name(*method) == "Invoke") - .expect("`Invoke` method not found") -} - -pub fn type_def_generics(reader: &Reader, def: TypeDef) -> Vec { - reader - .type_def_generics(def) - .map(Type::GenericParam) - .collect() -} - -// TODO: namespace should not be required - it's a hack to accomodate Win32 metadata -// TODO: this is very Rust-specific and Win32-metadata specific with all of its translation. Replace with literal signature parser that just returns slice of types. -pub fn method_def_signature( - reader: &Reader, - namespace: &str, - row: MethodDef, - generics: &[Type], -) -> Signature { - let mut blob = reader.row_blob(row, 4); - let call_flags = MethodCallAttributes(blob.read_usize() as u8); - let _param_count = blob.read_usize(); - let mut return_type = reader.type_from_blob(&mut blob, None, generics); - - let mut params: Vec = reader - .method_def_params(row) - .filter_map(|param| { - let param_is_const = reader.has_attribute(param, "ConstAttribute"); - if reader.param_sequence(param) == 0 { - if param_is_const { - return_type = return_type.clone().to_const_type(); - } - None - } else { - let is_output = reader.param_flags(param).contains(ParamAttributes::Out); - let mut ty = reader.type_from_blob(&mut blob, None, generics); - - if let Some(name) = param_or_enum(reader, param) { - let def = reader - .get_type_def(TypeName::new(namespace, &name)) - .next() - .expect("Enum not found"); - ty = Type::PrimitiveOrEnum( - Box::new(ty), - Box::new(Type::TypeDef(def, Vec::new())), - ); - } - - if param_is_const || !is_output { - ty = ty.to_const_type(); - } - if !is_output { - ty = ty.to_const_ptr(); - } - let kind = param_kind(reader, param); - Some(SignatureParam { - def: param, - ty, - kind, - }) - } - }) - .collect(); - - for position in 0..params.len() { - // Point len params back to the corresponding ptr params. - match params[position].kind { - SignatureParamKind::ArrayRelativeLen(relative) - | SignatureParamKind::ArrayRelativeByteLen(relative) => { - // The len params must be input only. - if !reader - .param_flags(params[relative].def) - .contains(ParamAttributes::Out) - && position != relative - && !params[relative].ty.is_pointer() - { - params[relative].kind = SignatureParamKind::ArrayRelativePtr(position); - } else { - params[position].kind = SignatureParamKind::Other; - } - } - SignatureParamKind::ArrayFixed(_) => { - if reader.has_attribute(params[position].def, "FreeWithAttribute") { - params[position].kind = SignatureParamKind::Other; - } - } - _ => {} - } - } - - let mut sets = BTreeMap::>::new(); - - // Finds sets of ptr params pointing at the same len param. - for (position, param) in params.iter().enumerate() { - match param.kind { - SignatureParamKind::ArrayRelativeLen(relative) - | SignatureParamKind::ArrayRelativeByteLen(relative) => { - sets.entry(relative).or_default().push(position); - } - _ => {} - } - } - - // Remove all sets. - for (len, ptrs) in sets { - if ptrs.len() > 1 { - params[len].kind = SignatureParamKind::Other; - for ptr in ptrs { - params[ptr].kind = SignatureParamKind::Other; - } - } - } - - // Remove any byte arrays that aren't byte-sized types. - for position in 0..params.len() { - if let SignatureParamKind::ArrayRelativeByteLen(relative) = params[position].kind { - if !params[position].ty.is_byte_size() { - params[position].kind = SignatureParamKind::Other; - params[relative].kind = SignatureParamKind::Other; - } - } - } - - for param in &mut params { - if param.kind == SignatureParamKind::Other { - if signature_param_is_convertible(reader, param) { - if type_is_non_exclusive_winrt_interface(reader, ¶m.ty) { - param.kind = SignatureParamKind::TryInto; - } else { - param.kind = SignatureParamKind::IntoParam; - } - } else { - let flags = reader.param_flags(param.def); - if param.ty.is_pointer() - && (flags.contains(ParamAttributes::Optional) - || reader.has_attribute(param.def, "ReservedAttribute")) - { - param.kind = SignatureParamKind::OptionalPointer; - } else if reader.type_is_primitive(¶m.ty) - && (!param.ty.is_pointer() || reader.type_is_blittable(¶m.ty.deref())) - { - param.kind = SignatureParamKind::ValueType; - } else if reader.type_is_blittable(¶m.ty) { - param.kind = SignatureParamKind::Blittable; - } - } - } - } - - Signature { - def: row, - params, - return_type, - call_flags, - } -} - -fn param_kind(reader: &Reader, row: Param) -> SignatureParamKind { - for attribute in reader.attributes(row) { - match reader.attribute_name(attribute) { - "NativeArrayInfoAttribute" => { - for (_, value) in reader.attribute_args(attribute) { - match value { - Value::I16(value) => { - return SignatureParamKind::ArrayRelativeLen(value as usize) - } - Value::I32(value) => return SignatureParamKind::ArrayFixed(value as usize), - _ => {} - } - } - } - "MemorySizeAttribute" => { - for (_, value) in reader.attribute_args(attribute) { - if let Value::I16(value) = value { - return SignatureParamKind::ArrayRelativeByteLen(value as usize); - } - } - } - _ => {} - } - } - SignatureParamKind::Other -} -// TODO: this is a terribly broken Win32 metadata attribute - need to get rid of it. -fn param_or_enum(reader: &Reader, row: Param) -> Option { - reader - .find_attribute(row, "AssociatedEnumAttribute") - .and_then(|attribute| { - for (_, arg) in reader.attribute_args(attribute) { - if let Value::String(name) = arg { - return Some(name); - } - } - None - }) -} - -pub fn signature_param_is_borrowed(reader: &Reader, param: &SignatureParam) -> bool { - type_is_borrowed(reader, ¶m.ty) -} - -pub fn signature_param_is_convertible(reader: &Reader, param: &SignatureParam) -> bool { - !reader.param_flags(param.def).contains(ParamAttributes::Out) - && !param.ty.is_winrt_array() - && !param.ty.is_pointer() - && !param.kind.is_array() - && (type_is_borrowed(reader, ¶m.ty) - || type_is_non_exclusive_winrt_interface(reader, ¶m.ty) - || type_is_trivially_convertible(reader, ¶m.ty)) -} -fn signature_param_is_retval(reader: &Reader, param: &SignatureParam) -> bool { - // The Win32 metadata uses `RetValAttribute` to call out retval methods but it is employed - // very sparingly, so this heuristic is used to apply the transformation more uniformly. - if reader.has_attribute(param.def, "RetValAttribute") { - return true; - } - if !param.ty.is_pointer() { - return false; - } - if param.ty.is_void() { - return false; - } - let flags = reader.param_flags(param.def); - if flags.contains(ParamAttributes::In) - || !flags.contains(ParamAttributes::Out) - || flags.contains(ParamAttributes::Optional) - || param.kind.is_array() - { - return false; - } - if param_kind(reader, param.def).is_array() { - return false; - } - // If it's bigger than 128 bits, best to pass as a reference. - if reader.type_size(¶m.ty.deref()) > 16 { - return false; - } - // Win32 callbacks are defined as `Option` so we don't include them here to avoid - // producing the `Result>` anti-pattern. - !type_is_callback(reader, ¶m.ty.deref()) -} -pub fn signature_kind(reader: &Reader, signature: &Signature) -> SignatureKind { - if reader.has_attribute(signature.def, "CanReturnMultipleSuccessValuesAttribute") { - return SignatureKind::PreserveSig; - } - match &signature.return_type { - Type::Void if signature_is_retval(reader, signature) => SignatureKind::ReturnValue, - Type::Void => SignatureKind::ReturnVoid, - Type::HRESULT => { - if signature.params.len() >= 2 { - if let Some(guid) = signature_param_is_query_guid(reader, &signature.params) { - if let Some(object) = signature_param_is_query_object(reader, &signature.params) - { - if reader - .param_flags(signature.params[object].def) - .contains(ParamAttributes::Optional) - { - return SignatureKind::QueryOptional(QueryPosition { object, guid }); - } else { - return SignatureKind::Query(QueryPosition { object, guid }); - } - } - } - } - if signature_is_retval(reader, signature) { - SignatureKind::ResultValue - } else { - SignatureKind::ResultVoid - } - } - Type::TypeDef(def, _) if reader.type_def_type_name(*def) == TypeName::NTSTATUS => { - SignatureKind::ResultVoid - } - Type::TypeDef(def, _) if reader.type_def_type_name(*def) == TypeName::WIN32_ERROR => { - SignatureKind::ResultVoid - } - Type::TypeDef(def, _) - if reader.type_def_type_name(*def) == TypeName::BOOL - && method_def_last_error(reader, signature.def) => - { - SignatureKind::ResultVoid - } - _ if reader.type_is_struct(&signature.return_type) => SignatureKind::ReturnStruct, - _ => SignatureKind::PreserveSig, - } -} -fn signature_is_retval(reader: &Reader, signature: &Signature) -> bool { - signature - .params - .last() - .map_or(false, |param| signature_param_is_retval(reader, param)) - && signature.params[..signature.params.len() - 1] - .iter() - .all(|param| { - let flags = reader.param_flags(param.def); - !flags.contains(ParamAttributes::Out) - }) -} -fn signature_param_is_query_guid(reader: &Reader, params: &[SignatureParam]) -> Option { - params.iter().rposition(|param| { - param.ty == Type::ConstPtr(Box::new(Type::GUID), 1) - && !reader.param_flags(param.def).contains(ParamAttributes::Out) - }) -} -fn signature_param_is_query_object(reader: &Reader, params: &[SignatureParam]) -> Option { - params.iter().rposition(|param| { - param.ty == Type::MutPtr(Box::new(Type::Void), 2) - && reader.has_attribute(param.def, "ComOutPtrAttribute") - }) -} - -fn method_def_last_error(reader: &Reader, row: MethodDef) -> bool { - if let Some(map) = reader.method_def_impl_map(row) { - reader - .impl_map_flags(map) - .contains(PInvokeAttributes::SupportsLastError) - } else { - false - } -} - -fn type_is_borrowed(reader: &Reader, ty: &Type) -> bool { - match ty { - Type::TypeDef(row, _) => !reader.type_def_is_blittable(*row), - Type::BSTR - | Type::PCSTR - | Type::PCWSTR - | Type::IInspectable - | Type::IUnknown - | Type::GenericParam(_) => true, - _ => false, - } -} - -pub fn type_is_non_exclusive_winrt_interface(reader: &Reader, ty: &Type) -> bool { - match ty { - Type::TypeDef(row, _) => { - let flags = reader.type_def_flags(*row); - if !flags.contains(TypeAttributes::WindowsRuntime) { - false - } else { - match reader.type_def_kind(*row) { - TypeKind::Interface => !reader.type_def_is_exclusive(*row), - TypeKind::Class => reader.has_attribute(*row, "ComposableAttribute"), - _ => false, - } - } - } - _ => false, - } -} - -fn type_is_trivially_convertible(reader: &Reader, ty: &Type) -> bool { - match ty { - Type::TypeDef(row, _) => match reader.type_def_kind(*row) { - TypeKind::Struct => reader.type_def_is_handle(*row), - _ => false, - }, - Type::PCSTR | Type::PCWSTR => true, - _ => false, - } -} - -fn type_is_callback(reader: &Reader, ty: &Type) -> bool { - match ty { - Type::TypeDef(row, _) => type_def_is_callback(reader, *row), - _ => false, - } -} - -fn type_def_is_callback(reader: &Reader, row: TypeDef) -> bool { - !reader - .type_def_flags(row) - .contains(TypeAttributes::WindowsRuntime) - && reader.type_def_kind(row) == TypeKind::Delegate -} - -pub fn type_has_callback(reader: &Reader, ty: &Type) -> bool { - match ty { - Type::TypeDef(row, _) => type_def_has_callback(reader, *row), - Type::Win32Array(ty, _) => type_has_callback(reader, ty), - _ => false, - } -} -pub fn type_def_has_callback(reader: &Reader, row: TypeDef) -> bool { - if type_def_is_callback(reader, row) { - return true; - } - if reader.type_def_kind(row) != TypeKind::Struct { - return false; - } - fn check(reader: &Reader, row: TypeDef) -> bool { - if reader - .type_def_fields(row) - .any(|field| type_has_callback(reader, &reader.field_type(field, Some(row)))) - { - return true; - } - false - } - let type_name = reader.type_def_type_name(row); - if type_name.namespace.is_empty() { - check(reader, row) - } else { - for row in reader.get_type_def(type_name) { - if check(reader, row) { - return true; - } - } - false - } -} - -pub fn type_interfaces(reader: &Reader, ty: &Type) -> Vec { - // TODO: collect into btree map and then return collected vec - // This will both sort the results and should make finding dupes faster - fn walk(reader: &Reader, result: &mut Vec, parent: &Type, is_base: bool) { - if let Type::TypeDef(row, generics) = parent { - for imp in reader.type_def_interface_impls(*row) { - let mut child = Interface { - ty: reader.interface_impl_type(imp, generics), - kind: if reader.has_attribute(imp, "DefaultAttribute") { - InterfaceKind::Default - } else { - InterfaceKind::None - }, - }; - - child.kind = if !is_base && child.kind == InterfaceKind::Default { - InterfaceKind::Default - } else if child.kind == InterfaceKind::Overridable { - continue; - } else if is_base { - InterfaceKind::Base - } else { - InterfaceKind::None - }; - let mut found = false; - for existing in result.iter_mut() { - if existing.ty == child.ty { - found = true; - if child.kind == InterfaceKind::Default { - existing.kind = child.kind - } - } - } - if !found { - walk(reader, result, &child.ty, is_base); - result.push(child); - } - } - } - } - let mut result = Vec::new(); - walk(reader, &mut result, ty, false); - if let Type::TypeDef(row, _) = ty { - if reader.type_def_kind(*row) == TypeKind::Class { - for base in reader.type_def_bases(*row) { - walk(reader, &mut result, &Type::TypeDef(base, Vec::new()), true); - } - for attribute in reader.attributes(*row) { - match reader.attribute_name(attribute) { - "StaticAttribute" | "ActivatableAttribute" => { - for (_, arg) in reader.attribute_args(attribute) { - if let Value::TypeName(type_name) = arg { - let def = reader - .get_type_def(TypeName::parse(&type_name)) - .next() - .expect("Type not found"); - result.push(Interface { - ty: Type::TypeDef(def, Vec::new()), - kind: InterfaceKind::Static, - }); - break; - } - } - } - _ => {} - } - } - } - } - result.sort_by(|a, b| type_name(reader, &a.ty).cmp(type_name(reader, &b.ty))); - result -} - -fn type_name<'a>(reader: &Reader<'a>, ty: &Type) -> &'a str { - match ty { - Type::TypeDef(row, _) => reader.type_def_name(*row), - _ => "", - } -} - -pub fn type_def_async_kind(reader: &Reader, row: TypeDef) -> AsyncKind { - match reader.type_def_type_name(row) { - TypeName::IAsyncAction => AsyncKind::Action, - TypeName::IAsyncActionWithProgress => AsyncKind::ActionWithProgress, - TypeName::IAsyncOperation => AsyncKind::Operation, - TypeName::IAsyncOperationWithProgress => AsyncKind::OperationWithProgress, - _ => AsyncKind::None, - } -} diff --git a/crates/tools/riddle/src/rdl/fmt.rs b/crates/tools/riddle/src/rdl/fmt.rs deleted file mode 100644 index ef3c8eb6d0..0000000000 --- a/crates/tools/riddle/src/rdl/fmt.rs +++ /dev/null @@ -1,445 +0,0 @@ -use super::*; - -// TODO: should we use rustfmt in the short term (with pre/post) - -#[derive(Default)] -pub struct Writer { - out: String, - indent: usize, - newline: bool, -} - -impl Writer { - pub fn new(file: &rdl::File) -> Self { - let mut writer = Self::default(); - writer.rdl_file(file); - writer - } - - pub fn into_string(mut self) -> String { - self.out.push('\n'); - self.out - } - - fn word(&mut self, value: &str) { - if self.newline { - self.newline = false; - self.out.push('\n'); - for _ in 0..self.indent { - self.out.push_str(" "); - } - } - - self.out.push_str(value); - } - - fn newline(&mut self) { - self.newline = true; - } - - fn rdl_file(&mut self, file: &rdl::File) { - if file.winrt { - self.word("#![winrt]\n"); - } else { - self.word("#![win32]\n"); - } - - self.newline(); - - for reference in &file.references { - self.item_use(reference); - } - - for module in &file.modules { - self.rdl_module(module); - } - } - - fn rdl_module(&mut self, module: &rdl::Module) { - self.word("mod "); - self.word(module.name()); - self.word(" {"); - self.newline(); - self.indent += 1; - - for member in &module.members { - self.rdl_module_member(member); - self.newline(); - } - - self.indent -= 1; - self.newline(); - self.word("}"); - self.newline(); - } - - fn rdl_module_member(&mut self, member: &rdl::ModuleMember) { - match member { - rdl::ModuleMember::Module(member) => self.rdl_module(member), - rdl::ModuleMember::Interface(member) => self.rdl_interface(member), - rdl::ModuleMember::Struct(member) => self.rdl_struct(member), - rdl::ModuleMember::Enum(member) => self.rdl_enum(member), - rdl::ModuleMember::Class(member) => self.rdl_class(member), - rdl::ModuleMember::Constant(member) => self.rdl_constant(member), - rdl::ModuleMember::Function(member) => self.rdl_function(member), - } - } - - fn rdl_class(&mut self, member: &rdl::Class) { - self.attrs(&member.attributes); - self.word("class "); - self.word(&member.name); - - if !member.extends.is_empty() { - self.word(" : "); - - let mut first = true; - for path in &member.extends { - if first { - first = false; - } else { - self.word(", "); - } - self.type_path(path); - } - } - - self.word(";"); - self.newline(); - } - - fn rdl_interface(&mut self, member: &rdl::Interface) { - self.attrs(&member.attributes); - self.word("interface "); - self.word(&member.name); - - if !member.generics.is_empty() { - self.word("<"); - - let mut first = true; - for generic in &member.generics { - if first { - first = false; - } else { - self.word(", "); - } - self.word(generic); - } - - self.word(">"); - } - - if !member.extends.is_empty() { - self.word(" : "); - - let mut first = true; - for path in &member.extends { - if first { - first = false; - } else { - self.word(", "); - } - self.type_path(path); - } - } - - self.word(" {"); - self.newline(); - self.indent += 1; - - for method in &member.methods { - self.trait_item_fn(method); - self.word(";"); - self.newline(); - } - - self.indent -= 1; - self.newline(); - self.word("}"); - } - - fn rdl_constant(&mut self, member: &rdl::Constant) { - self.item_const(&member.item); - } - - fn rdl_function(&mut self, member: &rdl::Function) { - self.trait_item_fn(&member.item); - self.word(";"); - self.newline(); - } - - fn item_const(&mut self, item: &syn::ItemConst) { - self.word("const "); - self.ident(&item.ident); - self.word(": "); - self.ty(&item.ty); - self.word(" = "); - self.expr(&item.expr); - self.word(";"); - self.newline(); - } - - fn attrs(&mut self, attrs: &[syn::Attribute]) { - for attr in attrs { - self.attr(attr); - } - } - - fn attr(&mut self, attr: &syn::Attribute) { - self.word("#["); - self.meta(&attr.meta); - self.word("]"); - self.newline(); - } - - fn meta(&mut self, meta: &syn::Meta) { - match meta { - syn::Meta::Path(path) => self.path(path), - syn::Meta::List(list) => self.meta_list(list), - syn::Meta::NameValue(meta) => self.meta_name_value(meta), - } - } - - fn meta_list(&mut self, meta_list: &syn::MetaList) { - self.path(&meta_list.path); - self.word("("); - self.word(&meta_list.tokens.to_string()); - self.word(")"); - } - - fn meta_name_value(&mut self, meta: &syn::MetaNameValue) { - self.path(&meta.path); - self.word(" = "); - self.expr(&meta.value); - } - - fn rdl_struct(&mut self, member: &rdl::Struct) { - self.attrs(&member.attributes); - - self.word("struct "); - self.word(&member.name); - self.word(" {"); - self.newline(); - self.indent += 1; - - for field in &member.fields { - self.word(&field.name); - self.word(": "); - self.ty(&field.ty); - self.word(","); - self.newline(); - } - - self.indent -= 1; - self.newline(); - self.word("}"); - } - - fn rdl_enum(&mut self, member: &rdl::Enum) { - self.attrs(&member.item.attrs); - - self.word("enum "); - self.ident(&member.item.ident); - self.word(" {"); - self.newline(); - self.indent += 1; - - for variant in &member.item.variants { - self.ident(&variant.ident); - if let Some((_, expr)) = &variant.discriminant { - self.word(" = "); - self.expr(expr); - } - self.word(","); - self.newline(); - } - - self.indent -= 1; - self.newline(); - self.word("}"); - } - - fn trait_item_fn(&mut self, method: &syn::TraitItemFn) { - self.attrs(&method.attrs); - self.signature(&method.sig); - } - - fn signature(&mut self, signature: &syn::Signature) { - self.word("fn "); - self.ident(&signature.ident); - self.word("("); - - let mut first = true; - for input in &signature.inputs { - if first { - first = false; - } else { - self.word(", "); - } - self.fn_arg(input); - } - - self.word(")"); - - if let syn::ReturnType::Type(_, ty) = &signature.output { - self.word(" -> "); - self.ty(ty); - } - } - - fn fn_arg(&mut self, fn_arg: &syn::FnArg) { - if let syn::FnArg::Typed(pat_type) = fn_arg { - self.pat_type(pat_type); - } - } - - fn pat_type(&mut self, pat_type: &syn::PatType) { - self.pat(&pat_type.pat); - self.word(": "); - self.ty(&pat_type.ty); - } - - fn pat(&mut self, pat: &syn::Pat) { - match pat { - syn::Pat::Ident(pat_ident) => self.pat_ident(pat_ident), - rest => unimplemented!("{rest:?}"), - } - } - - fn pat_ident(&mut self, pat_ident: &syn::PatIdent) { - self.ident(&pat_ident.ident); - } - - fn ty(&mut self, ty: &syn::Type) { - match ty { - syn::Type::Path(ty) => self.type_path(ty), - syn::Type::Ptr(ptr) => self.type_ptr(ptr), - syn::Type::Array(array) => self.type_array(array), - rest => unimplemented!("{rest:?}"), - } - } - - fn type_array(&mut self, array: &syn::TypeArray) { - self.word("["); - self.ty(&array.elem); - self.word("; "); - self.expr(&array.len); - self.word("]"); - } - - fn expr(&mut self, expr: &syn::Expr) { - match expr { - syn::Expr::Lit(lit) => self.expr_lit(lit), - syn::Expr::Unary(unary) => self.expr_unary(unary), - rest => unimplemented!("{rest:?}"), - } - } - - fn expr_unary(&mut self, unary: &syn::ExprUnary) { - self.word("-"); - self.expr(&unary.expr); - } - - fn expr_lit(&mut self, expr: &syn::ExprLit) { - self.lit(&expr.lit); - } - - fn lit(&mut self, lit: &syn::Lit) { - match lit { - syn::Lit::Int(lit) => self.lit_int(lit), - syn::Lit::Str(lit) => self.lit_str(lit), - _ => _ = dbg!(lit), - } - } - - fn lit_str(&mut self, lit: &syn::LitStr) { - self.word("\""); - self.word(&lit.value()); - self.word("\""); - } - - fn lit_int(&mut self, lit: &syn::LitInt) { - self.word(&lit.token().to_string()); - } - - fn type_ptr(&mut self, ptr: &syn::TypePtr) { - if ptr.mutability.is_some() { - self.word("*mut "); - } else { - self.word("*const "); - } - self.ty(&ptr.elem); - } - - fn type_path(&mut self, ty: &syn::TypePath) { - self.path(&ty.path); - } - - fn path(&mut self, path: &syn::Path) { - let mut first = true; - for segment in &path.segments { - if first { - first = false; - } else { - self.word("::"); - } - self.path_segment(segment); - } - } - - pub fn path_segment(&mut self, segment: &syn::PathSegment) { - self.ident(&segment.ident); - - if let syn::PathArguments::AngleBracketed(args) = &segment.arguments { - self.word("<"); - - let mut first = true; - for arg in &args.args { - if first { - first = false; - } else { - self.word(", "); - } - self.generic_argument(arg); - } - - self.word(">"); - } - } - - fn generic_argument(&mut self, arg: &syn::GenericArgument) { - match arg { - syn::GenericArgument::Type(ty) => self.ty(ty), - rest => unimplemented!("{rest:?}"), - } - } - - fn item_use(&mut self, item: &syn::ItemUse) { - self.word("use "); - self.use_tree(&item.tree); - self.word(";"); - self.newline(); - } - - fn use_tree(&mut self, use_tree: &syn::UseTree) { - match use_tree { - syn::UseTree::Path(use_path) => self.use_path(use_path), - syn::UseTree::Name(use_name) => self.use_name(use_name), - _ => {} - } - } - - fn use_path(&mut self, use_path: &syn::UsePath) { - self.ident(&use_path.ident); - self.word("::"); - self.use_tree(&use_path.tree); - } - - fn use_name(&mut self, use_name: &syn::UseName) { - self.ident(&use_name.ident); - } - - pub fn ident(&mut self, ident: &syn::Ident) { - self.word(&ident.to_string()); - } -} diff --git a/crates/tools/riddle/src/rdl/from_reader.rs b/crates/tools/riddle/src/rdl/from_reader.rs deleted file mode 100644 index f877912e63..0000000000 --- a/crates/tools/riddle/src/rdl/from_reader.rs +++ /dev/null @@ -1,479 +0,0 @@ -use super::*; -use crate::tokens::{quote, to_ident, TokenStream}; -use crate::{rdl, Error, Result, Tree}; -use metadata::RowReader; - -pub fn from_reader( - reader: &metadata::Reader, - filter: &metadata::Filter, - mut config: std::collections::BTreeMap<&str, &str>, - output: &str, -) -> Result<()> { - let dialect = match config.remove("TYPE") { - Some("winrt") => Dialect::WinRT, - Some("win32") => Dialect::Win32, - _ => { - return Err(Error::new( - "configuration value `TYPE` must be `win32` or `winrt`", - )) - } - }; - - let mut writer = Writer::new(reader, filter, output, dialect); - - // TODO: be sure to use the same "SPLIT" key for winmd splitting. - // May also want to support SPLIT=N similar to the way MIDLRT supports winmd splitting - // at different nesting levels. - writer.split = config.remove("SPLIT").is_some(); - - if let Some((key, _)) = config.first_key_value() { - return Err(Error::new(&format!("invalid configuration value `{key}`"))); - } - - if writer.split { - gen_split(&writer) - } else { - gen_file(&writer) - } -} - -fn gen_split(writer: &Writer) -> Result<()> { - let tree = Tree::new(writer.reader, writer.filter); - let directory = crate::directory(writer.output); - - // TODO: parallelize - for tree in tree.flatten() { - let tokens = writer.tree(tree); - - if !tokens.is_empty() { - let output = format!("{directory}/{}.rdl", tree.namespace); - writer.write_to_file(&output, tokens)?; - } - } - - Ok(()) -} - -fn gen_file(writer: &Writer) -> Result<()> { - let tree = Tree::new(writer.reader, writer.filter); - let tokens = writer.tree(&tree); - writer.write_to_file(writer.output, tokens) -} - -#[derive(Debug, Copy, Clone, PartialEq)] -enum Dialect { - Win32, - WinRT, -} - -struct Writer<'a> { - reader: &'a metadata::Reader<'a>, - filter: &'a metadata::Filter<'a>, - namespace: &'a str, - dialect: Dialect, - split: bool, - output: &'a str, -} - -impl<'a> Writer<'a> { - fn new( - reader: &'a metadata::Reader, - filter: &'a metadata::Filter, - output: &'a str, - dialect: Dialect, - ) -> Self { - Self { - reader, - filter, - namespace: "", - output, - dialect, - split: false, - } - } - - fn with_namespace(&self, namespace: &'a str) -> Self { - Self { - reader: self.reader, - filter: self.filter, - namespace, - dialect: self.dialect, - output: self.output, - split: self.split, - } - } - - fn write_to_file(&self, output: &str, tokens: TokenStream) -> Result<()> { - let dialect = match self.dialect { - Dialect::Win32 => quote! { #![win32] }, - Dialect::WinRT => quote! { #![winrt] }, - }; - - let tokens = quote! { - #dialect - #tokens - }; - - let file = rdl::File::parse_str(&tokens.into_string())?; - crate::write_to_file(output, file.fmt()) - //crate::write_to_file(output, tokens.into_string()) - } - - fn tree(&self, tree: &'a Tree) -> TokenStream { - let items = self.items(tree); - - if self.split { - let mut tokens = items; - - if !tokens.is_empty() { - for name in tree.namespace.rsplit('.').map(to_ident) { - tokens = quote! { - mod #name { - #tokens - } - }; - } - } - - tokens - } else { - let name = to_ident( - tree.namespace - .rsplit_once('.') - .map_or(tree.namespace, |(_, name)| name), - ); - - let modules = tree - .nested - .values() - .map(|tree| self.with_namespace(tree.namespace).tree(tree)); - - if tree.namespace.is_empty() { - quote! { - #(#modules)* - #items - } - } else { - quote! { - mod #name { - #(#modules)* - #items - } - } - } - } - } - - fn items(&self, tree: &'a Tree) -> TokenStream { - let mut functions = vec![]; - let mut constants = vec![]; - let mut types = vec![]; - - if !tree.namespace.is_empty() { - for item in self - .reader - .namespace_items(tree.namespace, self.filter) - .filter(|item| match item { - metadata::Item::Type(def) => { - let winrt = self - .reader - .type_def_flags(*def) - .contains(metadata::TypeAttributes::WindowsRuntime); - match self.dialect { - Dialect::Win32 => !winrt, - Dialect::WinRT => winrt, - } - } - metadata::Item::Fn(_, _) | metadata::Item::Const(_) => { - self.dialect == Dialect::Win32 - } - }) - { - match item { - metadata::Item::Type(def) => types.push(self.type_def(def)), - metadata::Item::Const(field) => constants.push(self.constant(field)), - metadata::Item::Fn(method, namespace) => { - functions.push(self.function(method, &namespace)) - } - } - } - } - - quote! { - #(#functions)* - #(#constants)* - #(#types)* - } - } - - fn function(&self, def: metadata::MethodDef, _namespace: &str) -> TokenStream { - let name = to_ident(self.reader.method_def_name(def)); - quote! { fn #name(); } - } - - fn constant(&self, def: metadata::Field) -> TokenStream { - let name = to_ident(self.reader.field_name(def)); - quote! { const #name: i32 = 0; } - } - - fn type_def(&self, def: metadata::TypeDef) -> TokenStream { - if let Some(extends) = self.reader.type_def_extends(def) { - if extends.namespace == "System" { - if extends.name == "Enum" { - self.enum_def(def) - } else if extends.name == "ValueType" { - self.struct_def(def) - } else if extends.name == "MulticastDelegate" { - self.delegate_def(def) - } else { - self.class_def(def) - } - } else { - self.class_def(def) - } - } else { - self.interface_def(def) - } - } - - fn enum_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(self.reader.type_def_name(def)); - - quote! { - struct #name { - - } - } - } - - fn struct_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(self.reader.type_def_name(def)); - - let fields = self.reader.type_def_fields(def).map(|field| { - let name = to_ident(self.reader.field_name(field)); - let ty = self.ty(&self.reader.field_type(field, Some(def))); - quote! { - #name: #ty - } - }); - - quote! { - struct #name { - #(#fields),* - } - } - } - - fn delegate_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(self.reader.type_def_name(def)); - - quote! { - struct #name { - - } - } - } - - fn class_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(self.reader.type_def_name(def)); - let implements = self.implements(def, &[]); - - quote! { - class #name #implements; - } - } - - fn interface_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(self.reader.type_def_name(def)); - let generics = &metadata::type_def_generics(self.reader, def); - let implements = self.implements(def, generics); - - let methods = self.reader.type_def_methods(def).map(|method| { - let name = to_ident(self.reader.method_def_name(method)); - - // TODO: use reader.method_def_signature instead - let signature = metadata::method_def_signature( - self.reader, - self.reader.type_def_namespace(def), - method, - generics, - ); - - let return_type = self.return_type(&signature.return_type); - - let params = signature.params.iter().map(|param| { - let name = to_ident(self.reader.param_name(param.def)); - let ty = self.ty(¶m.ty); - quote! { #name: #ty } - }); - - quote! { - fn #name(#(#params),*) #return_type; - } - }); - - let generics = self.generics(generics); - - quote! { - interface #name #generics #implements { - #(#methods)* - } - } - } - - fn generics(&self, generics: &[metadata::Type]) -> TokenStream { - if generics.is_empty() { - quote! {} - } else { - let generics = generics.iter().map(|generic| self.ty(generic)); - - quote! { <#(#generics),*>} - } - } - - fn implements(&self, def: metadata::TypeDef, generics: &[metadata::Type]) -> TokenStream { - let mut types = Vec::::new(); - - // TODO: if a winrt composable class then start with base - // TODO: then list default interface first - // Then everything else - - for imp in self.reader.type_def_interface_impls(def) { - let ty = self.reader.interface_impl_type(imp, generics); - if self.reader.has_attribute(imp, "DefaultAttribute") { - types.insert(0, ty); - } else { - types.push(ty); - } - } - - if types.is_empty() { - quote! {} - } else { - let types = types.iter().map(|ty| self.ty(ty)); - quote! { : #(#types),* } - } - } - - fn return_type(&self, ty: &metadata::Type) -> TokenStream { - match ty { - metadata::Type::Void => quote! {}, - _ => { - let ty = self.ty(ty); - quote! { -> #ty } - } - } - } - - fn ty(&self, ty: &metadata::Type) -> TokenStream { - match ty { - metadata::Type::Void => quote! { ::core::ffi::c_void }, - metadata::Type::Bool => quote! { bool }, - metadata::Type::Char => quote! { u16 }, - metadata::Type::I8 => quote! { i8 }, - metadata::Type::U8 => quote! { u8 }, - metadata::Type::I16 => quote! { i16 }, - metadata::Type::U16 => quote! { u16 }, - metadata::Type::I32 => quote! { i32 }, - metadata::Type::U32 => quote! { u32 }, - metadata::Type::I64 => quote! { i64 }, - metadata::Type::U64 => quote! { u64 }, - metadata::Type::F32 => quote! { f32 }, - metadata::Type::F64 => quote! { f64 }, - metadata::Type::ISize => quote! { isize }, - metadata::Type::USize => quote! { usize }, - - // TODO: dialect-specific keywords for "well-known types" that don't map to metadata in all cases. - metadata::Type::String => quote! { HSTRING }, - metadata::Type::HRESULT => quote! { HRESULT }, - metadata::Type::GUID => quote! { GUID }, - metadata::Type::IInspectable => quote! { IInspectable }, - metadata::Type::IUnknown => quote! { IUnknown }, - - metadata::Type::TypeDef(def, generics) => { - let namespace = self.namespace(self.reader.type_def_namespace(*def)); - let name = to_ident(self.reader.type_def_name(*def)); - if generics.is_empty() { - quote! { #namespace #name } - } else { - let generics = generics.iter().map(|ty| self.ty(ty)); - quote! { #namespace #name<#(#generics,)*> } - } - } - - metadata::Type::TypeRef(code) => { - let type_name = self.reader.type_def_or_ref(*code); - let namespace = self.namespace(type_name.namespace); - let name = to_ident(type_name.name); - quote! { #namespace #name } - } - - metadata::Type::GenericParam(generic) => { - self.reader.generic_param_name(*generic).into() - } - metadata::Type::WinrtArray(ty) => self.ty(ty), - metadata::Type::WinrtArrayRef(ty) => self.ty(ty), - metadata::Type::ConstRef(ty) => self.ty(ty), - metadata::Type::MutPtr(ty, _pointers) => self.ty(ty), - metadata::Type::ConstPtr(ty, _pointers) => self.ty(ty), - metadata::Type::Win32Array(ty, _len) => self.ty(ty), - // TODO: these types should just be regular metadata type defs - metadata::Type::PSTR => quote! { PSTR }, - metadata::Type::PWSTR => quote! { PWSTR }, - metadata::Type::PCSTR => quote! { PCSTR }, - metadata::Type::PCWSTR => quote! { PCWSTR }, - metadata::Type::BSTR => quote! { BSTR }, - metadata::Type::PrimitiveOrEnum(_, ty) => self.ty(ty), - rest => unimplemented!("{rest:?}"), - } - } - - fn namespace(&self, namespace: &str) -> TokenStream { - // TODO: handle nested structs? - if namespace.is_empty() || self.namespace == namespace { - quote! {} - } else { - // TODO: problem with making relative paths here is that we don't have the context to disambiguate - - // let mut relative = self.namespace.split('.').peekable(); - // let mut namespace = namespace.split('.').peekable(); - // let mut related = false; - - // while relative.peek() == namespace.peek() { - // related = true; - - // if relative.next().is_none() { - // break; - // } - - // namespace.next(); - // } - - // let mut tokens = TokenStream::new(); - - // if related { - // for _ in 0..relative.count() { - // tokens.push_str("super::"); - // } - // } - - // for namespace in namespace { - // tokens.push_str(namespace); - // tokens.push_str("::"); - // } - - // tokens - - // TODO: so instead we just gen it out in full - - let mut tokens = TokenStream::new(); - - for namespace in namespace.split('.') { - tokens.push_str(namespace); - tokens.push_str("::"); - } - - tokens - } - } -} diff --git a/crates/tools/riddle/src/rdl/mod.rs b/crates/tools/riddle/src/rdl/mod.rs deleted file mode 100644 index b206866ec4..0000000000 --- a/crates/tools/riddle/src/rdl/mod.rs +++ /dev/null @@ -1,399 +0,0 @@ -use super::*; -mod fmt; -mod from_reader; -mod to_winmd; -use crate::Result; -pub use from_reader::from_reader; -use syn::spanned::Spanned; - -// TODO: may want to finally get rid of `syn` as it also doesn't support preserving code comments - -impl File { - pub fn parse_str(input: &str) -> Result { - Ok(syn::parse_str::(input)?) - } - - // Note: this isn't called automatically by `parse_str` to avoid canonicalizing when we're merely formatting IDL. - pub fn canonicalize(&mut self) -> Result<()> { - // TODO maybe we rewrite the `File` here to resolve any `super` references and use declarations so that - // subsequently the rdl-to-winmd conversion can just assume everything's fully qualified? - // * super can't refer to something outside of the IDL file - // * use declarations are only used for unqualified names that aren't defined in the IDL file - // * use declarations don't support globs and must name all externally defined types - // This way we can quickly kick out common invalid IDL files before we lost file/span context info - - Ok(()) - } - - pub fn fmt(&self) -> String { - fmt::Writer::new(self).into_string() - } - - pub fn into_winmd(mut self) -> Result> { - self.canonicalize()?; - to_winmd::rdl_to_winmd(&self) - } -} - -// The value of the IDL-specific memory representation is that it allows for constructs that are not modeled in the abstract Module -// tree such as the use declarations and if we get rid of it we'd always "format" IDL by stripping out any of that into a single -// canonical form which would not be very friendly to developers. -#[derive(Debug)] -pub struct File { - pub winrt: bool, - pub references: Vec, - pub modules: Vec, -} - -// TODO: need to change these to unpack the syn types and store strings we can reference for efficiency along with spans since the syn -// is made for value semantics. - -#[derive(Clone, Debug)] -pub struct Module { - pub namespace: String, - pub members: Vec, -} - -#[derive(Clone, Debug)] -pub enum ModuleMember { - Module(Module), - Interface(Interface), - Struct(Struct), - Enum(Enum), - Class(Class), - Function(Function), - Constant(Constant), -} - -impl ModuleMember { - pub fn name(&self) -> &str { - match self { - Self::Module(module) => crate::extension(&module.namespace), - Self::Interface(member) => &member.name, - Self::Struct(member) => &member.name, - Self::Enum(member) => &member.name, - Self::Class(member) => &member.name, - Self::Function(member) => &member.name, - Self::Constant(member) => &member.name, - } - } -} - -#[derive(Clone, Debug)] -pub struct Enum { - pub winrt: bool, - pub name: String, - pub item: syn::ItemEnum, -} - -#[derive(Clone, Debug)] -pub struct Constant { - pub name: String, - pub item: syn::ItemConst, -} - -#[derive(Clone, Debug)] -pub struct Struct { - pub winrt: bool, - pub name: String, - pub attributes: Vec, - pub span: proc_macro2::Span, - pub fields: Vec, -} - -#[derive(Clone, Debug)] -pub struct Field { - pub name: String, - pub attributes: Vec, - pub span: proc_macro2::Span, - pub ty: syn::Type, -} - -#[derive(Clone, Debug)] -pub struct Class { - pub name: String, - pub attributes: Vec, - pub extends: Vec, -} - -#[derive(Clone, Debug)] -pub struct Function { - pub name: String, - pub item: syn::TraitItemFn, -} - -#[derive(Clone, Debug)] -pub struct Interface { - pub winrt: bool, - pub name: String, - pub generics: Vec, - pub attributes: Vec, - pub extends: Vec, - pub methods: Vec, -} - -syn::custom_keyword!(interface); -syn::custom_keyword!(class); - -fn winrt(input: syn::parse::ParseStream) -> syn::Result { - let attributes = input.call(syn::Attribute::parse_inner)?; - if attributes.len() == 1 { - if let syn::Meta::Path(path) = &attributes[0].meta { - if path.is_ident("winrt") { - return Ok(true); - } - - if path.is_ident("win32") { - return Ok(false); - } - } - } - - Err(syn::Error::new( - input.span(), - "A single `#![win32]` or `#![winrt]` attribute required", - )) -} - -impl syn::parse::Parse for File { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let mut references = vec![]; - let mut modules = vec![]; - let winrt = winrt(input)?; - - while !input.is_empty() { - let lookahead = input.lookahead1(); - if lookahead.peek(syn::Token![mod]) { - modules.push(Module::parse("", winrt, input)?); - } else if lookahead.peek(syn::Token![use]) { - references.push(input.parse()?); - } else { - return Err(lookahead.error()); - } - } - Ok(Self { - winrt, - references, - modules, - }) - } -} - -impl Module { - fn name(&self) -> &str { - self.namespace - .rsplit_once('.') - .map_or(&self.namespace, |(_, name)| name) - } - - fn parse(namespace: &str, winrt: bool, input: syn::parse::ParseStream) -> syn::Result { - input.parse::()?; - let name = input.parse::()?.to_string(); - - let namespace = if namespace.is_empty() { - name.to_string() - } else { - format!("{namespace}.{name}") - }; - - let content; - syn::braced!(content in input); - let mut members = vec![]; - while !content.is_empty() { - members.push(ModuleMember::parse(&namespace, winrt, &content)?); - } - Ok(Self { namespace, members }) - } -} - -impl ModuleMember { - fn parse(namespace: &str, winrt: bool, input: syn::parse::ParseStream) -> syn::Result { - let attributes: Vec = input.call(syn::Attribute::parse_outer)?; - let lookahead = input.lookahead1(); - if lookahead.peek(syn::Token![mod]) { - if let Some(attribute) = attributes.first() { - return Err(syn::Error::new( - attribute.span(), - "`use` attributes not supported", - )); - } - Ok(ModuleMember::Module(Module::parse( - namespace, winrt, input, - )?)) - } else if lookahead.peek(interface) { - Ok(ModuleMember::Interface(Interface::parse( - namespace, winrt, attributes, input, - )?)) - } else if lookahead.peek(syn::Token![struct]) { - Ok(ModuleMember::Struct(Struct::parse( - namespace, winrt, attributes, input, - )?)) - } else if lookahead.peek(syn::Token![enum]) { - Ok(ModuleMember::Enum(Enum::parse( - namespace, winrt, attributes, input, - )?)) - } else if lookahead.peek(class) { - Ok(ModuleMember::Class(Class::parse(attributes, input)?)) - } else if lookahead.peek(syn::Token![fn]) { - Ok(ModuleMember::Function(Function::parse( - namespace, attributes, input, - )?)) - } else if lookahead.peek(syn::Token![const]) { - Ok(ModuleMember::Constant(Constant::parse( - namespace, attributes, input, - )?)) - } else { - Err(lookahead.error()) - } - } -} - -impl Class { - fn parse(attributes: Vec, input: syn::parse::ParseStream) -> syn::Result { - input.parse::()?; - let name = input.parse::()?.to_string(); - let mut extends = Vec::new(); - - if input.peek(syn::Token![:]) { - input.parse::()?; - while !input.peek(syn::Token![;]) { - extends.push(input.parse()?); - _ = input.parse::(); - } - } - - input.parse::()?; - Ok(Self { - attributes, - name, - extends, - }) - } -} - -impl Interface { - fn parse( - _namespace: &str, - winrt: bool, - attributes: Vec, - input: syn::parse::ParseStream, - ) -> syn::Result { - input.parse::()?; - let name = input.parse::()?.to_string(); - - let mut generics = Vec::new(); - - if input.peek(syn::Token![<]) { - input.parse::()?; - while input.peek(syn::Ident) { - generics.push(input.parse::()?.to_string()); - _ = input.parse::(); - } - - input.parse::]>()?; - } - - let mut extends = Vec::new(); - - if input.peek(syn::Token![:]) { - input.parse::()?; - while !input.peek(syn::token::Brace) { - extends.push(input.parse()?); - _ = input.parse::(); - } - } - - let content; - syn::braced!(content in input); - let mut methods = vec![]; - while !content.is_empty() { - methods.push(content.parse()?); - } - Ok(Self { - winrt, - attributes, - generics, - extends, - name, - methods, - }) - } -} - -impl Struct { - fn parse( - _namespace: &str, - winrt: bool, - attributes: Vec, - input: syn::parse::ParseStream, - ) -> syn::Result { - // TODO: need to validate that the struct is valid according to the constraints of the winmd type system. - // Same for the other types. That way we can spit out errors quickly for things like unnamed fields. - let span = input.span(); - let item: syn::ItemStruct = input.parse()?; - let name = item.ident.to_string(); - let mut fields = vec![]; - - let syn::Fields::Named(named) = item.fields else { - return Err(syn::Error::new(item.span(), "unnamed fields not supported")); - }; - - for field in named.named { - fields.push(Field { - span: field.span(), - attributes: field.attrs, - // Simply unwrapping since we already know that it is a named field. - name: field.ident.unwrap().to_string(), - ty: field.ty, - }); - } - - Ok(Self { - winrt, - name, - attributes, - span, - fields, - }) - } -} - -impl Enum { - fn parse( - _namespace: &str, - winrt: bool, - attributes: Vec, - input: syn::parse::ParseStream, - ) -> syn::Result { - let mut item: syn::ItemEnum = input.parse()?; - item.attrs = attributes; - let name = item.ident.to_string(); - Ok(Self { winrt, name, item }) - } -} - -impl Constant { - fn parse( - _namespace: &str, - attributes: Vec, - input: syn::parse::ParseStream, - ) -> syn::Result { - let mut item: syn::ItemConst = input.parse()?; - item.attrs = attributes; - let name = item.ident.to_string(); - Ok(Self { name, item }) - } -} - -impl Function { - fn parse( - _namespace: &str, - attributes: Vec, - input: syn::parse::ParseStream, - ) -> syn::Result { - let mut item: syn::TraitItemFn = input.parse()?; - item.attrs = attributes; - let name = item.sig.ident.to_string(); - Ok(Self { name, item }) - } -} diff --git a/crates/tools/riddle/src/rdl/to_winmd.rs b/crates/tools/riddle/src/rdl/to_winmd.rs deleted file mode 100644 index fc80b2d7a6..0000000000 --- a/crates/tools/riddle/src/rdl/to_winmd.rs +++ /dev/null @@ -1,395 +0,0 @@ -use super::*; -use crate::winmd::{self, writer}; -use crate::{rdl, Result}; - -// TODO: store span in winmd so that errors resolving type references can be traced back to file/line/column -use std::collections::HashMap; -//use syn::spanned::Spanned; - -// TODO: this creates a temporary in-memory winmd used to treat the IDL content uniformly as metadata. -// The winmd_to_winmd does the harder job of validating and producing canonical winmd for public consumption. - -pub fn rdl_to_winmd(file: &rdl::File) -> Result> { - // Local-to-qualified type names found in use declaration - e.g. "IStringable" -> "Windows.Foundation.IStringable" - // This is just a convenience for the developer to shorten common references like this but would not support globs or renames. - // Note that none of these are verified to be real until much later when the winmd is validated since we don't - // know what other metadata may be combined - let mut _use_map = HashMap::::new(); - - // TODO: read file and populate use_map - - // Types are collected here in two passes - this allows us to figure out whether a local name points to a relative type - // or a type from a use declaration...? - let mut collector = HashMap::>::new(); - - file.modules - .iter() - .for_each(|module| collect_module(&mut collector, module)); - - // TODO: collect type names into hashmap (phase 1) and just drop clones of the IDL members into the collector - - // TODO: Can we just walk the collector at this point and populate the winmd writer and thus need the read-phase? - // this second walking of the collector is basically the "define" phase - - let mut writer = winmd::Writer::new("temp.winmd"); - - collector.iter().for_each(|(namespace, members)| { - members - .iter() - .for_each(|(name, member)| write_member(&mut writer, namespace, name, member)) - }); - - Ok(writer.into_stream()) -} - -fn collect_module<'a>( - collector: &mut HashMap>, - module: &'a rdl::Module, -) { - module - .members - .iter() - .for_each(|member| collect_member(collector, module, member)); -} - -fn collect_member<'a>( - collector: &mut HashMap>, - module: &'a rdl::Module, - member: &'a rdl::ModuleMember, -) { - match member { - rdl::ModuleMember::Module(module) => collect_module(collector, module), - rdl::ModuleMember::Constant(_) | rdl::ModuleMember::Function(_) => { - collector - .entry(module.namespace.to_string()) - .or_default() - .entry("Apis") - .or_insert(member.clone()); - } - _ => { - collector - .entry(module.namespace.to_string()) - .or_default() - .entry(member.name()) - .or_insert(member.clone()); - } - } -} - -fn write_member( - writer: &mut winmd::Writer, - namespace: &str, - name: &str, - member: &rdl::ModuleMember, -) { - match member { - rdl::ModuleMember::Interface(member) => write_interface(writer, namespace, name, member), - rdl::ModuleMember::Struct(member) => write_struct(writer, namespace, name, member), - rdl::ModuleMember::Enum(member) => write_enum(writer, namespace, name, member), - rdl::ModuleMember::Class(member) => write_class(writer, namespace, name, member), - rest => unimplemented!("{rest:?}"), - } -} - -fn write_interface( - writer: &mut winmd::Writer, - namespace: &str, - name: &str, - member: &rdl::Interface, -) { - let mut flags = metadata::TypeAttributes::Public - | metadata::TypeAttributes::Interface - | metadata::TypeAttributes::Abstract; - - if member.winrt { - flags |= metadata::TypeAttributes::WindowsRuntime - } - - writer.tables.TypeDef.push(winmd::TypeDef { - Extends: 0, - FieldList: writer.tables.Field.len() as u32, - MethodList: writer.tables.MethodDef.len() as u32, - Flags: flags.0, - TypeName: writer.strings.insert(name), - TypeNamespace: writer.strings.insert(namespace), - }); - - for (number, generic) in member.generics.iter().enumerate() { - writer.tables.GenericParam.push(writer::GenericParam { - Number: number as u16, - Flags: 0, - Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1) - .encode(), - Name: writer.strings.insert(generic), - }); - } - - for type_path in &member.extends { - let ty = syn_type_path(namespace, &member.generics, type_path); - - let reference = match &ty { - winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => { - writer.insert_type_ref(&type_name.namespace, &type_name.name) - } - winmd::Type::TypeRef(_) => writer.insert_type_spec(ty), - rest => unimplemented!("{rest:?}"), - }; - - writer.tables.InterfaceImpl.push(writer::InterfaceImpl { - Class: writer.tables.TypeDef.len() as u32 - 1, - Interface: reference, - }); - } - - for method in &member.methods { - let signature = syn_signature(namespace, &member.generics, &method.sig); - - let params: Vec = signature - .params - .iter() - .map(|param| param.ty.clone()) - .collect(); - - let signature_blob = writer.insert_method_sig( - metadata::MethodCallAttributes(0), - &signature.return_type, - ¶ms, - ); - - let flags = metadata::MethodAttributes::Abstract - | metadata::MethodAttributes::HideBySig - | metadata::MethodAttributes::HideBySig - | metadata::MethodAttributes::NewSlot - | metadata::MethodAttributes::Public - | metadata::MethodAttributes::Virtual; - - writer.tables.MethodDef.push(winmd::MethodDef { - RVA: 0, - ImplFlags: 0, - Flags: flags.0, - Name: writer.strings.insert(&method.sig.ident.to_string()), - Signature: signature_blob, - ParamList: writer.tables.Param.len() as u32, - }); - - for (sequence, param) in signature.params.iter().enumerate() { - writer.tables.Param.push(winmd::Param { - Flags: 0, - Sequence: (sequence + 1) as u16, - Name: writer.strings.insert(¶m.name), - }); - } - } -} - -fn write_struct(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &rdl::Struct) { - let mut flags = metadata::TypeAttributes::Public - | metadata::TypeAttributes::Sealed - | metadata::TypeAttributes::SequentialLayout; - - if member.winrt { - flags |= metadata::TypeAttributes::WindowsRuntime - } - - let extends = writer.insert_type_ref("System", "ValueType"); - - writer.tables.TypeDef.push(winmd::TypeDef { - Extends: extends, - FieldList: writer.tables.Field.len() as u32, - MethodList: writer.tables.MethodDef.len() as u32, - Flags: flags.0, - TypeName: writer.strings.insert(name), - TypeNamespace: writer.strings.insert(namespace), - }); - - for field in &member.fields { - let flags = metadata::FieldAttributes::Public; - let ty = syn_type(namespace, &[], &field.ty); - let signature = writer.insert_field_sig(&ty); - - writer.tables.Field.push(winmd::Field { - Flags: flags.0, - Name: writer.strings.insert(&field.name), - Signature: signature, - }); - } -} - -fn write_enum(_writer: &mut winmd::Writer, _namespace: &str, _name: &str, _member: &rdl::Enum) {} - -fn write_class(writer: &mut winmd::Writer, namespace: &str, name: &str, _member: &rdl::Class) { - let flags = metadata::TypeAttributes::Public - | metadata::TypeAttributes::Sealed - | metadata::TypeAttributes::WindowsRuntime; - - let extends = writer.insert_type_ref("System", "Object"); - - writer.tables.TypeDef.push(winmd::TypeDef { - Extends: extends, - // Even though ECMA-335 says these can be "null", bugs in ILDASM necessitate this to avoid "misreading" the list terminators. - FieldList: writer.tables.Field.len() as u32, - MethodList: writer.tables.MethodDef.len() as u32, - Flags: flags.0, - TypeName: writer.strings.insert(name), - TypeNamespace: writer.strings.insert(namespace), - }); -} - -fn syn_signature(namespace: &str, generics: &[String], sig: &syn::Signature) -> winmd::Signature { - let params = sig - .inputs - .iter() - .map(|param| match param { - syn::FnArg::Typed(pat_type) => { - let name = match &*pat_type.pat { - syn::Pat::Ident(pat_ident) => pat_ident.ident.to_string(), - rest => unimplemented!("{rest:?}"), - }; - let ty = syn_type(namespace, generics, &pat_type.ty); - winmd::SignatureParam { name, ty } - } - rest => unimplemented!("{rest:?}"), - }) - .collect(); - - let return_type = if let syn::ReturnType::Type(_, ty) = &sig.output { - syn_type(namespace, generics, ty) - } else { - winmd::Type::Void - }; - - winmd::Signature { - params, - return_type, - call_flags: 0, - } -} - -fn syn_type(namespace: &str, generics: &[String], ty: &syn::Type) -> winmd::Type { - match ty { - syn::Type::Path(ty) => syn_type_path(namespace, generics, ty), - syn::Type::Ptr(ptr) => syn_type_ptr(namespace, ptr), - syn::Type::Array(array) => syn_type_array(namespace, array), - rest => unimplemented!("{rest:?}"), - } -} - -fn syn_type_array(namespace: &str, array: &syn::TypeArray) -> winmd::Type { - let ty = syn_type(namespace, &[], &array.elem); - - if let syn::Expr::Lit(lit) = &array.len { - if let syn::Lit::Int(lit) = &lit.lit { - if let Ok(len) = lit.base10_parse() { - return ty.into_array(len); - } - } - } - - unimplemented!() -} - -fn syn_type_ptr(namespace: &str, ptr: &syn::TypePtr) -> winmd::Type { - let ty = syn_type(namespace, &[], &ptr.elem); - if ptr.mutability.is_some() { - ty.into_mut_ptr() - } else { - ty.into_const_ptr() - } -} - -fn syn_type_path(namespace: &str, generics: &[String], ty: &syn::TypePath) -> winmd::Type { - if ty.qself.is_none() { - return syn_path(namespace, generics, &ty.path); - } - - unimplemented!() -} - -fn syn_path(namespace: &str, generics: &[String], path: &syn::Path) -> winmd::Type { - if let Some(segment) = path.segments.first() { - if path.segments.len() == 1 && segment.arguments.is_empty() { - let name = segment.ident.to_string(); - - if let Some(number) = generics.iter().position(|generic| generic == &name) { - return winmd::Type::GenericParam(number as u16); - } - - match name.as_str() { - "void" => return winmd::Type::Void, - "bool" => return winmd::Type::Bool, - "char" => return winmd::Type::Char, - "i8" => return winmd::Type::I8, - "u8" => return winmd::Type::U8, - "i16" => return winmd::Type::I16, - "u16" => return winmd::Type::U16, - "i32" => return winmd::Type::I32, - "u32" => return winmd::Type::U32, - "i64" => return winmd::Type::I64, - "u64" => return winmd::Type::U64, - "f32" => return winmd::Type::F32, - "f64" => return winmd::Type::F64, - "isize" => return winmd::Type::ISize, - "usize" => return winmd::Type::USize, - "HSTRING" => return winmd::Type::String, - "GUID" => return winmd::Type::GUID, - "IUnknown" => return winmd::Type::IUnknown, - "IInspectable" => return winmd::Type::IInspectable, - "HRESULT" => return winmd::Type::HRESULT, - "PSTR" => return winmd::Type::PSTR, - "PWSTR" => return winmd::Type::PWSTR, - "PCSTR" => return winmd::Type::PCSTR, - "PCWSTR" => return winmd::Type::PCWSTR, - "BSTR" => return winmd::Type::BSTR, - _ => {} - }; - } - } - - // TODO: Here we assume that paths are absolute since there's no way to disambiguate between nested and absolute paths - // The canonicalize function (should maybe) preprocesses the IDL to make this work - - let mut builder = vec![]; - - for segment in &path.segments { - let segment = segment.ident.to_string(); - - if segment == "super" { - if builder.is_empty() { - for segment in namespace.split('.') { - builder.push(segment.to_string()); - } - } - builder.pop(); - } else { - builder.push(segment); - } - } - - // Unwrapping is fine as there should always be at least one segment. - let (name, type_namespace) = builder.split_last().unwrap(); - let type_namespace = if type_namespace.is_empty() { - namespace.to_string() - } else { - type_namespace.join(".") - }; - let mut type_generics = vec![]; - - if let Some(segment) = path.segments.last() { - if let syn::PathArguments::AngleBracketed(args) = &segment.arguments { - for arg in &args.args { - match arg { - syn::GenericArgument::Type(ty) => { - type_generics.push(syn_type(namespace, generics, ty)) - } - rest => unimplemented!("{rest:?}"), - } - } - } - } - - winmd::Type::TypeRef(winmd::TypeName { - namespace: type_namespace, - name: name.to_string(), - generics: type_generics, - }) -} diff --git a/crates/tools/riddle/src/rust/cfg.rs b/crates/tools/riddle/src/rust/cfg.rs deleted file mode 100644 index ba5e9d0dd1..0000000000 --- a/crates/tools/riddle/src/rust/cfg.rs +++ /dev/null @@ -1,203 +0,0 @@ -use super::*; - -#[derive(Default, Clone)] -pub struct Cfg<'a> { - pub types: BTreeMap<&'a str, BTreeSet>, - pub core_types: BTreeSet, - pub arches: BTreeSet<&'static str>, - pub implement: bool, -} - -impl<'a> Cfg<'a> { - pub fn add_feature(&mut self, feature: &'a str) { - self.types.entry(feature).or_default(); - } - pub fn union(&self, other: &Self) -> Self { - let mut union = Self::default(); - self.types.keys().for_each(|feature| { - union.types.entry(feature).or_default(); - }); - other.types.keys().for_each(|feature| { - union.types.entry(feature).or_default(); - }); - self.arches.iter().for_each(|arch| { - union.arches.insert(arch); - }); - other.arches.iter().for_each(|arch| { - union.arches.insert(arch); - }); - union - } -} - -pub fn field_cfg<'a>(reader: &'a Reader<'a>, row: Field) -> Cfg<'a> { - let mut cfg = Cfg::default(); - field_cfg_combine(reader, row, None, &mut cfg); - cfg -} -fn field_cfg_combine<'a>( - reader: &'a Reader, - row: Field, - enclosing: Option, - cfg: &mut Cfg<'a>, -) { - type_cfg_combine(reader, &reader.field_type(row, enclosing), cfg) -} - -pub fn type_def_cfg<'a>(reader: &'a Reader, row: TypeDef, generics: &[Type]) -> Cfg<'a> { - let mut cfg = Cfg::default(); - type_def_cfg_combine(reader, row, generics, &mut cfg); - cfg_add_attributes(reader, &mut cfg, row); - cfg -} -pub fn type_def_cfg_impl<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type]) -> Cfg<'a> { - let mut cfg = Cfg { - implement: true, - ..Default::default() - }; - - fn combine<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type], cfg: &mut Cfg<'a>) { - type_def_cfg_combine(reader, def, generics, cfg); - - for method in reader.type_def_methods(def) { - signature_cfg_combine(reader, &reader.method_def_signature(method, generics), cfg); - } - } - - combine(reader, def, generics, &mut cfg); - - for def in reader.type_def_vtables(def) { - if let Type::TypeDef(def, generics) = def { - combine(reader, def, &generics, &mut cfg); - } - } - - if reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - for interface in reader.type_def_interfaces(def, generics) { - if let Type::TypeDef(def, generics) = interface { - combine(reader, def, &generics, &mut cfg); - } - } - } - - cfg_add_attributes(reader, &mut cfg, def); - cfg -} -pub fn type_def_cfg_combine<'a>( - reader: &'a Reader, - row: TypeDef, - generics: &[Type], - cfg: &mut Cfg<'a>, -) { - let type_name = reader.type_def_type_name(row); - - for generic in generics { - type_cfg_combine(reader, generic, cfg); - } - - if cfg - .types - .entry(type_name.namespace) - .or_default() - .insert(row) - { - match reader.type_def_kind(row) { - TypeKind::Class => { - if let Some(default_interface) = reader.type_def_default_interface(row) { - type_cfg_combine(reader, &default_interface, cfg); - } - } - TypeKind::Interface => { - if !reader - .type_def_flags(row) - .contains(TypeAttributes::WindowsRuntime) - { - for def in reader.type_def_vtables(row) { - if let Type::TypeDef(def, _) = def { - cfg.add_feature(reader.type_def_namespace(def)); - } - } - } - } - TypeKind::Struct => { - reader - .type_def_fields(row) - .for_each(|field| field_cfg_combine(reader, field, Some(row), cfg)); - if !type_name.namespace.is_empty() { - for def in reader.get_type_def(type_name) { - if def != row { - type_def_cfg_combine(reader, def, &[], cfg); - } - } - } - } - TypeKind::Delegate => signature_cfg_combine( - reader, - &reader.method_def_signature(type_def_invoke_method(reader, row), generics), - cfg, - ), - _ => {} - } - } -} - -pub fn signature_cfg<'a>(reader: &'a Reader, method: MethodDef) -> Cfg<'a> { - let mut cfg = Cfg::default(); - signature_cfg_combine(reader, &reader.method_def_signature(method, &[]), &mut cfg); - cfg_add_attributes(reader, &mut cfg, method); - cfg -} -fn signature_cfg_combine<'a>(reader: &'a Reader, signature: &MethodDefSig, cfg: &mut Cfg<'a>) { - type_cfg_combine(reader, &signature.return_type, cfg); - signature - .params - .iter() - .for_each(|param| type_cfg_combine(reader, param, cfg)); -} - -fn cfg_add_attributes>(reader: &Reader, cfg: &mut Cfg, row: R) { - for attribute in reader.attributes(row) { - match reader.attribute_name(attribute) { - "SupportedArchitectureAttribute" => { - if let Some((_, Value::EnumDef(_, value))) = reader.attribute_args(attribute).get(0) - { - if let Value::I32(value) = **value { - if value & 1 == 1 { - cfg.arches.insert("x86"); - } - if value & 2 == 2 { - cfg.arches.insert("x86_64"); - } - if value & 4 == 4 { - cfg.arches.insert("aarch64"); - } - } - } - } - "DeprecatedAttribute" => { - cfg.add_feature("deprecated"); - } - _ => {} - } - } -} - -pub fn type_cfg<'a>(reader: &'a Reader, ty: &Type) -> Cfg<'a> { - let mut cfg = Cfg::default(); - type_cfg_combine(reader, ty, &mut cfg); - cfg -} -fn type_cfg_combine<'a>(reader: &'a Reader, ty: &Type, cfg: &mut Cfg<'a>) { - match ty { - Type::TypeDef(row, generics) => type_def_cfg_combine(reader, *row, generics, cfg), - Type::Win32Array(ty, _) => type_cfg_combine(reader, ty, cfg), - Type::ConstPtr(ty, _) => type_cfg_combine(reader, ty, cfg), - Type::MutPtr(ty, _) => type_cfg_combine(reader, ty, cfg), - Type::WinrtArray(ty) => type_cfg_combine(reader, ty, cfg), - Type::WinrtArrayRef(ty) => type_cfg_combine(reader, ty, cfg), - ty => _ = cfg.core_types.insert(ty.clone()), - } -} diff --git a/crates/tools/riddle/src/rust/classes.rs b/crates/tools/riddle/src/rust/classes.rs deleted file mode 100644 index c5f7219e12..0000000000 --- a/crates/tools/riddle/src/rust/classes.rs +++ /dev/null @@ -1,213 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { - if writer.sys { - if writer.reader.type_def_has_default_interface(def) { - let name = to_ident(writer.reader.type_def_name(def)); - quote! { - pub type #name = *mut ::core::ffi::c_void; - } - } else { - quote! {} - } - } else { - gen_class(writer, def) - } -} - -fn gen_class(writer: &Writer, def: TypeDef) -> TokenStream { - if writer.reader.type_def_extends(def) == Some(TypeName::Attribute) { - return TokenStream::new(); - } - - let name = to_ident(writer.reader.type_def_name(def)); - let interfaces = type_interfaces(writer.reader, &Type::TypeDef(def, Vec::new())); - let mut methods = quote! {}; - let mut method_names = MethodNames::new(); - - let cfg = type_def_cfg(writer.reader, def, &[]); - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - - for interface in &interfaces { - if let Type::TypeDef(def, generics) = &interface.ty { - let mut virtual_names = MethodNames::new(); - - for method in writer.reader.type_def_methods(*def) { - methods.combine(&winrt_methods::writer( - writer, - *def, - generics, - interface.kind, - method, - &mut method_names, - &mut virtual_names, - )); - } - } - } - - let factories = interfaces.iter().filter_map(|interface| match interface.kind { - InterfaceKind::Static => { - if let Type::TypeDef(def, generics) = &interface.ty { - if writer.reader.type_def_methods(*def).next().is_some() { - let interface_type = writer.type_name(&interface.ty); - let features = writer.cfg_features(&type_def_cfg(writer.reader, *def, generics)); - - return Some(quote! { - #[doc(hidden)] - #features - pub fn #interface_type ::windows_core::Result>( - callback: F, - ) -> ::windows_core::Result { - static SHARED: ::windows_core::imp::FactoryCache<#name, #interface_type> = - ::windows_core::imp::FactoryCache::new(); - SHARED.call(callback) - } - }); - } - } - None - } - _ => None, - }); - - if writer.reader.type_def_has_default_interface(def) { - let new = if writer.reader.type_def_has_default_constructor(def) { - quote! { - pub fn new() -> ::windows_core::Result { - Self::IActivationFactory(|f| f.ActivateInstance::()) - } - fn IActivationFactory ::windows_core::Result>( - callback: F, - ) -> ::windows_core::Result { - static SHARED: ::windows_core::imp::FactoryCache<#name, ::windows_core::imp::IGenericFactory> = - ::windows_core::imp::FactoryCache::new(); - SHARED.call(callback) - } - } - } else { - quote! {} - }; - - let mut tokens = quote! { - #doc - #features - #[repr(transparent)] - pub struct #name(::windows_core::IUnknown); - #features - impl #name { - #new - #methods - #(#factories)* - } - }; - - tokens.combine(&writer.interface_core_traits( - def, - &[], - &name, - &TokenStream::new(), - &TokenStream::new(), - &features, - )); - tokens.combine(&writer.interface_winrt_trait( - def, - &[], - &name, - &TokenStream::new(), - &TokenStream::new(), - &features, - )); - tokens.combine(&writer.interface_trait( - def, - &[], - &name, - &TokenStream::new(), - &features, - true, - )); - tokens.combine(&writer.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); - tokens.combine(&writer.async_get( - def, - &[], - &name, - &TokenStream::new(), - &TokenStream::new(), - &features, - )); - tokens.combine(&iterators::writer( - writer, - def, - &[], - &name, - &TokenStream::new(), - &TokenStream::new(), - &cfg, - )); - tokens.combine(&gen_conversions(writer, def, &name, &interfaces, &cfg)); - tokens.combine(&writer.agile(def, &name, &TokenStream::new(), &features)); - tokens - } else { - let mut tokens = quote! { - #doc - #features - pub struct #name; - #features - impl #name { - #methods - #(#factories)* - } - }; - - tokens.combine(&writer.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); - tokens - } -} - -fn gen_conversions( - writer: &Writer, - def: TypeDef, - name: &TokenStream, - interfaces: &[Interface], - cfg: &Cfg, -) -> TokenStream { - let features = writer.cfg_features(cfg); - let mut tokens = quote! { - #features - ::windows_core::imp::interface_hierarchy!(#name, ::windows_core::IUnknown, ::windows_core::IInspectable); - }; - - for interface in interfaces { - if writer.reader.type_is_exclusive(&interface.ty) { - continue; - } - - if interface.kind != InterfaceKind::Default - && interface.kind != InterfaceKind::None - && interface.kind != InterfaceKind::Base - { - continue; - } - - let into = writer.type_name(&interface.ty); - let features = writer.cfg_features(&cfg.union(&type_cfg(writer.reader, &interface.ty))); - - tokens.combine("e! { - #features - impl ::windows_core::CanTryInto<#into> for #name {} - }); - } - - for def in writer.reader.type_def_bases(def) { - let into = writer.type_def_name(def, &[]); - let features = writer.cfg_features(&cfg.union(&type_def_cfg(writer.reader, def, &[]))); - - tokens.combine("e! { - #features - impl ::windows_core::CanTryInto<#into> for #name {} - }); - } - - tokens -} diff --git a/crates/tools/riddle/src/rust/com_methods.rs b/crates/tools/riddle/src/rust/com_methods.rs deleted file mode 100644 index af1c2a8f70..0000000000 --- a/crates/tools/riddle/src/rust/com_methods.rs +++ /dev/null @@ -1,244 +0,0 @@ -use super::*; - -pub fn writer( - writer: &Writer, - def: TypeDef, - kind: InterfaceKind, - method: MethodDef, - method_names: &mut MethodNames, - virtual_names: &mut MethodNames, - base_count: usize, -) -> TokenStream { - let signature = method_def_signature( - writer.reader, - writer.reader.type_def_namespace(def), - method, - &[], - ); - - let name = method_names.add(writer, method); - let vname = virtual_names.add(writer, method); - let generics = writer.constraint_generics(&signature.params); - let where_clause = writer.where_clause(&signature.params); - let mut cfg = signature_cfg(writer.reader, method); - cfg.add_feature(writer.reader.type_def_namespace(def)); - let doc = writer.cfg_method_doc(&cfg); - let features = writer.cfg_features(&cfg); - - if kind == InterfaceKind::None { - return quote! {}; - } - - let mut bases = quote! {}; - - for _ in 0..base_count { - bases.combine("e! { .base__ }); - } - - let kind = signature_kind(writer.reader, &signature); - match kind { - SignatureKind::Query(_) => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let generics = expand_generics(generics, quote!(T)); - let where_clause = - expand_where_clause(where_clause, quote!(T: ::windows_core::ComInterface)); - - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params) -> ::windows_core::Result #where_clause { - let mut result__ = ::std::ptr::null_mut(); - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args).from_abi(result__) - } - } - } - SignatureKind::QueryOptional(_) => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let generics = expand_generics(generics, quote!(T)); - let where_clause = - expand_where_clause(where_clause, quote!(T: ::windows_core::ComInterface)); - - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params result__: *mut ::core::option::Option) -> ::windows_core::Result<()> #where_clause { - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args).ok() - } - } - } - SignatureKind::ResultValue => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let return_type = signature.params[signature.params.len() - 1].ty.deref(); - let return_type = writer.type_name(&return_type); - - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params) -> ::windows_core::Result<#return_type> #where_clause { - let mut result__ = ::std::mem::zeroed(); - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args).from_abi(result__) - } - } - } - SignatureKind::ResultVoid => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params) -> ::windows_core::Result<()> #where_clause { - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args).ok() - } - } - } - SignatureKind::ReturnValue => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let return_type = signature.params[signature.params.len() - 1].ty.deref(); - let is_nullable = writer.reader.type_is_nullable(&return_type); - let return_type = writer.type_name(&return_type); - - if is_nullable { - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params) -> ::windows_core::Result<#return_type> #where_clause { - let mut result__ = ::std::mem::zeroed(); - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args); - ::windows_core::from_abi(result__) - } - } - } else { - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params) -> #return_type #where_clause { - let mut result__ = ::std::mem::zeroed(); - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args); - ::std::mem::transmute(result__) - } - } - } - } - SignatureKind::ReturnStruct => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let return_type = writer.type_name(&signature.return_type); - - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params) -> #return_type #where_clause { - let mut result__: #return_type = ::core::mem::zeroed(); - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), &mut result__, #args); - result__ - } - } - } - SignatureKind::PreserveSig => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let return_type = writer.return_sig(&signature); - - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params) #return_type #where_clause { - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args) - } - } - } - SignatureKind::ReturnVoid => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - - quote! { - #doc - #features - pub unsafe fn #name<#generics>(&self, #params) #where_clause { - (::windows_core::Interface::vtable(self)#bases.#vname)(::windows_core::Interface::as_raw(self), #args) - } - } - } - } -} - -pub fn gen_upcall(writer: &Writer, sig: &Signature, inner: TokenStream) -> TokenStream { - match signature_kind(writer.reader, sig) { - SignatureKind::ResultValue => { - let invoke_args = sig.params[..sig.params.len() - 1] - .iter() - .map(|param| gen_win32_invoke_arg(writer, param)); - - let result = writer.param_name(sig.params[sig.params.len() - 1].def); - - quote! { - match #inner(#(#invoke_args,)*) { - ::core::result::Result::Ok(ok__) => { - // use `core::ptr::write` since the result could be uninitialized - ::core::ptr::write(#result, ::core::mem::transmute(ok__)); - ::windows_core::HRESULT(0) - } - ::core::result::Result::Err(err) => err.into() - } - } - } - SignatureKind::Query(_) | SignatureKind::QueryOptional(_) | SignatureKind::ResultVoid => { - let invoke_args = sig - .params - .iter() - .map(|param| gen_win32_invoke_arg(writer, param)); - - quote! { - #inner(#(#invoke_args,)*).into() - } - } - SignatureKind::ReturnStruct => { - let invoke_args = sig - .params - .iter() - .map(|param| gen_win32_invoke_arg(writer, param)); - - quote! { - *result__ = #inner(#(#invoke_args,)*) - } - } - _ => { - let invoke_args = sig - .params - .iter() - .map(|param| gen_win32_invoke_arg(writer, param)); - - quote! { - #inner(#(#invoke_args,)*) - } - } - } -} - -fn gen_win32_invoke_arg(writer: &Writer, param: &SignatureParam) -> TokenStream { - let name = writer.param_name(param.def); - - if writer - .reader - .param_flags(param.def) - .contains(ParamAttributes::In) - && writer.reader.type_is_nullable(¶m.ty) - { - quote! { ::windows_core::from_raw_borrowed(&#name) } - } else if (!param.ty.is_pointer() && writer.reader.type_is_nullable(¶m.ty)) - || (writer - .reader - .param_flags(param.def) - .contains(ParamAttributes::In) - && !writer.reader.type_is_primitive(¶m.ty)) - { - quote! { ::core::mem::transmute(&#name) } - } else { - quote! { ::core::mem::transmute_copy(&#name) } - } -} diff --git a/crates/tools/riddle/src/rust/constants.rs b/crates/tools/riddle/src/rust/constants.rs deleted file mode 100644 index a2097fd339..0000000000 --- a/crates/tools/riddle/src/rust/constants.rs +++ /dev/null @@ -1,188 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, def: Field) -> TokenStream { - let name = to_ident(writer.reader.field_name(def)); - let ty = writer.reader.field_type(def, None).to_const_type(); - let cfg = field_cfg(writer.reader, def); - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - - if let Some(constant) = writer.reader.field_constant(def) { - let constant_type = writer.reader.constant_type(constant); - - if ty == constant_type { - if ty == Type::String { - let crate_name = writer.crate_name(); - if writer.reader.field_is_ansi(def) { - let value = writer.value(&writer.reader.constant_value(constant)); - quote! { - #doc - #features - pub const #name: #crate_name PCSTR = #crate_name s!(#value); - } - } else { - let value = writer.value(&writer.reader.constant_value(constant)); - quote! { - #doc - #features - pub const #name: #crate_name PCWSTR = #crate_name w!(#value); - } - } - } else { - let value = writer.typed_value(&writer.reader.constant_value(constant)); - quote! { - #doc - #features - pub const #name: #value; - } - } - } else { - let kind = writer.type_default_name(&ty); - let value = writer.value(&writer.reader.constant_value(constant)); - let underlying_type = writer.reader.type_underlying_type(&ty); - - let value = if underlying_type == constant_type { - value - } else if writer.std && underlying_type == Type::ISize { - quote! { ::core::ptr::invalid_mut(#value as _) } - } else { - quote! { #value as _ } - }; - - if !writer.sys && writer.reader.type_has_replacement(&ty) { - quote! { - #doc - #features - pub const #name: #kind = #kind(#value); - } - } else { - quote! { - #doc - #features - pub const #name: #kind = #value; - } - } - } - } else if let Some(guid) = writer.reader.field_guid(def) { - let value = writer.guid(&guid); - let guid = writer.type_name(&Type::GUID); - quote! { - #doc - pub const #name: #guid = #value; - } - } else if let Some(value) = initializer(writer, def) { - let kind = writer.type_default_name(&ty); - - quote! { - #doc - #features - pub const #name: #kind = #kind { #value }; - } - } else { - quote! {} - } -} - -fn initializer(writer: &Writer, def: Field) -> Option { - let Some(value) = constant(writer, def) else { - return None; - }; - - let mut input = value.as_str(); - - let Type::TypeDef(def, _) = writer.reader.field_type(def, None) else { - unimplemented!(); - }; - - let mut result = quote! {}; - - for field in writer.reader.type_def_fields(def) { - let (value, rest) = field_initializer(writer, field, input); - input = rest; - result.combine(&value); - } - - Some(result) -} - -fn field_initializer<'a>(writer: &Writer, field: Field, input: &'a str) -> (TokenStream, &'a str) { - let name = to_ident(writer.reader.field_name(field)); - - match writer.reader.field_type(field, None) { - Type::GUID => { - let (literals, rest) = read_literal_array(input, 11); - let value = writer.guid(&GUID::from_string_args(&literals)); - (quote! { #name: #value, }, rest) - } - Type::Win32Array(_, len) => { - let (literals, rest) = read_literal_array(input, len); - let literals = literals.iter().map(|literal| TokenStream::from(*literal)); - (quote! { #name: [#(#literals,)*], }, rest) - } - _ => { - let (literal, rest) = read_literal(input); - let literal: TokenStream = literal.into(); - (quote! { #name: #literal, }, rest) - } - } -} - -fn constant(writer: &Writer, def: Field) -> Option { - writer - .reader - .find_attribute(def, "ConstantAttribute") - .map(|attribute| { - let args = writer.reader.attribute_args(attribute); - match &args[0].1 { - Value::String(value) => value.clone(), - rest => unimplemented!("{rest:?}"), - } - }) -} - -fn read_literal(input: &str) -> (&str, &str) { - let mut start = None; - let mut end = 0; - - for (pos, c) in input.bytes().enumerate() { - if start.is_none() { - if c != b' ' && c != b',' { - start = Some(pos); - } - } else if c == b' ' || c == b',' || c == b'}' { - break; - } - end += 1; - } - - let Some(start) = start else { - unimplemented!(); - }; - - (&input[start..end], &input[end..]) -} - -fn read_token(input: &str, token: u8) -> &str { - for (pos, c) in input.bytes().enumerate() { - if c == token { - return &input[pos + 1..]; - } else if c != b' ' && c != b',' { - break; - } - } - - panic!("`{}` expected", token.escape_ascii()); -} - -fn read_literal_array(input: &str, len: usize) -> (Vec<&str>, &str) { - let mut input = read_token(input, b'{'); - let mut result = vec![]; - - for _ in 0..len { - let (literal, rest) = read_literal(input); - result.push(literal); - input = rest; - } - - (result, read_token(input, b'}')) -} diff --git a/crates/tools/riddle/src/rust/delegates.rs b/crates/tools/riddle/src/rust/delegates.rs deleted file mode 100644 index 2590b8444e..0000000000 --- a/crates/tools/riddle/src/rust/delegates.rs +++ /dev/null @@ -1,192 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { - if writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - gen_delegate(writer, def) - } else { - gen_callback(writer, def) - } -} - -fn gen_callback(writer: &Writer, def: TypeDef) -> TokenStream { - let name = to_ident(writer.reader.type_def_name(def)); - let method = type_def_invoke_method(writer.reader, def); - - let signature = method_def_signature( - writer.reader, - writer.reader.type_def_namespace(def), - method, - &[], - ); - - let return_type = writer.return_sig(&signature); - let cfg = type_def_cfg(writer.reader, def, &[]); - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - - let params = signature.params.iter().map(|p| { - let name = writer.param_name(p.def); - let tokens = writer.type_default_name(&p.ty); - quote! { #name: #tokens } - }); - - quote! { - #doc - #features - pub type #name = ::core::option::Option; - } -} - -fn gen_delegate(writer: &Writer, def: TypeDef) -> TokenStream { - if writer.sys { - let name = to_ident(writer.reader.type_def_name(def)); - quote! { - pub type #name = *mut ::core::ffi::c_void; - } - } else { - gen_win_delegate(writer, def) - } -} - -fn gen_win_delegate(writer: &Writer, def: TypeDef) -> TokenStream { - let name = to_ident(writer.reader.type_def_name(def)); - let vtbl = name.join("_Vtbl"); - let boxed = name.join("Box"); - - let generics = &type_def_generics(writer.reader, def); - let phantoms = writer.generic_phantoms(generics); - let named_phantoms = writer.generic_named_phantoms(generics); - let constraints = writer.generic_constraints(generics); - let generic_names = writer.generic_names(generics); - - let ident = writer.type_def_name(def, generics); - let method = type_def_invoke_method(writer.reader, def); - - let signature = method_def_signature( - writer.reader, - writer.reader.type_def_namespace(def), - method, - generics, - ); - - let fn_constraint = gen_fn_constraint(writer, def, &signature); - let cfg = type_def_cfg(writer.reader, def, generics); - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - - let vtbl_signature = writer.vtbl_signature(def, generics, &signature); - let invoke = winrt_methods::writer( - writer, - def, - generics, - InterfaceKind::Default, - method, - &mut MethodNames::new(), - &mut MethodNames::new(), - ); - let invoke_upcall = winrt_methods::gen_upcall(writer, &signature, quote! { ((*this).invoke) }); - - let mut tokens = quote! { - #doc - #features - #[repr(transparent)] - pub struct #ident(pub ::windows_core::IUnknown, #phantoms) where #constraints; - #features - impl<#constraints> #ident { - pub fn new<#fn_constraint>(invoke: F) -> Self { - let com = #boxed::<#generic_names F> { - vtable: &#boxed::<#generic_names F>::VTABLE, - count: ::windows_core::imp::RefCount::new(1), - invoke, - }; - unsafe { - ::core::mem::transmute(::std::boxed::Box::new(com)) - } - } - #invoke - } - #features - #[repr(C)] - struct #boxed<#generic_names #fn_constraint> where #constraints { - vtable: *const #vtbl<#generic_names>, - invoke: F, - count: ::windows_core::imp::RefCount, - } - #features - impl<#constraints #fn_constraint> #boxed<#generic_names F> { - const VTABLE: #vtbl<#generic_names> = #vtbl::<#generic_names>{ - base__: ::windows_core::IUnknown_Vtbl{QueryInterface: Self::QueryInterface, AddRef: Self::AddRef, Release: Self::Release}, - Invoke: Self::Invoke, - #(#named_phantoms)* - }; - unsafe extern "system" fn QueryInterface(this: *mut ::core::ffi::c_void, iid: &::windows_core::GUID, interface: *mut *const ::core::ffi::c_void) -> ::windows_core::HRESULT { - let this = this as *mut *mut ::core::ffi::c_void as *mut Self; - - *interface = if iid == &<#ident as ::windows_core::ComInterface>::IID || - iid == &<::windows_core::IUnknown as ::windows_core::ComInterface>::IID || - iid == &<::windows_core::imp::IAgileObject as ::windows_core::ComInterface>::IID { - &mut (*this).vtable as *mut _ as _ - } else { - ::core::ptr::null_mut() - }; - - // TODO: implement IMarshal - - if (*interface).is_null() { - ::windows_core::HRESULT(-2147467262) // E_NOINTERFACE - } else { - (*this).count.add_ref(); - ::windows_core::HRESULT(0) - } - } - unsafe extern "system" fn AddRef(this: *mut ::core::ffi::c_void) -> u32 { - let this = this as *mut *mut ::core::ffi::c_void as *mut Self; - (*this).count.add_ref() - } - unsafe extern "system" fn Release(this: *mut ::core::ffi::c_void) -> u32 { - let this = this as *mut *mut ::core::ffi::c_void as *mut Self; - let remaining = (*this).count.release(); - - if remaining == 0 { - let _ = ::std::boxed::Box::from_raw(this); - } - - remaining - } - unsafe extern "system" fn Invoke #vtbl_signature { - let this = this as *mut *mut ::core::ffi::c_void as *mut Self; - #invoke_upcall - } - } - }; - - tokens.combine(&writer.interface_core_traits( - def, - generics, - &ident, - &constraints, - &phantoms, - &features, - )); - tokens.combine(&writer.interface_trait(def, generics, &ident, &constraints, &features, true)); - tokens.combine(&writer.interface_winrt_trait( - def, - generics, - &ident, - &constraints, - &phantoms, - &features, - )); - tokens.combine(&writer.interface_vtbl(def, generics, &ident, &constraints, &features)); - tokens -} - -fn gen_fn_constraint(writer: &Writer, def: TypeDef, signature: &Signature) -> TokenStream { - let signature = writer.impl_signature(def, signature); - - quote! { F: FnMut #signature + ::core::marker::Send + 'static } -} diff --git a/crates/tools/riddle/src/rust/enums.rs b/crates/tools/riddle/src/rust/enums.rs deleted file mode 100644 index e0b987c7f1..0000000000 --- a/crates/tools/riddle/src/rust/enums.rs +++ /dev/null @@ -1,194 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { - let type_name = writer.reader.type_def_type_name(def); - let ident = to_ident(type_name.name); - let underlying_type = writer.reader.type_def_underlying_type(def); - let underlying_type = writer.type_name(&underlying_type); - - // TODO: unscoped enums should be removed from metadata - let is_scoped = writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - || writer.reader.has_attribute(def, "ScopedEnumAttribute"); - - let cfg = type_def_cfg(writer.reader, def, &[]); - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - - let fields: Vec<(TokenStream, TokenStream)> = writer - .reader - .type_def_fields(def) - .filter_map(|field| { - if writer - .reader - .field_flags(field) - .contains(FieldAttributes::Literal) - { - let field_name = to_ident(writer.reader.field_name(field)); - let constant = writer.reader.field_constant(field).unwrap(); - let value = writer.value(&writer.reader.constant_value(constant)); - - Some((field_name, value)) - } else { - None - } - }) - .collect(); - - let eq = if writer.sys { - quote! {} - } else { - quote! { - // Unfortunately, Rust requires these to be derived to allow constant patterns. - #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] - } - }; - - let mut tokens = if is_scoped || !writer.sys { - quote! { - #doc - #features - #[repr(transparent)] - #eq - pub struct #ident(pub #underlying_type); - } - } else { - quote! { - #doc - #features - pub type #ident = #underlying_type; - } - }; - - if is_scoped { - let fields = fields.iter().map(|(field_name, value)| { - quote! { - pub const #field_name: Self = Self(#value); - } - }); - - tokens.combine("e! { - #features - impl #ident { - #(#fields)* - } - }); - } - - if is_scoped || !writer.sys { - tokens.combine("e! { - #features - impl ::core::marker::Copy for #ident {} - #features - impl ::core::clone::Clone for #ident { - fn clone(&self) -> Self { - *self - } - } - }); - } - - if !writer.sys { - tokens.combine("e! { - #features - impl ::core::default::Default for #ident { - fn default() -> Self { - Self(0) - } - } - }); - } - - if !writer.sys { - let name = type_name.name; - tokens.combine("e! { - #features - impl ::windows_core::TypeKind for #ident { - type TypeKind = ::windows_core::CopyType; - } - #features - impl ::core::fmt::Debug for #ident { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple(#name).field(&self.0).finish() - } - } - }); - - // Win32 enums use the Flags attribute. WinRT enums don't have the Flags attribute but are paritioned merely based - // on whether they are signed. - // TODO: Win32 metadata should just follow WinRT's example here. - let type_def_is_flags = writer.reader.has_attribute(def, "FlagsAttribute") - || (writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - && writer.reader.type_def_underlying_type(def) == Type::U32); - - if type_def_is_flags { - tokens.combine("e! { - #features - impl #ident { - pub const fn contains(&self, other: Self) -> bool { - self.0 & other.0 == other.0 - } - } - #features - impl ::core::ops::BitOr for #ident { - type Output = Self; - - fn bitor(self, other: Self) -> Self { - Self(self.0 | other.0) - } - } - #features - impl ::core::ops::BitAnd for #ident { - type Output = Self; - - fn bitand(self, other: Self) -> Self { - Self(self.0 & other.0) - } - } - #features - impl ::core::ops::BitOrAssign for #ident { - fn bitor_assign(&mut self, other: Self) { - self.0.bitor_assign(other.0) - } - } - #features - impl ::core::ops::BitAndAssign for #ident { - fn bitand_assign(&mut self, other: Self) { - self.0.bitand_assign(other.0) - } - } - #features - impl ::core::ops::Not for #ident { - type Output = Self; - - fn not(self) -> Self { - Self(self.0.not()) - } - } - }); - } - - if writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - let signature = - Literal::byte_string(writer.reader.type_def_signature(def, &[]).as_bytes()); - - tokens.combine("e! { - #features - impl ::windows_core::RuntimeType for #ident { - const SIGNATURE: ::windows_core::imp::ConstBuffer = ::windows_core::imp::ConstBuffer::from_slice(#signature); - } - }); - } - } - - tokens -} diff --git a/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/Iterable.rs b/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/Iterable.rs deleted file mode 100644 index 6bed10d68f..0000000000 --- a/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/Iterable.rs +++ /dev/null @@ -1,96 +0,0 @@ -#[::windows_implement::implement(IIterable)] -struct StockIterable -where - T: ::windows_core::RuntimeType + 'static, - >::Default: ::std::clone::Clone, -{ - values: std::vec::Vec, -} - -impl IIterable_Impl for StockIterable -where - T: ::windows_core::RuntimeType, - >::Default: ::std::clone::Clone, -{ - fn First(&self) -> ::windows_core::Result> { - unsafe { - // TODO: ideally we can do an AddRef rather than a QI here (via cast)... - // and then we can get rid of the unsafe as well. - Ok(StockIterator { - owner: self.cast()?, - current: 0.into(), - } - .into()) - } - } -} - -#[::windows_implement::implement(IIterator)] -struct StockIterator -where - T: ::windows_core::RuntimeType + 'static, - >::Default: ::std::clone::Clone, -{ - owner: IIterable, - current: ::std::sync::atomic::AtomicUsize, -} - -impl IIterator_Impl for StockIterator -where - T: ::windows_core::RuntimeType, - >::Default: ::std::clone::Clone, -{ - fn Current(&self) -> ::windows_core::Result { - let owner: &StockIterable = unsafe { ::windows_core::AsImpl::as_impl(&self.owner) }; - let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); - - if owner.values.len() > current { - T::from_default(&owner.values[current]) - } else { - Err(::windows_core::Error::from(::windows_core::imp::E_BOUNDS)) - } - } - - fn HasCurrent(&self) -> ::windows_core::Result { - let owner: &StockIterable = unsafe { ::windows_core::AsImpl::as_impl(&self.owner) }; - let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); - - Ok(owner.values.len() > current) - } - - fn MoveNext(&self) -> ::windows_core::Result { - let owner: &StockIterable = unsafe { ::windows_core::AsImpl::as_impl(&self.owner) }; - let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); - - if current < owner.values.len() { - self.current - .fetch_add(1, ::std::sync::atomic::Ordering::Relaxed); - } - - Ok(owner.values.len() > current + 1) - } - - fn GetMany(&self, values: &mut [T::Default]) -> ::windows_core::Result { - let owner: &StockIterable = unsafe { ::windows_core::AsImpl::as_impl(&self.owner) }; - let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); - - let actual = std::cmp::min(owner.values.len() - current, values.len()); - let (values, _) = values.split_at_mut(actual); - values.clone_from_slice(&owner.values[current..current + actual]); - self.current - .fetch_add(actual, ::std::sync::atomic::Ordering::Relaxed); - Ok(actual as u32) - } -} - -impl ::core::convert::TryFrom<::std::vec::Vec> for IIterable -where - T: ::windows_core::RuntimeType, - >::Default: ::std::clone::Clone, -{ - type Error = ::windows_core::Error; - fn try_from(values: ::std::vec::Vec) -> ::windows_core::Result { - // TODO: should provide a fallible try_into or more explicit allocator - Ok(StockIterable { values }.into()) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/MapView.rs b/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/MapView.rs deleted file mode 100644 index 72b39f56ec..0000000000 --- a/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/MapView.rs +++ /dev/null @@ -1,174 +0,0 @@ -#[::windows_implement::implement(IMapView, IIterable>)] -struct StockMapView -where - K: ::windows_core::RuntimeType + 'static, - V: ::windows_core::RuntimeType + 'static, - >::Default: std::clone::Clone + std::cmp::Ord, - >::Default: std::clone::Clone, -{ - map: std::collections::BTreeMap, -} - -impl IIterable_Impl> for StockMapView -where - K: ::windows_core::RuntimeType, - V: ::windows_core::RuntimeType, - >::Default: std::clone::Clone + std::cmp::Ord, - >::Default: std::clone::Clone, -{ - fn First(&self) -> ::windows_core::Result>> { - unsafe { - // TODO: ideally we can do an AddRef rather than a QI here (via cast)... - // and then we can get rid of the unsafe as well. - Ok(StockMapViewIterator:: { - _owner: self.cast()?, - current: std::sync::RwLock::new(self.map.iter()), - } - .into()) - } - } -} - -impl IMapView_Impl for StockMapView -where - K: ::windows_core::RuntimeType, - V: ::windows_core::RuntimeType, - >::Default: std::clone::Clone + std::cmp::Ord, - >::Default: std::clone::Clone, -{ - fn Lookup(&self, key: &K::Default) -> ::windows_core::Result { - let value = self - .map - .get(key) - .ok_or_else(|| ::windows_core::Error::from(::windows_core::imp::E_BOUNDS))?; - V::from_default(value) - } - fn Size(&self) -> ::windows_core::Result { - Ok(self.map.len() as u32) - } - fn HasKey(&self, key: &K::Default) -> ::windows_core::Result { - Ok(self.map.contains_key(key)) - } - fn Split( - &self, - first: &mut std::option::Option>, - second: &mut std::option::Option>, - ) -> ::windows_core::Result<()> { - *first = None; - *second = None; - Ok(()) - } -} - -#[::windows_implement::implement(IIterator>)] -struct StockMapViewIterator<'a, K, V> -where - K: ::windows_core::RuntimeType + 'static, - V: ::windows_core::RuntimeType + 'static, - >::Default: std::clone::Clone + std::cmp::Ord, - >::Default: std::clone::Clone, -{ - _owner: IIterable>, - current: ::std::sync::RwLock>, -} - -impl<'a, K, V> IIterator_Impl> for StockMapViewIterator<'a, K, V> -where - K: ::windows_core::RuntimeType, - V: ::windows_core::RuntimeType, - >::Default: std::clone::Clone + std::cmp::Ord, - >::Default: std::clone::Clone, -{ - fn Current(&self) -> ::windows_core::Result> { - let mut current = self.current.read().unwrap().clone().peekable(); - - if let Some((key, value)) = current.peek() { - Ok(StockKeyValuePair { - key: (*key).clone(), - value: (*value).clone(), - } - .into()) - } else { - Err(::windows_core::Error::from(::windows_core::imp::E_BOUNDS)) - } - } - - fn HasCurrent(&self) -> ::windows_core::Result { - let mut current = self.current.read().unwrap().clone().peekable(); - - Ok(current.peek().is_some()) - } - - fn MoveNext(&self) -> ::windows_core::Result { - let mut current = self.current.write().unwrap(); - - current.next(); - Ok(current.clone().peekable().peek().is_some()) - } - - fn GetMany(&self, pairs: &mut [Option>]) -> ::windows_core::Result { - let mut current = self.current.write().unwrap(); - let mut actual = 0; - - for pair in pairs { - if let Some((key, value)) = current.next() { - *pair = Some( - StockKeyValuePair { - key: (*key).clone(), - value: (*value).clone(), - } - .into(), - ); - actual += 1; - } else { - break; - } - } - - Ok(actual) - } -} - -#[::windows_implement::implement(IKeyValuePair)] -struct StockKeyValuePair -where - K: ::windows_core::RuntimeType + 'static, - V: ::windows_core::RuntimeType + 'static, - >::Default: std::clone::Clone, - >::Default: std::clone::Clone, -{ - key: K::Default, - value: V::Default, -} - -impl IKeyValuePair_Impl for StockKeyValuePair -where - K: ::windows_core::RuntimeType, - V: ::windows_core::RuntimeType, - >::Default: std::clone::Clone, - >::Default: std::clone::Clone, -{ - fn Key(&self) -> ::windows_core::Result { - K::from_default(&self.key) - } - fn Value(&self) -> ::windows_core::Result { - V::from_default(&self.value) - } -} - -impl ::core::convert::TryFrom> - for IMapView -where - K: ::windows_core::RuntimeType, - V: ::windows_core::RuntimeType, - >::Default: std::clone::Clone + std::cmp::Ord, - >::Default: std::clone::Clone, -{ - type Error = ::windows_core::Error; - fn try_from( - map: std::collections::BTreeMap, - ) -> ::windows_core::Result { - // TODO: should provide a fallible try_into or more explicit allocator - Ok(StockMapView { map }.into()) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/VectorView.rs b/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/VectorView.rs deleted file mode 100644 index cc482b70fd..0000000000 --- a/crates/tools/riddle/src/rust/extensions/impl/Foundation/Collections/VectorView.rs +++ /dev/null @@ -1,132 +0,0 @@ -#[::windows_implement::implement(IVectorView, IIterable)] -struct StockVectorView -where - T: ::windows_core::RuntimeType + 'static, - >::Default: std::clone::Clone + std::cmp::PartialEq, -{ - values: std::vec::Vec, -} - -impl IIterable_Impl for StockVectorView -where - T: ::windows_core::RuntimeType, - >::Default: std::clone::Clone + std::cmp::PartialEq, -{ - fn First(&self) -> ::windows_core::Result> { - unsafe { - // TODO: ideally we can do an AddRef rather than a QI here (via cast)... - // and then we can get rid of the unsafe as well. - Ok(StockVectorViewIterator { - owner: self.cast()?, - current: 0.into(), - } - .into()) - } - } -} - -impl IVectorView_Impl for StockVectorView -where - T: ::windows_core::RuntimeType, - >::Default: std::clone::Clone + std::cmp::PartialEq, -{ - fn GetAt(&self, index: u32) -> ::windows_core::Result { - let item = self - .values - .get(index as usize) - .ok_or_else(|| ::windows_core::Error::from(::windows_core::imp::E_BOUNDS))?; - T::from_default(item) - } - fn Size(&self) -> ::windows_core::Result { - Ok(self.values.len() as u32) - } - fn IndexOf(&self, value: &T::Default, result: &mut u32) -> ::windows_core::Result { - match self.values.iter().position(|element| element == value) { - Some(index) => { - *result = index as u32; - Ok(true) - } - None => Ok(false), - } - } - fn GetMany(&self, current: u32, values: &mut [T::Default]) -> ::windows_core::Result { - let current = current as usize; - if current >= self.values.len() { - return Ok(0); - } - let actual = std::cmp::min(self.values.len() - current, values.len()); - let (values, _) = values.split_at_mut(actual); - values.clone_from_slice(&self.values[current..current + actual]); - Ok(actual as u32) - } -} - -#[::windows_implement::implement(IIterator)] -struct StockVectorViewIterator -where - T: ::windows_core::RuntimeType + 'static, - >::Default: std::clone::Clone + std::cmp::PartialEq, -{ - owner: IIterable, - current: ::std::sync::atomic::AtomicUsize, -} - -impl IIterator_Impl for StockVectorViewIterator -where - T: ::windows_core::RuntimeType, - >::Default: std::clone::Clone + std::cmp::PartialEq, -{ - fn Current(&self) -> ::windows_core::Result { - let owner: &StockVectorView = unsafe { ::windows_core::AsImpl::as_impl(&self.owner) }; - let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); - - if owner.values.len() > current { - T::from_default(&owner.values[current]) - } else { - Err(::windows_core::Error::from(::windows_core::imp::E_BOUNDS)) - } - } - - fn HasCurrent(&self) -> ::windows_core::Result { - let owner: &StockVectorView = unsafe { ::windows_core::AsImpl::as_impl(&self.owner) }; - let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); - - Ok(owner.values.len() > current) - } - - fn MoveNext(&self) -> ::windows_core::Result { - let owner: &StockVectorView = unsafe { ::windows_core::AsImpl::as_impl(&self.owner) }; - let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); - - if current < owner.values.len() { - self.current - .fetch_add(1, ::std::sync::atomic::Ordering::Relaxed); - } - - Ok(owner.values.len() > current + 1) - } - - fn GetMany(&self, values: &mut [T::Default]) -> ::windows_core::Result { - let owner: &StockVectorView = unsafe { ::windows_core::AsImpl::as_impl(&self.owner) }; - let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); - - let actual = std::cmp::min(owner.values.len() - current, values.len()); - let (values, _) = values.split_at_mut(actual); - values.clone_from_slice(&owner.values[current..current + actual]); - self.current - .fetch_add(actual, ::std::sync::atomic::Ordering::Relaxed); - Ok(actual as u32) - } -} - -impl ::core::convert::TryFrom<::std::vec::Vec> for IVectorView -where - T: ::windows_core::RuntimeType, - >::Default: std::clone::Clone + std::cmp::PartialEq, -{ - type Error = ::windows_core::Error; - fn try_from(values: ::std::vec::Vec) -> ::windows_core::Result { - // TODO: should provide a fallible try_into or more explicit allocator - Ok(StockVectorView { values }.into()) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod.rs b/crates/tools/riddle/src/rust/extensions/mod.rs deleted file mode 100644 index 9404dcb05b..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod.rs +++ /dev/null @@ -1,53 +0,0 @@ -use super::*; - -pub fn gen_mod(writer: &Writer, namespace: &str) -> TokenStream { - if namespace == "Windows.Win32.UI.WindowsAndMessaging" { - return include_str!("mod/Win32/UI/WindowsAndMessaging/WindowLong.rs").into(); - } - - if writer.sys { - return "".into(); - } - - match namespace { - "Windows.Foundation.Numerics" => concat!( - include_str!("mod/Foundation/Numerics/Matrix3x2.rs"), - include_str!("mod/Foundation/Numerics/Matrix4x4.rs"), - include_str!("mod/Foundation/Numerics/Vector2.rs"), - include_str!("mod/Foundation/Numerics/Vector3.rs"), - include_str!("mod/Foundation/Numerics/Vector4.rs"), - ), - "Windows.Foundation" => concat!(include_str!("mod/Foundation/TimeSpan.rs"),), - "Windows.Win32.Foundation" => concat!( - include_str!("mod/Win32/Foundation/BOOL.rs"), - include_str!("mod/Win32/Foundation/BOOLEAN.rs"), - include_str!("mod/Win32/Foundation/NTSTATUS.rs"), - include_str!("mod/Win32/Foundation/VARIANT_BOOL.rs"), - include_str!("mod/Win32/Foundation/WIN32_ERROR.rs"), - ), - "Windows.Win32.Networking.WinSock" => concat!( - include_str!("mod/Win32/Networking/WinSock/IN_ADDR.rs"), - include_str!("mod/Win32/Networking/WinSock/IN6_ADDR.rs"), - include_str!("mod/Win32/Networking/WinSock/SOCKADDR_IN.rs"), - include_str!("mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs"), - include_str!("mod/Win32/Networking/WinSock/SOCKADDR_INET.rs"), - ), - "Windows.Win32.UI.WindowsAndMessaging" => { - include_str!("mod/Win32/UI/WindowsAndMessaging/WindowLong.rs") - } - _ => "", - } - .into() -} - -pub fn gen_impl(namespace: &str) -> TokenStream { - match namespace { - "Windows.Foundation.Collections" => concat!( - include_str!("impl/Foundation/Collections/Iterable.rs"), - include_str!("impl/Foundation/Collections/MapView.rs"), - include_str!("impl/Foundation/Collections/VectorView.rs"), - ), - _ => "", - } - .into() -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Matrix3x2.rs b/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Matrix3x2.rs deleted file mode 100644 index 98be806365..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Matrix3x2.rs +++ /dev/null @@ -1,139 +0,0 @@ -impl Matrix3x2 { - pub const fn identity() -> Self { - Self { M11: 1.0, M12: 0.0, M21: 0.0, M22: 1.0, M31: 0.0, M32: 0.0 } - } - pub const fn translation(x: f32, y: f32) -> Self { - Self { M11: 1.0, M12: 0.0, M21: 0.0, M22: 1.0, M31: x, M32: y } - } - pub fn rotation(angle: f32, x: f32, y: f32) -> Self { - #[repr(C)] - pub struct D2D_POINT_2F { - pub x: f32, - pub y: f32, - } - ::windows_targets::link!("d2d1.dll" "system" fn D2D1MakeRotateMatrix(angle: f32, center: D2D_POINT_2F, matrix: *mut Matrix3x2) -> ()); - let mut matrix = Self::default(); - unsafe { - D2D1MakeRotateMatrix(angle, D2D_POINT_2F { x, y }, &mut matrix); - } - matrix - } - fn impl_add(&self, rhs: &Self) -> Self { - Self { - M11: self.M11 + rhs.M11, - M12: self.M12 + rhs.M12, - M21: self.M21 + rhs.M21, - M22: self.M22 + rhs.M22, - M31: self.M31 + rhs.M31, - M32: self.M32 + rhs.M32, - } - } - fn impl_sub(&self, rhs: &Self) -> Self { - Self { - M11: self.M11 - rhs.M11, - M12: self.M12 - rhs.M12, - M21: self.M21 - rhs.M21, - M22: self.M22 - rhs.M22, - M31: self.M31 - rhs.M31, - M32: self.M32 - rhs.M32, - } - } - fn impl_mul(&self, rhs: &Self) -> Self { - Self { - M11: self.M11 * rhs.M11 + self.M12 * rhs.M21, - M12: self.M11 * rhs.M12 + self.M12 * rhs.M22, - M21: self.M21 * rhs.M11 + self.M22 * rhs.M21, - M22: self.M21 * rhs.M12 + self.M22 * rhs.M22, - M31: self.M31 * rhs.M11 + self.M32 * rhs.M21 + rhs.M31, - M32: self.M31 * rhs.M12 + self.M32 * rhs.M22 + rhs.M32, - } - } - fn impl_mul_f32(&self, rhs: f32) -> Self { - Self { M11: self.M11 * rhs, M12: self.M12 * rhs, M21: self.M21 * rhs, M22: self.M22 * rhs, M31: self.M31 * rhs, M32: self.M32 * rhs } - } -} - -impl ::core::ops::Add for Matrix3x2 { - type Output = Matrix3x2; - fn add(self, rhs: Matrix3x2) -> Matrix3x2 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Matrix3x2> for Matrix3x2 { - type Output = Matrix3x2; - fn add(self, rhs: &Matrix3x2) -> Matrix3x2 { - self.impl_add(rhs) - } -} -impl ::core::ops::Add for &Matrix3x2 { - type Output = Matrix3x2; - fn add(self, rhs: Matrix3x2) -> Matrix3x2 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Matrix3x2> for &Matrix3x2 { - type Output = Matrix3x2; - fn add(self, rhs: &Matrix3x2) -> Matrix3x2 { - self.impl_add(rhs) - } -} -impl ::core::ops::Sub for Matrix3x2 { - type Output = Matrix3x2; - fn sub(self, rhs: Matrix3x2) -> Matrix3x2 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Matrix3x2> for Matrix3x2 { - type Output = Matrix3x2; - fn sub(self, rhs: &Matrix3x2) -> Matrix3x2 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Sub for &Matrix3x2 { - type Output = Matrix3x2; - fn sub(self, rhs: Matrix3x2) -> Matrix3x2 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Matrix3x2> for &Matrix3x2 { - type Output = Matrix3x2; - fn sub(self, rhs: &Matrix3x2) -> Matrix3x2 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Mul for Matrix3x2 { - type Output = Matrix3x2; - fn mul(self, rhs: Matrix3x2) -> Matrix3x2 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Matrix3x2> for Matrix3x2 { - type Output = Matrix3x2; - fn mul(self, rhs: &Matrix3x2) -> Matrix3x2 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for &Matrix3x2 { - type Output = Matrix3x2; - fn mul(self, rhs: Matrix3x2) -> Matrix3x2 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Matrix3x2> for &Matrix3x2 { - type Output = Matrix3x2; - fn mul(self, rhs: &Matrix3x2) -> Matrix3x2 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for Matrix3x2 { - type Output = Matrix3x2; - fn mul(self, rhs: f32) -> Matrix3x2 { - self.impl_mul_f32(rhs) - } -} -impl ::core::ops::Mul for &Matrix3x2 { - type Output = Matrix3x2; - fn mul(self, rhs: f32) -> Matrix3x2 { - self.impl_mul_f32(rhs) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Matrix4x4.rs b/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Matrix4x4.rs deleted file mode 100644 index fb5d60866f..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Matrix4x4.rs +++ /dev/null @@ -1,235 +0,0 @@ -impl Matrix4x4 { - pub const fn translation(x: f32, y: f32, z: f32) -> Self { - Self { - M11: 1.0, - M12: 0.0, - M13: 0.0, - M14: 0.0, - M21: 0.0, - M22: 1.0, - M23: 0.0, - M24: 0.0, - M31: 0.0, - M32: 0.0, - M33: 1.0, - M34: 0.0, - M41: x, - M42: y, - M43: z, - M44: 1.0, - } - } - pub fn rotation_y(degree: f32) -> Self { - ::windows_targets::link!("d2d1.dll" "system" fn D2D1SinCos(angle: f32, sin: *mut f32, cos: *mut f32) -> ()); - let angle = degree * (3.141592654 / 180.0); - let mut sin = 0.0; - let mut cos = 0.0; - unsafe { - D2D1SinCos(angle, &mut sin, &mut cos); - } - Self { - M11: cos, - M12: 0.0, - M13: -sin, - M14: 0.0, - M21: 0.0, - M22: 1.0, - M23: 0.0, - M24: 0.0, - M31: sin, - M32: 0.0, - M33: cos, - M34: 0.0, - M41: 0.0, - M42: 0.0, - M43: 0.0, - M44: 1.0, - } - } - pub fn perspective_projection(depth: f32) -> Self { - let projection = if depth > 0.0 { -1.0 / depth } else { 0.0 }; - Self { - M11: 1.0, - M12: 0.0, - M13: 0.0, - M14: 0.0, - M21: 0.0, - M22: 1.0, - M23: 0.0, - M24: 0.0, - M31: 0.0, - M32: 0.0, - M33: 1.0, - M34: projection, - M41: 0.0, - M42: 0.0, - M43: 0.0, - M44: 1.0, - } - } - fn impl_add(&self, rhs: &Self) -> Self { - Self { - M11: self.M11 + rhs.M11, - M12: self.M12 + rhs.M12, - M13: self.M13 + rhs.M13, - M14: self.M14 + rhs.M14, - M21: self.M21 + rhs.M21, - M22: self.M22 + rhs.M22, - M23: self.M23 + rhs.M23, - M24: self.M24 + rhs.M24, - M31: self.M31 + rhs.M31, - M32: self.M32 + rhs.M32, - M33: self.M33 + rhs.M33, - M34: self.M34 + rhs.M34, - M41: self.M41 + rhs.M41, - M42: self.M42 + rhs.M42, - M43: self.M43 + rhs.M43, - M44: self.M44 + rhs.M44, - } - } - fn impl_sub(&self, rhs: &Self) -> Self { - Self { - M11: self.M11 - rhs.M11, - M12: self.M12 - rhs.M12, - M13: self.M13 - rhs.M13, - M14: self.M14 - rhs.M14, - M21: self.M21 - rhs.M21, - M22: self.M22 - rhs.M22, - M23: self.M23 - rhs.M23, - M24: self.M24 - rhs.M24, - M31: self.M31 - rhs.M31, - M32: self.M32 - rhs.M32, - M33: self.M33 - rhs.M33, - M34: self.M34 - rhs.M34, - M41: self.M41 - rhs.M41, - M42: self.M42 - rhs.M42, - M43: self.M43 - rhs.M43, - M44: self.M44 - rhs.M44, - } - } - fn impl_mul(&self, rhs: &Self) -> Self { - Self { - M11: self.M11 * rhs.M11 + self.M12 * rhs.M21 + self.M13 * rhs.M31 + self.M14 * rhs.M41, - M12: self.M11 * rhs.M12 + self.M12 * rhs.M22 + self.M13 * rhs.M32 + self.M14 * rhs.M42, - M13: self.M11 * rhs.M13 + self.M12 * rhs.M23 + self.M13 * rhs.M33 + self.M14 * rhs.M43, - M14: self.M11 * rhs.M14 + self.M12 * rhs.M24 + self.M13 * rhs.M34 + self.M14 * rhs.M44, - M21: self.M21 * rhs.M11 + self.M22 * rhs.M21 + self.M23 * rhs.M31 + self.M24 * rhs.M41, - M22: self.M21 * rhs.M12 + self.M22 * rhs.M22 + self.M23 * rhs.M32 + self.M24 * rhs.M42, - M23: self.M21 * rhs.M13 + self.M22 * rhs.M23 + self.M23 * rhs.M33 + self.M24 * rhs.M43, - M24: self.M21 * rhs.M14 + self.M22 * rhs.M24 + self.M23 * rhs.M34 + self.M24 * rhs.M44, - M31: self.M31 * rhs.M11 + self.M32 * rhs.M21 + self.M33 * rhs.M31 + self.M34 * rhs.M41, - M32: self.M31 * rhs.M12 + self.M32 * rhs.M22 + self.M33 * rhs.M32 + self.M34 * rhs.M42, - M33: self.M31 * rhs.M13 + self.M32 * rhs.M23 + self.M33 * rhs.M33 + self.M34 * rhs.M43, - M34: self.M31 * rhs.M14 + self.M32 * rhs.M24 + self.M33 * rhs.M34 + self.M34 * rhs.M44, - M41: self.M41 * rhs.M11 + self.M42 * rhs.M21 + self.M43 * rhs.M31 + self.M44 * rhs.M41, - M42: self.M41 * rhs.M12 + self.M42 * rhs.M22 + self.M43 * rhs.M32 + self.M44 * rhs.M42, - M43: self.M41 * rhs.M13 + self.M42 * rhs.M23 + self.M43 * rhs.M33 + self.M44 * rhs.M43, - M44: self.M41 * rhs.M14 + self.M42 * rhs.M24 + self.M43 * rhs.M34 + self.M44 * rhs.M44, - } - } - fn impl_mul_f32(&self, rhs: f32) -> Self { - Self { - M11: self.M11 * rhs, - M12: self.M12 * rhs, - M13: self.M13 * rhs, - M14: self.M14 * rhs, - M21: self.M21 * rhs, - M22: self.M22 * rhs, - M23: self.M23 * rhs, - M24: self.M24 * rhs, - M31: self.M31 * rhs, - M32: self.M32 * rhs, - M33: self.M33 * rhs, - M34: self.M34 * rhs, - M41: self.M41 * rhs, - M42: self.M42 * rhs, - M43: self.M43 * rhs, - M44: self.M44 * rhs, - } - } -} - -impl ::core::ops::Add for Matrix4x4 { - type Output = Matrix4x4; - fn add(self, rhs: Matrix4x4) -> Matrix4x4 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Matrix4x4> for Matrix4x4 { - type Output = Matrix4x4; - fn add(self, rhs: &Matrix4x4) -> Matrix4x4 { - self.impl_add(rhs) - } -} -impl ::core::ops::Add for &Matrix4x4 { - type Output = Matrix4x4; - fn add(self, rhs: Matrix4x4) -> Matrix4x4 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Matrix4x4> for &Matrix4x4 { - type Output = Matrix4x4; - fn add(self, rhs: &Matrix4x4) -> Matrix4x4 { - self.impl_add(rhs) - } -} -impl ::core::ops::Sub for Matrix4x4 { - type Output = Matrix4x4; - fn sub(self, rhs: Matrix4x4) -> Matrix4x4 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Matrix4x4> for Matrix4x4 { - type Output = Matrix4x4; - fn sub(self, rhs: &Matrix4x4) -> Matrix4x4 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Sub for &Matrix4x4 { - type Output = Matrix4x4; - fn sub(self, rhs: Matrix4x4) -> Matrix4x4 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Matrix4x4> for &Matrix4x4 { - type Output = Matrix4x4; - fn sub(self, rhs: &Matrix4x4) -> Matrix4x4 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Mul for Matrix4x4 { - type Output = Matrix4x4; - fn mul(self, rhs: Matrix4x4) -> Matrix4x4 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Matrix4x4> for Matrix4x4 { - type Output = Matrix4x4; - fn mul(self, rhs: &Matrix4x4) -> Matrix4x4 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for &Matrix4x4 { - type Output = Matrix4x4; - fn mul(self, rhs: Matrix4x4) -> Matrix4x4 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Matrix4x4> for &Matrix4x4 { - type Output = Matrix4x4; - fn mul(self, rhs: &Matrix4x4) -> Matrix4x4 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for Matrix4x4 { - type Output = Matrix4x4; - fn mul(self, rhs: f32) -> Matrix4x4 { - self.impl_mul_f32(rhs) - } -} -impl ::core::ops::Mul for &Matrix4x4 { - type Output = Matrix4x4; - fn mul(self, rhs: f32) -> Matrix4x4 { - self.impl_mul_f32(rhs) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector2.rs b/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector2.rs deleted file mode 100644 index f37b4620be..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector2.rs +++ /dev/null @@ -1,175 +0,0 @@ -impl Vector2 { - pub fn new(X: f32, Y: f32) -> Self { - Self { X, Y } - } - pub fn zero() -> Self { - Self { X: 0f32, Y: 0f32 } - } - pub fn one() -> Self { - Self { X: 1f32, Y: 1f32 } - } - pub fn unit_x() -> Self { - Self { X: 1.0, Y: 0.0 } - } - pub fn unit_y() -> Self { - Self { X: 0.0, Y: 1.0 } - } - pub fn dot(&self, rhs: &Self) -> f32 { - self.X * rhs.X + self.Y * rhs.Y - } - pub fn length_squared(&self) -> f32 { - self.dot(self) - } - pub fn length(&self) -> f32 { - self.length_squared().sqrt() - } - pub fn distance(&self, value: &Self) -> f32 { - (self - value).length() - } - pub fn distance_squared(&self, value: &Self) -> f32 { - (self - value).length_squared() - } - pub fn normalize(&self) -> Self { - self / self.length() - } - - fn impl_add(&self, rhs: &Self) -> Self { - Self { X: self.X + rhs.X, Y: self.Y + rhs.Y } - } - fn impl_sub(&self, rhs: &Self) -> Self { - Self { X: self.X - rhs.X, Y: self.Y - rhs.Y } - } - fn impl_div(&self, rhs: &Self) -> Self { - Self { X: self.X / rhs.X, Y: self.Y / rhs.Y } - } - fn impl_div_f32(&self, rhs: f32) -> Self { - Self { X: self.X / rhs, Y: self.Y / rhs } - } - fn impl_mul(&self, rhs: &Self) -> Self { - Self { X: self.X * rhs.X, Y: self.Y * rhs.Y } - } - fn impl_mul_f32(&self, rhs: f32) -> Self { - Self { X: self.X * rhs, Y: self.Y * rhs } - } -} - -impl ::core::ops::Add for Vector2 { - type Output = Vector2; - fn add(self, rhs: Vector2) -> Vector2 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Vector2> for Vector2 { - type Output = Vector2; - fn add(self, rhs: &Vector2) -> Vector2 { - self.impl_add(rhs) - } -} -impl ::core::ops::Add for &Vector2 { - type Output = Vector2; - fn add(self, rhs: Vector2) -> Vector2 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Vector2> for &Vector2 { - type Output = Vector2; - fn add(self, rhs: &Vector2) -> Vector2 { - self.impl_add(rhs) - } -} -impl ::core::ops::Sub for Vector2 { - type Output = Vector2; - fn sub(self, rhs: Vector2) -> Vector2 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Vector2> for Vector2 { - type Output = Vector2; - fn sub(self, rhs: &Vector2) -> Vector2 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Sub for &Vector2 { - type Output = Vector2; - fn sub(self, rhs: Vector2) -> Vector2 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Vector2> for &Vector2 { - type Output = Vector2; - fn sub(self, rhs: &Vector2) -> Vector2 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Div for Vector2 { - type Output = Vector2; - fn div(self, rhs: Vector2) -> Vector2 { - self.impl_div(&rhs) - } -} -impl ::core::ops::Div<&Vector2> for Vector2 { - type Output = Vector2; - fn div(self, rhs: &Vector2) -> Vector2 { - self.impl_div(rhs) - } -} -impl ::core::ops::Div for &Vector2 { - type Output = Vector2; - fn div(self, rhs: Vector2) -> Vector2 { - self.impl_div(&rhs) - } -} -impl ::core::ops::Div<&Vector2> for &Vector2 { - type Output = Vector2; - fn div(self, rhs: &Vector2) -> Vector2 { - self.impl_div(rhs) - } -} -impl ::core::ops::Div for Vector2 { - type Output = Vector2; - fn div(self, rhs: f32) -> Vector2 { - self.impl_div_f32(rhs) - } -} -impl ::core::ops::Div for &Vector2 { - type Output = Vector2; - fn div(self, rhs: f32) -> Vector2 { - self.impl_div_f32(rhs) - } -} -impl ::core::ops::Mul for Vector2 { - type Output = Vector2; - fn mul(self, rhs: Vector2) -> Vector2 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Vector2> for Vector2 { - type Output = Vector2; - fn mul(self, rhs: &Vector2) -> Vector2 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for &Vector2 { - type Output = Vector2; - fn mul(self, rhs: Vector2) -> Vector2 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Vector2> for &Vector2 { - type Output = Vector2; - fn mul(self, rhs: &Vector2) -> Vector2 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for Vector2 { - type Output = Vector2; - fn mul(self, rhs: f32) -> Vector2 { - self.impl_mul_f32(rhs) - } -} -impl ::core::ops::Mul for &Vector2 { - type Output = Vector2; - fn mul(self, rhs: f32) -> Vector2 { - self.impl_mul_f32(rhs) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector3.rs b/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector3.rs deleted file mode 100644 index 58dcf96538..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector3.rs +++ /dev/null @@ -1,178 +0,0 @@ -impl Vector3 { - pub fn new(X: f32, Y: f32, Z: f32) -> Self { - Self { X, Y, Z } - } - pub fn zero() -> Self { - Self { X: 0f32, Y: 0f32, Z: 0f32 } - } - pub fn one() -> Self { - Self { X: 1f32, Y: 1f32, Z: 1f32 } - } - pub fn unit_x() -> Self { - Self { X: 1.0, Y: 0.0, Z: 0.0 } - } - pub fn unit_y() -> Self { - Self { X: 0.0, Y: 1.0, Z: 0.0 } - } - pub fn unit_z() -> Self { - Self { X: 0.0, Y: 0.0, Z: 1.0 } - } - pub fn dot(&self, rhs: &Self) -> f32 { - self.X * rhs.X + self.Y * rhs.Y + self.Z * rhs.Z - } - pub fn length_squared(&self) -> f32 { - self.dot(self) - } - pub fn length(&self) -> f32 { - self.length_squared().sqrt() - } - pub fn distance(&self, value: &Self) -> f32 { - (self - value).length() - } - pub fn distance_squared(&self, value: &Self) -> f32 { - (self - value).length_squared() - } - pub fn normalize(&self) -> Self { - self / self.length() - } - - fn impl_add(&self, rhs: &Self) -> Self { - Self { X: self.X + rhs.X, Y: self.Y + rhs.Y, Z: self.Z + rhs.Z } - } - fn impl_sub(&self, rhs: &Self) -> Self { - Self { X: self.X - rhs.X, Y: self.Y - rhs.Y, Z: self.Z - rhs.Z } - } - fn impl_div(&self, rhs: &Self) -> Self { - Self { X: self.X / rhs.X, Y: self.Y / rhs.Y, Z: self.Z / rhs.Z } - } - fn impl_div_f32(&self, rhs: f32) -> Self { - Self { X: self.X / rhs, Y: self.Y / rhs, Z: self.Z / rhs } - } - fn impl_mul(&self, rhs: &Self) -> Self { - Self { X: self.X * rhs.X, Y: self.Y * rhs.Y, Z: self.Z * rhs.Z } - } - fn impl_mul_f32(&self, rhs: f32) -> Self { - Self { X: self.X * rhs, Y: self.Y * rhs, Z: self.Z * rhs } - } -} - -impl ::core::ops::Add for Vector3 { - type Output = Vector3; - fn add(self, rhs: Vector3) -> Vector3 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Vector3> for Vector3 { - type Output = Vector3; - fn add(self, rhs: &Vector3) -> Vector3 { - self.impl_add(rhs) - } -} -impl ::core::ops::Add for &Vector3 { - type Output = Vector3; - fn add(self, rhs: Vector3) -> Vector3 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Vector3> for &Vector3 { - type Output = Vector3; - fn add(self, rhs: &Vector3) -> Vector3 { - self.impl_add(rhs) - } -} -impl ::core::ops::Sub for Vector3 { - type Output = Vector3; - fn sub(self, rhs: Vector3) -> Vector3 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Vector3> for Vector3 { - type Output = Vector3; - fn sub(self, rhs: &Vector3) -> Vector3 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Sub for &Vector3 { - type Output = Vector3; - fn sub(self, rhs: Vector3) -> Vector3 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Vector3> for &Vector3 { - type Output = Vector3; - fn sub(self, rhs: &Vector3) -> Vector3 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Div for Vector3 { - type Output = Vector3; - fn div(self, rhs: Vector3) -> Vector3 { - self.impl_div(&rhs) - } -} -impl ::core::ops::Div<&Vector3> for Vector3 { - type Output = Vector3; - fn div(self, rhs: &Vector3) -> Vector3 { - self.impl_div(rhs) - } -} -impl ::core::ops::Div for &Vector3 { - type Output = Vector3; - fn div(self, rhs: Vector3) -> Vector3 { - self.impl_div(&rhs) - } -} -impl ::core::ops::Div<&Vector3> for &Vector3 { - type Output = Vector3; - fn div(self, rhs: &Vector3) -> Vector3 { - self.impl_div(rhs) - } -} -impl ::core::ops::Div for Vector3 { - type Output = Vector3; - fn div(self, rhs: f32) -> Vector3 { - self.impl_div_f32(rhs) - } -} -impl ::core::ops::Div for &Vector3 { - type Output = Vector3; - fn div(self, rhs: f32) -> Vector3 { - self.impl_div_f32(rhs) - } -} -impl ::core::ops::Mul for Vector3 { - type Output = Vector3; - fn mul(self, rhs: Vector3) -> Vector3 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Vector3> for Vector3 { - type Output = Vector3; - fn mul(self, rhs: &Vector3) -> Vector3 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for &Vector3 { - type Output = Vector3; - fn mul(self, rhs: Vector3) -> Vector3 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Vector3> for &Vector3 { - type Output = Vector3; - fn mul(self, rhs: &Vector3) -> Vector3 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for Vector3 { - type Output = Vector3; - fn mul(self, rhs: f32) -> Vector3 { - self.impl_mul_f32(rhs) - } -} -impl ::core::ops::Mul for &Vector3 { - type Output = Vector3; - fn mul(self, rhs: f32) -> Vector3 { - self.impl_mul_f32(rhs) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector4.rs b/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector4.rs deleted file mode 100644 index 69609d906a..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Foundation/Numerics/Vector4.rs +++ /dev/null @@ -1,181 +0,0 @@ -impl Vector4 { - pub fn new(X: f32, Y: f32, Z: f32, W: f32) -> Self { - Self { X, Y, Z, W } - } - pub fn zero() -> Self { - Self { X: 0f32, Y: 0f32, Z: 0f32, W: 0f32 } - } - pub fn one() -> Self { - Self { X: 1f32, Y: 1f32, Z: 1f32, W: 1f32 } - } - pub fn unit_x() -> Self { - Self { X: 1.0, Y: 0.0, Z: 0.0, W: 0.0 } - } - pub fn unit_y() -> Self { - Self { X: 0.0, Y: 1.0, Z: 0.0, W: 0.0 } - } - pub fn unit_z() -> Self { - Self { X: 0.0, Y: 0.0, Z: 1.0, W: 0.0 } - } - pub fn unit_w() -> Self { - Self { X: 0.0, Y: 0.0, Z: 0.0, W: 1.0 } - } - pub fn dot(&self, rhs: &Self) -> f32 { - self.X * rhs.X + self.Y * rhs.Y + self.Z * rhs.Z + self.W * rhs.W - } - pub fn length_squared(&self) -> f32 { - self.dot(self) - } - pub fn length(&self) -> f32 { - self.length_squared().sqrt() - } - pub fn distance(&self, value: &Self) -> f32 { - (self - value).length() - } - pub fn distance_squared(&self, value: &Self) -> f32 { - (self - value).length_squared() - } - pub fn normalize(&self) -> Self { - self / self.length() - } - - fn impl_add(&self, rhs: &Self) -> Self { - Self { X: self.X + rhs.X, Y: self.Y + rhs.Y, Z: self.Z + rhs.Z, W: self.W + rhs.W } - } - fn impl_sub(&self, rhs: &Self) -> Self { - Self { X: self.X - rhs.X, Y: self.Y - rhs.Y, Z: self.Z - rhs.Z, W: self.W - rhs.W } - } - fn impl_div(&self, rhs: &Self) -> Self { - Self { X: self.X / rhs.X, Y: self.Y / rhs.Y, Z: self.Z / rhs.Z, W: self.W / rhs.W } - } - fn impl_div_f32(&self, rhs: f32) -> Self { - Self { X: self.X / rhs, Y: self.Y / rhs, Z: self.Z / rhs, W: self.W / rhs } - } - fn impl_mul(&self, rhs: &Self) -> Self { - Self { X: self.X * rhs.X, Y: self.Y * rhs.Y, Z: self.Z * rhs.Z, W: self.W * rhs.W } - } - fn impl_mul_f32(&self, rhs: f32) -> Self { - Self { X: self.X * rhs, Y: self.Y * rhs, Z: self.Z * rhs, W: self.W * rhs } - } -} - -impl ::core::ops::Add for Vector4 { - type Output = Vector4; - fn add(self, rhs: Vector4) -> Vector4 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Vector4> for Vector4 { - type Output = Vector4; - fn add(self, rhs: &Vector4) -> Vector4 { - self.impl_add(rhs) - } -} -impl ::core::ops::Add for &Vector4 { - type Output = Vector4; - fn add(self, rhs: Vector4) -> Vector4 { - self.impl_add(&rhs) - } -} -impl ::core::ops::Add<&Vector4> for &Vector4 { - type Output = Vector4; - fn add(self, rhs: &Vector4) -> Vector4 { - self.impl_add(rhs) - } -} -impl ::core::ops::Sub for Vector4 { - type Output = Vector4; - fn sub(self, rhs: Vector4) -> Vector4 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Vector4> for Vector4 { - type Output = Vector4; - fn sub(self, rhs: &Vector4) -> Vector4 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Sub for &Vector4 { - type Output = Vector4; - fn sub(self, rhs: Vector4) -> Vector4 { - self.impl_sub(&rhs) - } -} -impl ::core::ops::Sub<&Vector4> for &Vector4 { - type Output = Vector4; - fn sub(self, rhs: &Vector4) -> Vector4 { - self.impl_sub(rhs) - } -} -impl ::core::ops::Div for Vector4 { - type Output = Vector4; - fn div(self, rhs: Vector4) -> Vector4 { - self.impl_div(&rhs) - } -} -impl ::core::ops::Div<&Vector4> for Vector4 { - type Output = Vector4; - fn div(self, rhs: &Vector4) -> Vector4 { - self.impl_div(rhs) - } -} -impl ::core::ops::Div for &Vector4 { - type Output = Vector4; - fn div(self, rhs: Vector4) -> Vector4 { - self.impl_div(&rhs) - } -} -impl ::core::ops::Div<&Vector4> for &Vector4 { - type Output = Vector4; - fn div(self, rhs: &Vector4) -> Vector4 { - self.impl_div(rhs) - } -} -impl ::core::ops::Div for Vector4 { - type Output = Vector4; - fn div(self, rhs: f32) -> Vector4 { - self.impl_div_f32(rhs) - } -} -impl ::core::ops::Div for &Vector4 { - type Output = Vector4; - fn div(self, rhs: f32) -> Vector4 { - self.impl_div_f32(rhs) - } -} -impl ::core::ops::Mul for Vector4 { - type Output = Vector4; - fn mul(self, rhs: Vector4) -> Vector4 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Vector4> for Vector4 { - type Output = Vector4; - fn mul(self, rhs: &Vector4) -> Vector4 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for &Vector4 { - type Output = Vector4; - fn mul(self, rhs: Vector4) -> Vector4 { - self.impl_mul(&rhs) - } -} -impl ::core::ops::Mul<&Vector4> for &Vector4 { - type Output = Vector4; - fn mul(self, rhs: &Vector4) -> Vector4 { - self.impl_mul(rhs) - } -} -impl ::core::ops::Mul for Vector4 { - type Output = Vector4; - fn mul(self, rhs: f32) -> Vector4 { - self.impl_mul_f32(rhs) - } -} -impl ::core::ops::Mul for &Vector4 { - type Output = Vector4; - fn mul(self, rhs: f32) -> Vector4 { - self.impl_mul_f32(rhs) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Foundation/TimeSpan.rs b/crates/tools/riddle/src/rust/extensions/mod/Foundation/TimeSpan.rs deleted file mode 100644 index 814b3d45b7..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Foundation/TimeSpan.rs +++ /dev/null @@ -1,10 +0,0 @@ -impl ::core::convert::From<::core::time::Duration> for TimeSpan { - fn from(value: ::core::time::Duration) -> Self { - Self { Duration: (value.as_nanos() / 100) as i64 } - } -} -impl ::core::convert::From for ::core::time::Duration { - fn from(value: TimeSpan) -> Self { - ::core::time::Duration::from_nanos((value.Duration * 100) as u64) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/BOOL.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/BOOL.rs deleted file mode 100644 index 2499fa964d..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/BOOL.rs +++ /dev/null @@ -1,73 +0,0 @@ -impl BOOL { - #[inline] - pub fn as_bool(self) -> bool { - self.0 != 0 - } - #[inline] - pub fn ok(self) -> ::windows_core::Result<()> { - if self.as_bool() { - Ok(()) - } else { - Err(::windows_core::Error::from_win32()) - } - } - #[inline] - #[track_caller] - pub fn unwrap(self) { - self.ok().unwrap(); - } - #[inline] - #[track_caller] - pub fn expect(self, msg: &str) { - self.ok().expect(msg); - } -} -impl ::core::convert::From for bool { - fn from(value: BOOL) -> Self { - value.as_bool() - } -} -impl ::core::convert::From<&BOOL> for bool { - fn from(value: &BOOL) -> Self { - value.as_bool() - } -} -impl ::core::convert::From for BOOL { - fn from(value: bool) -> Self { - if value { - Self(1) - } else { - Self(0) - } - } -} -impl ::core::convert::From<&bool> for BOOL { - fn from(value: &bool) -> Self { - (*value).into() - } -} -impl ::core::cmp::PartialEq for BOOL { - fn eq(&self, other: &bool) -> bool { - self.as_bool() == *other - } -} -impl ::core::cmp::PartialEq for bool { - fn eq(&self, other: &BOOL) -> bool { - *self == other.as_bool() - } -} -impl ::core::ops::Not for BOOL { - type Output = Self; - fn not(self) -> Self::Output { - if self.as_bool() { - Self(0) - } else { - Self(1) - } - } -} -impl ::windows_core::IntoParam for bool { - fn into_param(self) -> ::windows_core::Param { - ::windows_core::Param::Owned(self.into()) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/BOOLEAN.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/BOOLEAN.rs deleted file mode 100644 index dd113d100d..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/BOOLEAN.rs +++ /dev/null @@ -1,68 +0,0 @@ -impl BOOLEAN { - #[inline] - pub fn as_bool(self) -> bool { - self.0 != 0 - } - #[inline] - pub fn ok(self) -> ::windows_core::Result<()> { - if self.as_bool() { - Ok(()) - } else { - Err(::windows_core::Error::from_win32()) - } - } - #[inline] - #[track_caller] - pub fn unwrap(self) { - self.ok().unwrap(); - } - #[inline] - #[track_caller] - pub fn expect(self, msg: &str) { - self.ok().expect(msg); - } -} -impl ::core::convert::From for bool { - fn from(value: BOOLEAN) -> Self { - value.as_bool() - } -} -impl ::core::convert::From<&BOOLEAN> for bool { - fn from(value: &BOOLEAN) -> Self { - value.as_bool() - } -} -impl ::core::convert::From for BOOLEAN { - fn from(value: bool) -> Self { - if value { - Self(1) - } else { - Self(0) - } - } -} -impl ::core::convert::From<&bool> for BOOLEAN { - fn from(value: &bool) -> Self { - (*value).into() - } -} -impl ::core::cmp::PartialEq for BOOLEAN { - fn eq(&self, other: &bool) -> bool { - self.as_bool() == *other - } -} -impl ::core::cmp::PartialEq for bool { - fn eq(&self, other: &BOOLEAN) -> bool { - *self == other.as_bool() - } -} -impl ::core::ops::Not for BOOLEAN { - type Output = Self; - fn not(self) -> Self::Output { - if self.as_bool() { - Self(0) - } else { - Self(1) - } - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/NTSTATUS.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/NTSTATUS.rs deleted file mode 100644 index 324b4e3d58..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/NTSTATUS.rs +++ /dev/null @@ -1,32 +0,0 @@ -impl NTSTATUS { - #[inline] - pub const fn is_ok(self) -> bool { - self.0 >= 0 - } - #[inline] - pub const fn is_err(self) -> bool { - !self.is_ok() - } - #[inline] - pub const fn to_hresult(self) -> ::windows_core::HRESULT { - ::windows_core::HRESULT(self.0 | 0x1000_0000) - } - #[inline] - pub fn ok(self) -> ::windows_core::Result<()> { - if self.is_ok() { - Ok(()) - } else { - Err(self.to_hresult().into()) - } - } -} -impl ::core::convert::From for ::windows_core::HRESULT { - fn from(value: NTSTATUS) -> Self { - value.to_hresult() - } -} -impl ::core::convert::From for ::windows_core::Error { - fn from(value: NTSTATUS) -> Self { - value.to_hresult().into() - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs deleted file mode 100644 index 7952f005e4..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs +++ /dev/null @@ -1,68 +0,0 @@ -impl VARIANT_BOOL { - #[inline] - pub fn as_bool(self) -> bool { - self.0 != 0 - } - #[inline] - pub fn ok(self) -> ::windows_core::Result<()> { - if self.as_bool() { - Ok(()) - } else { - Err(::windows_core::Error::from_win32()) - } - } - #[inline] - #[track_caller] - pub fn unwrap(self) { - self.ok().unwrap(); - } - #[inline] - #[track_caller] - pub fn expect(self, msg: &str) { - self.ok().expect(msg); - } -} -impl ::core::convert::From for bool { - fn from(value: VARIANT_BOOL) -> Self { - value.as_bool() - } -} -impl ::core::convert::From<&VARIANT_BOOL> for bool { - fn from(value: &VARIANT_BOOL) -> Self { - value.as_bool() - } -} -impl ::core::convert::From for VARIANT_BOOL { - fn from(value: bool) -> Self { - if value { - VARIANT_TRUE - } else { - VARIANT_FALSE - } - } -} -impl ::core::convert::From<&bool> for VARIANT_BOOL { - fn from(value: &bool) -> Self { - (*value).into() - } -} -impl ::core::cmp::PartialEq for VARIANT_BOOL { - fn eq(&self, other: &bool) -> bool { - self.as_bool() == *other - } -} -impl ::core::cmp::PartialEq for bool { - fn eq(&self, other: &VARIANT_BOOL) -> bool { - *self == other.as_bool() - } -} -impl ::core::ops::Not for VARIANT_BOOL { - type Output = Self; - fn not(self) -> Self::Output { - if self.as_bool() { - VARIANT_FALSE - } else { - VARIANT_TRUE - } - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/WIN32_ERROR.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/WIN32_ERROR.rs deleted file mode 100644 index 2c9441efb0..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Foundation/WIN32_ERROR.rs +++ /dev/null @@ -1,41 +0,0 @@ -impl WIN32_ERROR { - #[inline] - pub const fn is_ok(self) -> bool { - self.0 == 0 - } - #[inline] - pub const fn is_err(self) -> bool { - !self.is_ok() - } - #[inline] - pub const fn to_hresult(self) -> ::windows_core::HRESULT { - ::windows_core::HRESULT(if self.0 == 0 { self.0 } else { (self.0 & 0x0000_FFFF) | (7 << 16) | 0x8000_0000 } as i32) - } - #[inline] - pub fn from_error(error: &::windows_core::Error) -> ::core::option::Option { - let hresult = error.code().0 as u32; - if ((hresult >> 16) & 0x7FF) == 7 { - Some(Self(hresult & 0xFFFF)) - } else { - None - } - } - #[inline] - pub fn ok(self) -> ::windows_core::Result<()> { - if self.is_ok() { - Ok(()) - } else { - Err(self.to_hresult().into()) - } - } -} -impl ::core::convert::From for ::windows_core::HRESULT { - fn from(value: WIN32_ERROR) -> Self { - value.to_hresult() - } -} -impl ::core::convert::From for ::windows_core::Error { - fn from(value: WIN32_ERROR) -> Self { - value.to_hresult().into() - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs deleted file mode 100644 index f4290fba6a..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs +++ /dev/null @@ -1,11 +0,0 @@ -impl ::core::convert::From<::std::net::Ipv6Addr> for IN6_ADDR { - fn from(addr: ::std::net::Ipv6Addr) -> Self { - Self { u: IN6_ADDR_0 { Byte: addr.octets() } } - } -} -impl ::core::convert::From for ::std::net::Ipv6Addr { - fn from(in6_addr: IN6_ADDR) -> Self { - // SAFETY: this is safe because the union variants are just views of the same exact data - Self::from(unsafe { in6_addr.u.Byte }) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs deleted file mode 100644 index d12af968b2..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs +++ /dev/null @@ -1,15 +0,0 @@ -impl ::core::convert::From<::std::net::Ipv4Addr> for IN_ADDR { - fn from(addr: ::std::net::Ipv4Addr) -> Self { - // u32::from(addr) is in host byte order - // S_addr must be big-endian, network byte order - Self { S_un: IN_ADDR_0 { S_addr: u32::from(addr).to_be() } } - } -} -impl ::core::convert::From for ::std::net::Ipv4Addr { - fn from(in_addr: IN_ADDR) -> Self { - // SAFETY: this is safe because the union variants are just views of the same exact data - // in_addr.S_un.S_addr is big-endian, network byte order - // Ipv4Addr::new() expects the parameter in host byte order - Self::from(u32::from_be(unsafe { in_addr.S_un.S_addr })) - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs deleted file mode 100644 index 68bfdc76d0..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs +++ /dev/null @@ -1,7 +0,0 @@ -impl ::core::convert::From<::std::net::SocketAddrV4> for SOCKADDR_IN { - fn from(addr: ::std::net::SocketAddrV4) -> Self { - // addr.port() is in host byte order - // sin_port must be big-endian, network byte order - SOCKADDR_IN { sin_family: AF_INET, sin_port: addr.port().to_be(), sin_addr: (*addr.ip()).into(), ..Default::default() } - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs deleted file mode 100644 index 7b76f2f7d2..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs +++ /dev/null @@ -1,15 +0,0 @@ -impl ::core::convert::From<::std::net::SocketAddrV6> for SOCKADDR_IN6 { - fn from(addr: ::std::net::SocketAddrV6) -> Self { - // addr.port() and addr.flowinfo() are in host byte order - // sin6_port and sin6_flowinfo must be big-endian, network byte order - // sin6_scope_id is a bitfield without endianness - SOCKADDR_IN6 { - sin6_family: AF_INET6, - sin6_port: addr.port().to_be(), - sin6_flowinfo: addr.flowinfo().to_be(), - sin6_addr: (*addr.ip()).into(), - Anonymous: SOCKADDR_IN6_0 { sin6_scope_id: addr.scope_id() }, - ..Default::default() - } - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs deleted file mode 100644 index ccaf570c0a..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs +++ /dev/null @@ -1,19 +0,0 @@ - -impl ::core::convert::From<::std::net::SocketAddrV4> for SOCKADDR_INET { - fn from(addr: ::std::net::SocketAddrV4) -> Self { - SOCKADDR_INET { Ipv4: addr.into() } - } -} -impl ::core::convert::From<::std::net::SocketAddrV6> for SOCKADDR_INET { - fn from(addr: ::std::net::SocketAddrV6) -> Self { - SOCKADDR_INET { Ipv6: addr.into() } - } -} -impl ::core::convert::From<::std::net::SocketAddr> for SOCKADDR_INET { - fn from(addr: ::std::net::SocketAddr) -> Self { - match addr { - ::std::net::SocketAddr::V4(socket_addr_v4) => socket_addr_v4.into(), - ::std::net::SocketAddr::V6(socket_addr_v6) => socket_addr_v6.into(), - } - } -} diff --git a/crates/tools/riddle/src/rust/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs b/crates/tools/riddle/src/rust/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs deleted file mode 100644 index cf1cc08d90..0000000000 --- a/crates/tools/riddle/src/rust/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs +++ /dev/null @@ -1,12 +0,0 @@ -#[cfg(target_pointer_width = "32")] -#[cfg(feature = "Win32_Foundation")] -pub use GetWindowLongA as GetWindowLongPtrA; -#[cfg(target_pointer_width = "32")] -#[cfg(feature = "Win32_Foundation")] -pub use GetWindowLongW as GetWindowLongPtrW; -#[cfg(target_pointer_width = "32")] -#[cfg(feature = "Win32_Foundation")] -pub use SetWindowLongA as SetWindowLongPtrA; -#[cfg(target_pointer_width = "32")] -#[cfg(feature = "Win32_Foundation")] -pub use SetWindowLongW as SetWindowLongPtrW; diff --git a/crates/tools/riddle/src/rust/functions.rs b/crates/tools/riddle/src/rust/functions.rs deleted file mode 100644 index 6a68484985..0000000000 --- a/crates/tools/riddle/src/rust/functions.rs +++ /dev/null @@ -1,312 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, namespace: &str, def: MethodDef) -> TokenStream { - // TODO: remove inline functions from metadata - if writer.reader.method_def_module_name(def) == "forceinline" { - return quote! {}; - } - - // TODO: remove ordinal functions from metadata - if let Some(impl_map) = writer.reader.method_def_impl_map(def) { - if writer - .reader - .impl_map_import_name(impl_map) - .starts_with('#') - { - return quote! {}; - } - } - - if writer.sys { - gen_sys_function(writer, namespace, def) - } else { - gen_win_function(writer, namespace, def) - } -} - -fn gen_sys_function(writer: &Writer, namespace: &str, def: MethodDef) -> TokenStream { - let signature = method_def_signature(writer.reader, namespace, def, &[]); - let cfg = signature_cfg(writer.reader, def); - let mut tokens = writer.cfg_features(&cfg); - tokens.combine(&gen_link(writer, namespace, &signature, &cfg)); - tokens -} - -fn gen_win_function(writer: &Writer, namespace: &str, def: MethodDef) -> TokenStream { - let name = to_ident(writer.reader.method_def_name(def)); - let signature = method_def_signature(writer.reader, namespace, def, &[]); - let generics = writer.constraint_generics(&signature.params); - let where_clause = writer.where_clause(&signature.params); - let abi_return_type = writer.return_sig(&signature); - let cfg = signature_cfg(writer.reader, def); - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - let link = gen_link(writer, namespace, &signature, &cfg); - - let kind = signature_kind(writer.reader, &signature); - match kind { - SignatureKind::Query(_) => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let generics = expand_generics(generics, quote!(T)); - let where_clause = - expand_where_clause(where_clause, quote!(T: ::windows_core::ComInterface)); - - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params) -> ::windows_core::Result #where_clause { - #link - let mut result__ = ::std::ptr::null_mut(); - #name(#args).from_abi(result__) - } - } - } - SignatureKind::QueryOptional(_) => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let generics = expand_generics(generics, quote!(T)); - let where_clause = - expand_where_clause(where_clause, quote!(T: ::windows_core::ComInterface)); - - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params result__: *mut ::core::option::Option) -> ::windows_core::Result<()> #where_clause { - #link - #name(#args).ok() - } - } - } - SignatureKind::ResultValue => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let return_type = signature.params[signature.params.len() - 1].ty.deref(); - let return_type = writer.type_name(&return_type); - - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params) -> ::windows_core::Result<#return_type> #where_clause { - #link - let mut result__ = ::std::mem::zeroed(); - #name(#args).from_abi(result__) - } - } - } - SignatureKind::ResultVoid => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params) -> ::windows_core::Result<()> #where_clause { - #link - #name(#args).ok() - } - } - } - SignatureKind::ReturnValue => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let return_type = signature.params[signature.params.len() - 1].ty.deref(); - let is_nullable = writer.reader.type_is_nullable(&return_type); - let return_type = writer.type_name(&return_type); - - if is_nullable { - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params) -> ::windows_core::Result<#return_type> #where_clause { - #link - let mut result__ = ::std::mem::zeroed(); - #name(#args); - ::windows_core::from_abi(result__.assume_init()) - } - } - } else { - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params) -> #return_type #where_clause { - #link - let mut result__ = ::std::mem::zeroed(); - #name(#args); - ::std::mem::transmute(result__) - } - } - } - } - SignatureKind::ReturnStruct | SignatureKind::PreserveSig => { - if handle_last_error(writer, def, &signature) { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let return_type = writer.type_name(&signature.return_type); - - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params) -> ::windows_core::Result<#return_type> #where_clause { - #link - let result__ = #name(#args); - (!result__.is_invalid()).then(|| result__).ok_or_else(::windows_core::Error::from_win32) - } - } - } else { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params) #abi_return_type #where_clause { - #link - #name(#args) - } - } - } - } - SignatureKind::ReturnVoid => { - let args = writer.win32_args(&signature.params, kind); - let params = writer.win32_params(&signature.params, kind); - let does_not_return = does_not_return(writer, def); - - quote! { - #doc - #features - #[inline] - pub unsafe fn #name<#generics>(#params) #does_not_return #where_clause { - #link - #name(#args) - } - } - } - } -} - -fn gen_link(writer: &Writer, namespace: &str, signature: &Signature, cfg: &Cfg) -> TokenStream { - let name = writer.reader.method_def_name(signature.def); - let ident = to_ident(name); - let library = writer.reader.method_def_module_name(signature.def); - let abi = writer.reader.method_def_extern_abi(signature.def); - - let symbol = if let Some(impl_map) = writer.reader.method_def_impl_map(signature.def) { - writer.reader.impl_map_import_name(impl_map) - } else { - name - }; - - let link_name = if symbol != name { - quote! { #[link_name = #symbol] } - } else { - quote! {} - }; - - let params = signature.params.iter().map(|p| { - let name = writer.param_name(p.def); - let tokens = if p.kind == SignatureParamKind::ValueType { - writer.type_default_name(&p.ty) - } else { - writer.type_abi_name(&p.ty) - }; - quote! { #name: #tokens } - }); - - let return_type = writer.return_sig(signature); - - let vararg = if writer.sys && signature.call_flags.contains(MethodCallAttributes::VARARG) { - "...".into() - } else { - quote! {} - }; - - if writer.std || !namespace.starts_with("Windows.") { - let library = library.trim_end_matches(".dll"); - - quote! { - #[link(name = #library)] - extern #abi { - #link_name - pub fn #ident(#(#params,)* #vararg) #return_type; - } - } - } else if let Some(library) = writer.reader.method_def_static_lib(signature.def) { - quote! { - #[link(name = #library, kind = "static")] - extern #abi { - #link_name - pub fn #ident(#(#params,)* #vararg) #return_type; - } - } - } else { - let symbol = if symbol != name { - format!(" \"{symbol}\"") - } else { - String::new() - }; - - let doc = if writer.sys { - writer.cfg_doc(cfg).0 - } else { - String::new() - }; - - let mut tokens = String::new(); - for param in params { - tokens.push_str(&format!("{}, ", param.as_str())); - } - tokens.push_str(&vararg.0); - let tokens = tokens.trim_end_matches(", "); - format!( - r#"::windows_targets::link!("{library}" "{abi}"{symbol}{doc} fn {name}({tokens}){return_type});"# - ) - .into() - } -} - -fn does_not_return(writer: &Writer, def: MethodDef) -> TokenStream { - if writer.reader.has_attribute(def, "DoesNotReturnAttribute") { - quote! { -> ! } - } else { - quote! {} - } -} - -fn handle_last_error(writer: &Writer, def: MethodDef, signature: &Signature) -> bool { - if let Some(map) = writer.reader.method_def_impl_map(def) { - if writer - .reader - .impl_map_flags(map) - .contains(PInvokeAttributes::SupportsLastError) - { - if let Type::TypeDef(return_type, _) = &signature.return_type { - if writer.reader.type_def_is_handle(*return_type) { - if writer - .reader - .type_def_underlying_type(*return_type) - .is_pointer() - { - return true; - } - if !writer - .reader - .type_def_invalid_values(*return_type) - .is_empty() - { - return true; - } - } - } - } - } - false -} diff --git a/crates/tools/riddle/src/rust/handles.rs b/crates/tools/riddle/src/rust/handles.rs deleted file mode 100644 index 6968ac6067..0000000000 --- a/crates/tools/riddle/src/rust/handles.rs +++ /dev/null @@ -1,114 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { - if writer.sys { - gen_sys_handle(writer, def) - } else { - gen_win_handle(writer, def) - } -} - -pub fn gen_sys_handle(writer: &Writer, def: TypeDef) -> TokenStream { - let ident = to_ident(writer.reader.type_def_name(def)); - match writer.reader.type_def_underlying_type(def) { - Type::ISize if writer.std => quote! { - pub type #ident = *mut ::core::ffi::c_void; - }, - Type::USize if writer.std => quote! { - #[cfg(target_pointer_width = "32")] - pub type #ident = u32; - #[cfg(target_pointer_width = "64")] - pub type #ident = u64; - }, - underlying_type => { - let signature = writer.type_default_name(&underlying_type); - - quote! { - pub type #ident = #signature; - } - } - } -} - -pub fn gen_win_handle(writer: &Writer, def: TypeDef) -> TokenStream { - let name = writer.reader.type_def_name(def); - let ident = to_ident(name); - let underlying_type = writer.reader.type_def_underlying_type(def); - let signature = writer.type_default_name(&underlying_type); - let check = if underlying_type.is_pointer() { - quote! { - impl #ident { - pub fn is_invalid(&self) -> bool { - self.0.is_null() - } - } - } - } else { - let invalid = writer.reader.type_def_invalid_values(def); - - if !invalid.is_empty() { - let invalid = invalid.iter().map(|value| { - let literal = Literal::i64_unsuffixed(*value); - - if *value < 0 && underlying_type.is_unsigned() { - quote! { self.0 == #literal as _ } - } else { - quote! { self.0 == #literal } - } - }); - quote! { - impl #ident { - pub fn is_invalid(&self) -> bool { - #(#invalid)||* - } - } - } - } else { - quote! {} - } - }; - - let mut tokens = quote! { - #[repr(transparent)] - // Unfortunately, Rust requires these to be derived to allow constant patterns. - #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] - pub struct #ident(pub #signature); - #check - impl ::core::default::Default for #ident { - fn default() -> Self { - unsafe { ::core::mem::zeroed() } - } - } - impl ::core::clone::Clone for #ident { - fn clone(&self) -> Self { - *self - } - } - impl ::core::marker::Copy for #ident {} - impl ::core::fmt::Debug for #ident { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple(#name).field(&self.0).finish() - } - } - impl ::windows_core::TypeKind for #ident { - type TypeKind = ::windows_core::CopyType; - } - }; - - if let Some(dependency) = writer.reader.type_def_usable_for(def) { - let type_name = writer.reader.type_def_type_name(dependency); - let mut dependency = writer.namespace(type_name.namespace); - dependency.push_str(type_name.name); - - tokens.combine("e! { - impl ::windows_core::CanInto<#dependency> for #ident {} - impl ::core::convert::From<#ident> for #dependency { - fn from(value: #ident) -> Self { - Self(value.0) - } - } - }); - } - - tokens -} diff --git a/crates/tools/riddle/src/rust/implements.rs b/crates/tools/riddle/src/rust/implements.rs deleted file mode 100644 index bf500c1207..0000000000 --- a/crates/tools/riddle/src/rust/implements.rs +++ /dev/null @@ -1,196 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { - if writer.reader.type_def_kind(def) != TypeKind::Interface - || (!writer.implement && writer.reader.has_attribute(def, "ExclusiveToAttribute")) - { - return quote! {}; - } - - let generics = &type_def_generics(writer.reader, def); - let type_ident = to_ident(writer.reader.type_def_name(def)); - let impl_ident = type_ident.join("_Impl"); - let vtbl_ident = type_ident.join("_Vtbl"); - let implvtbl_ident = impl_ident.join("Vtbl"); - let constraints = writer.generic_constraints(generics); - let generic_names = writer.generic_names(generics); - let named_phantoms = writer.generic_named_phantoms(generics); - let cfg = type_def_cfg_impl(writer.reader, def, generics); - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - let mut requires = quote! {}; - let type_ident = quote! { #type_ident<#generic_names> }; - let vtables = writer.reader.type_def_vtables(def); - let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown)); - - fn gen_required_trait(writer: &Writer, def: TypeDef, generics: &[Type]) -> TokenStream { - let name = writer.type_def_name_imp(def, generics, "_Impl"); - quote! { - + #name - } - } - - let mut matches = quote! { iid == &<#type_ident as ::windows_core::ComInterface>::IID }; - - if let Some(Type::TypeDef(def, _)) = vtables.last() { - requires.combine(&gen_required_trait(writer, *def, &[])) - } - - for def in &vtables { - if let Type::TypeDef(def, generics) = def { - let name = writer.type_def_name(*def, generics); - - matches.combine("e! { - || iid == &<#name as ::windows_core::ComInterface>::IID - }) - } - } - - if writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - // TODO: this awkward wrapping of TypeDefs needs fixing - for interface in type_interfaces(writer.reader, &Type::TypeDef(def, generics.to_vec())) { - if let Type::TypeDef(def, generics) = interface.ty { - requires.combine(&gen_required_trait(writer, def, &generics)); - } - } - } - - let runtime_name = - writer.runtime_name_trait(def, generics, &type_ident, &constraints, &features); - - let mut method_names = MethodNames::new(); - method_names.add_vtable_types(writer, def); - - let method_traits = writer.reader.type_def_methods(def).map(|method| { - let name = method_names.add(writer, method); - - let signature = method_def_signature( - writer.reader, - writer.reader.type_def_namespace(def), - method, - generics, - ); - - let signature_tokens = writer.impl_signature(def, &signature); - quote! { fn #name #signature_tokens; } - }); - - let mut method_names = MethodNames::new(); - method_names.add_vtable_types(writer, def); - - let method_impls = writer.reader.type_def_methods(def).map(|method| { - let name = method_names.add(writer, method); - let signature = method_def_signature(writer.reader,writer.reader.type_def_namespace(def), method, generics); - let vtbl_signature = writer.vtbl_signature(def, generics, &signature); - - let invoke_upcall = if writer.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) { winrt_methods::gen_upcall(writer, &signature, quote! { this.#name }) } else { com_methods::gen_upcall(writer, &signature, quote! { this.#name }) }; - - if has_unknown_base { - quote! { - unsafe extern "system" fn #name<#constraints Identity: ::windows_core::IUnknownImpl, Impl: #impl_ident<#generic_names>, const OFFSET: isize> #vtbl_signature { - // offset the `this` pointer by `OFFSET` times the size of a pointer and cast it as an IUnknown implementation - let this = (this as *const *const ()).offset(OFFSET) as *const Identity; - let this = (*this).get_impl(); - #invoke_upcall - } - } - } else { - quote! { - unsafe extern "system" fn #name #vtbl_signature { - let this = (this as *mut *mut ::core::ffi::c_void) as *const ::windows_core::ScopedHeap; - let this = &*((*this).this as *const Impl); - #invoke_upcall - } - } - } - }); - - let mut methods = quote! {}; - - match vtables.last() { - Some(Type::IUnknown) => methods.combine("e! { base__: ::windows_core::IUnknown_Vtbl::new::(), }), - Some(Type::IInspectable) => methods.combine("e! { base__: ::windows_core::IInspectable_Vtbl::new::(), }), - Some(Type::TypeDef(def, generics)) => { - let name = writer.type_def_name_imp(*def, generics, "_Vtbl"); - if has_unknown_base { - methods.combine("e! { base__: #name::new::(), }); - } else { - methods.combine("e! { base__: #name::new::(), }); - } - } - _ => {} - } - - let mut method_names = MethodNames::new(); - method_names.add_vtable_types(writer, def); - - for method in writer.reader.type_def_methods(def) { - let name = method_names.add(writer, method); - if has_unknown_base { - methods.combine("e! { #name: #name::<#generic_names Identity, Impl, OFFSET>, }); - } else { - methods.combine("e! { #name: #name::, }); - } - } - - if has_unknown_base { - quote! { - #doc - #features - pub trait #impl_ident<#generic_names> : Sized #requires where #constraints { - #(#method_traits)* - } - #runtime_name - #features - impl<#constraints> #vtbl_ident<#generic_names> { - pub const fn new, Impl: #impl_ident<#generic_names>, const OFFSET: isize>() -> #vtbl_ident<#generic_names> { - #(#method_impls)* - Self{ - #methods - #(#named_phantoms)* - } - } - pub fn matches(iid: &::windows_core::GUID) -> bool { - #matches - } - } - } - } else { - quote! { - #doc - #features - pub trait #impl_ident : Sized #requires { - #(#method_traits)* - } - #features - impl #vtbl_ident { - pub const fn new() -> #vtbl_ident { - #(#method_impls)* - Self{ - #methods - #(#named_phantoms)* - } - } - } - #[doc(hidden)] - #features - struct #implvtbl_ident (::std::marker::PhantomData); - #features - impl #implvtbl_ident { - const VTABLE: #vtbl_ident = #vtbl_ident::new::(); - } - #features - impl #type_ident { - pub fn new<'a, T: #impl_ident>(this: &'a T) -> ::windows_core::ScopedInterface<'a, Self> { - let this = ::windows_core::ScopedHeap { vtable: &#implvtbl_ident::::VTABLE as *const _ as *const _, this: this as *const _ as *const _ }; - let this = ::std::mem::ManuallyDrop::new(::std::boxed::Box::new(this)); - unsafe { ::windows_core::ScopedInterface::new(::std::mem::transmute(&this.vtable)) } - } - } - } - } -} diff --git a/crates/tools/riddle/src/rust/interfaces.rs b/crates/tools/riddle/src/rust/interfaces.rs deleted file mode 100644 index 3bd36005ca..0000000000 --- a/crates/tools/riddle/src/rust/interfaces.rs +++ /dev/null @@ -1,230 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { - if writer.sys { - gen_sys_interface(writer, def) - } else { - gen_win_interface(writer, def) - } -} - -fn gen_sys_interface(writer: &Writer, def: TypeDef) -> TokenStream { - let name = writer.reader.type_def_name(def); - let ident = to_ident(name); - - if writer.reader.type_def_is_exclusive(def) { - quote! {} - } else { - quote! { - pub type #ident = *mut ::core::ffi::c_void; - } - } -} - -fn gen_win_interface(writer: &Writer, def: TypeDef) -> TokenStream { - let generics = &type_def_generics(writer.reader, def); - let ident = writer.type_def_name(def, generics); - let is_exclusive = writer.reader.type_def_is_exclusive(def); - let phantoms = writer.generic_phantoms(generics); - let constraints = writer.generic_constraints(generics); - let cfg = type_def_cfg(writer.reader, def, &[]); - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - let interfaces = type_interfaces(writer.reader, &Type::TypeDef(def, generics.to_vec())); - let vtables = writer.reader.type_def_vtables(def); - let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown)); - - let mut tokens = if is_exclusive { - quote! { #[doc(hidden)] } - } else { - quote! { #doc } - }; - - if has_unknown_base { - tokens.combine("e! { - #features - #[repr(transparent)] - pub struct #ident(::windows_core::IUnknown, #phantoms) where #constraints; - }); - } else { - tokens.combine("e! { - #features - #[repr(transparent)] - pub struct #ident(::std::ptr::NonNull<::std::ffi::c_void>); - }); - } - - if !is_exclusive { - let mut methods = quote! {}; - // We need to distinguish between public and virtual methods because some WinRT type hierarchies inherit colliding (overloaded) - // methods that must be distinguishable. - let method_names = &mut MethodNames::new(); - let virtual_names = &mut MethodNames::new(); - - if writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - for method in writer.reader.type_def_methods(def) { - methods.combine(&winrt_methods::writer( - writer, - def, - generics, - InterfaceKind::Default, - method, - method_names, - virtual_names, - )); - } - for interface in &interfaces { - if let Type::TypeDef(def, generics) = &interface.ty { - for method in writer.reader.type_def_methods(*def) { - methods.combine(&winrt_methods::writer( - writer, - *def, - generics, - InterfaceKind::None, - method, - method_names, - virtual_names, - )); - } - } - } - } else { - let mut bases = vtables.len(); - for ty in &vtables { - match ty { - Type::IUnknown | Type::IInspectable => {} - Type::TypeDef(def, _) => { - let kind = if writer.reader.type_def_type_name(*def) == TypeName::IDispatch - { - InterfaceKind::None - } else { - InterfaceKind::Default - }; - for method in writer.reader.type_def_methods(*def) { - methods.combine(&com_methods::writer( - writer, - *def, - kind, - method, - method_names, - virtual_names, - bases, - )); - } - } - rest => unimplemented!("{rest:?}"), - } - - bases -= 1; - } - for method in writer.reader.type_def_methods(def) { - methods.combine(&com_methods::writer( - writer, - def, - InterfaceKind::Default, - method, - method_names, - virtual_names, - 0, - )); - } - } - - tokens.combine("e! { - #features - impl<#constraints> #ident { - #methods - } - }); - - if !vtables.is_empty() && generics.is_empty() { - let mut hierarchy = format!("::windows_core::imp::interface_hierarchy!({ident}"); - let mut hierarchy_cfg = cfg.clone(); - - for ty in &vtables { - let into = writer.type_name(ty); - - write!(&mut hierarchy, ", {into}").unwrap(); - hierarchy_cfg = hierarchy_cfg.union(&type_cfg(writer.reader, ty)); - } - - hierarchy.push_str(");"); - tokens.combine(&writer.cfg_features(&hierarchy_cfg)); - tokens.push_str(&hierarchy); - } else { - for ty in &vtables { - let into = writer.type_name(ty); - let cfg = writer.cfg_features(&cfg.union(&type_cfg(writer.reader, ty))); - tokens.combine("e! { - #cfg - impl<#constraints> ::windows_core::CanInto<#into> for #ident {} - }); - } - } - - if writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - for interface in &interfaces { - let into = writer.type_name(&interface.ty); - let cfg = writer.cfg_features(&cfg.union(&type_cfg(writer.reader, &interface.ty))); - tokens.combine("e! { - #cfg - impl<#constraints> ::windows_core::CanTryInto<#into> for #ident {} - }); - } - } - - tokens.combine(&writer.interface_core_traits( - def, - generics, - &ident, - &constraints, - &phantoms, - &features, - )); - tokens.combine(&writer.interface_winrt_trait( - def, - generics, - &ident, - &constraints, - &phantoms, - &features, - )); - tokens.combine(&writer.async_get( - def, - generics, - &ident, - &constraints, - &phantoms, - &features, - )); - tokens.combine(&iterators::writer( - writer, - def, - generics, - &ident, - &constraints, - &phantoms, - &cfg, - )); - tokens.combine(&writer.agile(def, &ident, &constraints, &features)); - } - - tokens.combine(&writer.interface_trait( - def, - generics, - &ident, - &constraints, - &features, - has_unknown_base, - )); - tokens.combine(&writer.interface_vtbl(def, generics, &ident, &constraints, &features)); - tokens -} diff --git a/crates/tools/riddle/src/rust/iterators.rs b/crates/tools/riddle/src/rust/iterators.rs deleted file mode 100644 index a2839da73c..0000000000 --- a/crates/tools/riddle/src/rust/iterators.rs +++ /dev/null @@ -1,254 +0,0 @@ -use super::*; - -pub fn writer( - writer: &Writer, - def: TypeDef, - generics: &[Type], - ident: &TokenStream, - constraints: &TokenStream, - _phantoms: &TokenStream, - cfg: &Cfg, -) -> TokenStream { - match writer.reader.type_def_type_name(def) { - // If the type is IIterator then simply implement the Iterator trait over top. - TypeName::IIterator => { - return quote! { - impl ::core::iter::Iterator for IIterator { - type Item = T; - - fn next(&mut self) -> ::core::option::Option { - let result = self.Current().ok(); - - if result.is_some() { - self.MoveNext().ok()?; - } - - result - } - } - }; - } - // If the type is IIterable then implement the IntoIterator trait and rely on the resulting - // IIterator returned by first() to implement the Iterator trait. - TypeName::IIterable => { - return quote! { - impl ::core::iter::IntoIterator for IIterable { - type Item = T; - type IntoIter = IIterator; - - fn into_iter(self) -> Self::IntoIter { - ::core::iter::IntoIterator::into_iter(&self) - } - } - impl ::core::iter::IntoIterator for &IIterable { - type Item = T; - type IntoIter = IIterator; - - fn into_iter(self) -> Self::IntoIter { - // TODO: not sure how to avoid this unwrap, although it should always succeed in practice. - self.First().unwrap() - } - } - }; - } - // If the type is IVectorView then provide the VectorViewIterator fast iterator. - TypeName::IVectorView => { - return quote! { - pub struct VectorViewIterator { - vector: ::core::option::Option>, - current: u32, - } - - impl VectorViewIterator { - pub fn new(vector: ::core::option::Option>) -> Self { - Self { vector, current: 0 } - } - } - - impl ::core::iter::Iterator for VectorViewIterator { - type Item = T; - - fn next(&mut self) -> ::core::option::Option { - self.vector.as_ref() - .and_then(|vector| { - vector.GetAt(self.current).ok() - }) - .and_then(|result| { - self.current += 1; - Some(result) - }) - } - } - - impl ::core::iter::IntoIterator for IVectorView { - type Item = T; - type IntoIter = VectorViewIterator; - - fn into_iter(self) -> Self::IntoIter { - ::core::iter::IntoIterator::into_iter(&self) - } - } - impl ::core::iter::IntoIterator for &IVectorView { - type Item = T; - type IntoIter = VectorViewIterator; - - fn into_iter(self) -> Self::IntoIter { - // TODO: shouldn't need to clone - VectorViewIterator should hold a reference - VectorViewIterator::new(::core::option::Option::Some(::core::clone::Clone::clone(self))) - } - } - }; - } - TypeName::IVector => { - return quote! { - pub struct VectorIterator { - vector: ::core::option::Option>, - current: u32, - } - - impl VectorIterator { - pub fn new(vector: ::core::option::Option>) -> Self { - Self { vector, current: 0 } - } - } - - impl ::core::iter::Iterator for VectorIterator { - type Item = T; - - fn next(&mut self) -> ::core::option::Option { - self.vector.as_ref() - .and_then(|vector| { - vector.GetAt(self.current).ok() - }) - .and_then(|result| { - self.current += 1; - Some(result) - }) - } - } - - impl ::core::iter::IntoIterator for IVector { - type Item = T; - type IntoIter = VectorIterator; - - fn into_iter(self) -> Self::IntoIter { - ::core::iter::IntoIterator::into_iter(&self) - } - } - impl ::core::iter::IntoIterator for &IVector { - type Item = T; - type IntoIter = VectorIterator; - - fn into_iter(self) -> Self::IntoIter { - // TODO: shouldn't need to clone - VectorIterator should hold a reference - VectorIterator::new(::core::option::Option::Some(::core::clone::Clone::clone(self))) - } - } - }; - } - _ => {} - } - - let wfc = writer.namespace("Windows.Foundation.Collections"); - let mut iterable = None; - let interfaces = type_interfaces(writer.reader, &Type::TypeDef(def, generics.to_vec())); - - // If the class or interface is not one of the well-known collection interfaces, we then see whether it - // implements any one of them. Here is where we favor IVectorView/IVector over IIterable. - for interface in interfaces { - if let Type::TypeDef(interface, interface_generics) = &interface.ty { - match writer.reader.type_def_type_name(*interface) { - TypeName::IVectorView => { - let item = writer.type_name(&interface_generics[0]); - let mut cfg = cfg.clone(); - type_def_cfg_combine(writer.reader, *interface, interface_generics, &mut cfg); - let features = writer.cfg_features(&cfg); - - return quote! { - #features - impl<#constraints> ::core::iter::IntoIterator for #ident { - type Item = #item; - type IntoIter = #wfc VectorViewIterator; - - fn into_iter(self) -> Self::IntoIter { - ::core::iter::IntoIterator::into_iter(&self) - } - } - #features - impl<#constraints> ::core::iter::IntoIterator for &#ident { - type Item = #item; - type IntoIter = #wfc VectorViewIterator; - - fn into_iter(self) -> Self::IntoIter { - #wfc VectorViewIterator::new(::windows_core::ComInterface::cast(self).ok()) - } - } - }; - } - TypeName::IVector => { - let item = writer.type_name(&interface_generics[0]); - let mut cfg = cfg.clone(); - type_def_cfg_combine(writer.reader, *interface, interface_generics, &mut cfg); - let features = writer.cfg_features(&cfg); - - return quote! { - #features - impl<#constraints> ::core::iter::IntoIterator for #ident { - type Item = #item; - type IntoIter = #wfc VectorIterator; - - fn into_iter(self) -> Self::IntoIter { - ::core::iter::IntoIterator::into_iter(&self) - } - } - #features - impl<#constraints> ::core::iter::IntoIterator for &#ident { - type Item = #item; - type IntoIter = #wfc VectorIterator; - - fn into_iter(self) -> Self::IntoIter { - #wfc VectorIterator::new(::windows_core::ComInterface::cast(self).ok()) - } - } - }; - } - TypeName::IIterable => { - iterable = Some((*interface, interface_generics.to_vec())); - } - _ => {} - } - } - } - - match iterable { - None => TokenStream::new(), - Some((interface, interface_generics)) => { - let item = writer.type_name(&interface_generics[0]); - let mut cfg = cfg.clone(); - type_def_cfg_combine(writer.reader, interface, &interface_generics, &mut cfg); - let features = writer.cfg_features(&cfg); - - quote! { - #features - impl<#constraints> ::core::iter::IntoIterator for #ident { - type Item = #item; - type IntoIter = #wfc IIterator; - - fn into_iter(self) -> Self::IntoIter { - ::core::iter::IntoIterator::into_iter(&self) - } - } - #features - impl<#constraints> ::core::iter::IntoIterator for &#ident { - type Item = #item; - type IntoIter = #wfc IIterator; - - fn into_iter(self) -> Self::IntoIter { - // TODO: not sure how to avoid this unwrap, although it should always succeed in practice. - self.First().unwrap() - } - } - } - } - } -} diff --git a/crates/tools/riddle/src/rust/method_names.rs b/crates/tools/riddle/src/rust/method_names.rs deleted file mode 100644 index 1b2d595e10..0000000000 --- a/crates/tools/riddle/src/rust/method_names.rs +++ /dev/null @@ -1,30 +0,0 @@ -use super::*; - -pub struct MethodNames(BTreeMap); - -impl MethodNames { - pub fn new() -> Self { - Self(BTreeMap::new()) - } - - pub fn add(&mut self, writer: &Writer, method: MethodDef) -> TokenStream { - let name = writer.reader.method_def_special_name(method); - let overload = self.0.entry(name.to_string()).or_insert(0); - *overload += 1; - if *overload > 1 { - format!("{name}{overload}").into() - } else { - to_ident(&name) - } - } - - pub fn add_vtable_types(&mut self, writer: &Writer, def: TypeDef) { - for def in writer.reader.type_def_vtables(def) { - if let Type::TypeDef(def, _) = def { - for method in writer.reader.type_def_methods(def) { - self.add(writer, method); - } - } - } - } -} diff --git a/crates/tools/riddle/src/rust/mod.rs b/crates/tools/riddle/src/rust/mod.rs deleted file mode 100644 index 6e618b9c7f..0000000000 --- a/crates/tools/riddle/src/rust/mod.rs +++ /dev/null @@ -1,340 +0,0 @@ -mod cfg; -mod classes; -mod com_methods; -mod constants; -mod delegates; -mod enums; -mod extensions; -mod functions; -mod handles; -mod implements; -mod interfaces; -mod iterators; -mod method_names; -mod standalone; -mod structs; -mod try_format; -mod winrt_methods; -mod writer; -use super::*; -use crate::{Error, Result, Tree}; -use cfg::*; -use rayon::prelude::*; - -pub fn from_reader( - reader: &metadata::Reader, - filter: &metadata::Filter, - mut config: std::collections::BTreeMap<&str, &str>, - output: &str, -) -> Result<()> { - let mut writer = Writer::new(reader, filter, output); - writer.package = config.remove("PACKAGE").is_some(); - writer.flatten = config.remove("FLATTEN").is_some(); - writer.std = config.remove("STD").is_some(); - writer.sys = writer.std || config.remove("SYS").is_some(); - writer.implement = config.remove("IMPLEMENT").is_some(); - writer.minimal = config.remove("MINIMAL").is_some(); - - if writer.package && writer.flatten { - return Err(Error::new( - "cannot combine `PACKAGE` and `FLATTEN` configuration values", - )); - } - - if writer.implement && writer.sys { - return Err(Error::new( - "cannot combine `IMPLEMENT` and `SYS` configuration values", - )); - } - - if let Some((key, _)) = config.first_key_value() { - return Err(Error::new(&format!("invalid configuration value `{key}`"))); - } - - if writer.package { - gen_package(&writer) - } else { - gen_file(&writer) - } -} - -fn gen_file(writer: &Writer) -> Result<()> { - // TODO: harmonize this output code so we don't need these two wildly differnt code paths - // there should be a simple way to generate the with or without namespaces. - - if writer.flatten { - let tokens = standalone::standalone_imp(writer); - crate::write_to_file(writer.output, try_format(writer, &tokens)) - } else { - let mut tokens = String::new(); - let root = Tree::new(writer.reader, writer.filter); - - for tree in root.nested.values() { - tokens.push_str(&namespace(writer, tree)); - } - - crate::write_to_file(writer.output, try_format(writer, &tokens)) - } -} - -fn gen_package(writer: &Writer) -> Result<()> { - let directory = crate::directory(writer.output); - let root = Tree::new(writer.reader, writer.filter); - let mut root_len = 0; - - for tree in root.nested.values() { - root_len = tree.namespace.len(); - _ = std::fs::remove_dir_all(format!("{directory}/{}", tree.namespace)); - } - - let trees = root.flatten(); - - trees.par_iter().try_for_each(|tree| { - let directory = format!("{directory}/{}", tree.namespace.replace('.', "/")); - let mut tokens = namespace(writer, tree); - - let tokens_impl = if !writer.sys { - namespace_impl(writer, tree) - } else { - String::new() - }; - - if !writer.sys && !tokens_impl.is_empty() { - tokens.push_str("#[cfg(feature = \"implement\")]\n::core::include!(\"impl.rs\");\n"); - } - - let output = format!("{directory}/mod.rs"); - crate::write_to_file(&output, try_format(writer, &tokens))?; - - if !writer.sys && !tokens_impl.is_empty() { - let output = format!("{directory}/impl.rs"); - crate::write_to_file(&output, try_format(writer, &tokens_impl))?; - } - - Ok::<(), Error>(()) - })?; - - let cargo_toml = format!("{}/Cargo.toml", crate::directory(directory)); - let mut toml = String::new(); - - for line in crate::read_file_lines(&cargo_toml)? { - toml.push_str(&line); - toml.push('\n'); - - if line == "# generated features" { - break; - } - } - - for tree in trees.iter().skip(1) { - let feature = tree.namespace[root_len + 1..].replace('.', "_"); - - if let Some(pos) = feature.rfind('_') { - let dependency = &feature[..pos]; - - toml.push_str(&format!("{feature} = [\"{dependency}\"]\n")); - } else { - toml.push_str(&format!("{feature} = []\n")); - } - } - - crate::write_to_file(&cargo_toml, toml) -} - -use crate::tokens::*; -use metadata::*; -use method_names::*; -use std::collections::*; -use std::fmt::Write; -use try_format::*; -use writer::*; - -fn namespace(writer: &Writer, tree: &Tree) -> String { - let writer = &mut writer.clone(); - writer.namespace = tree.namespace; - let mut tokens = TokenStream::new(); - - for (name, tree) in &tree.nested { - let name = to_ident(name); - let namespace_feature = - tree.namespace[tree.namespace.find('.').unwrap() + 1..].replace('.', "_"); - if writer.package { - tokens.combine("e! { - #[cfg(feature = #namespace_feature)] - pub mod #name; - }); - } else { - tokens.combine("e! { pub mod #name }); - tokens.push_str("{"); - tokens.push_str(&namespace(writer, tree)); - tokens.push_str("}"); - } - } - - let mut functions = BTreeMap::<&str, TokenStream>::new(); - let mut types = BTreeMap::>::new(); - - for item in writer - .reader - .namespace_items(writer.namespace, writer.filter) - { - match item { - Item::Type(def) => { - let type_name = writer.reader.type_def_type_name(def); - if REMAP_TYPES.iter().any(|(x, _)| x == &type_name) { - continue; - } - if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { - continue; - } - let name = type_name.name; - let kind = writer.reader.type_def_kind(def); - match kind { - TypeKind::Class => { - if writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - types - .entry(kind) - .or_default() - .insert(name, classes::writer(writer, def)); - } - } - TypeKind::Interface => types - .entry(kind) - .or_default() - .entry(name) - .or_default() - .combine(&interfaces::writer(writer, def)), - TypeKind::Enum => types - .entry(kind) - .or_default() - .entry(name) - .or_default() - .combine(&enums::writer(writer, def)), - TypeKind::Struct => { - if writer.reader.type_def_fields(def).next().is_none() { - if let Some(guid) = writer.reader.type_def_guid(def) { - let ident = to_ident(name); - let value = writer.guid(&guid); - let guid = writer.type_name(&Type::GUID); - let cfg = type_def_cfg(writer.reader, def, &[]); - let doc = writer.cfg_doc(&cfg); - let constant = quote! { - #doc - pub const #ident: #guid = #value; - }; - types - .entry(TypeKind::Class) - .or_default() - .entry(name) - .or_default() - .combine(&constant); - continue; - } - } - types - .entry(kind) - .or_default() - .entry(name) - .or_default() - .combine(&structs::writer(writer, def)); - } - TypeKind::Delegate => types - .entry(kind) - .or_default() - .entry(name) - .or_default() - .combine(&delegates::writer(writer, def)), - } - } - Item::Fn(def, namespace) => { - let name = writer.reader.method_def_name(def); - functions - .entry(name) - .or_default() - .combine(&functions::writer(writer, &namespace, def)); - } - Item::Const(def) => { - let name = writer.reader.field_name(def); - types - .entry(TypeKind::Class) - .or_default() - .entry(name) - .or_default() - .combine(&constants::writer(writer, def)); - } - } - } - - for function in functions.values() { - tokens.combine(function); - } - - for ty in types.values().flat_map(|v| v.values()) { - tokens.combine(ty); - } - - tokens.combine(&extensions::gen_mod(writer, tree.namespace)); - - if writer.implement { - tokens.push_str(&namespace_impl(writer, tree)); - } - - tokens.into_string() -} - -fn namespace_impl(writer: &Writer, tree: &Tree) -> String { - let writer = &mut writer.clone(); - writer.namespace = tree.namespace; - let mut types = BTreeMap::<&str, TokenStream>::new(); - - for item in writer - .reader - .namespace_items(writer.namespace, writer.filter) - { - if let Item::Type(def) = item { - let type_name = writer.reader.type_def_type_name(def); - if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { - continue; - } - if writer.reader.type_def_kind(def) != TypeKind::Interface { - continue; - } - let tokens = implements::writer(writer, def); - - if !tokens.is_empty() { - types.insert(type_name.name, tokens); - } - } - } - - let types = types.values(); - - let mut tokens = quote! { - #(#types)* - }; - - tokens.combine(&extensions::gen_impl(tree.namespace)); - tokens.into_string() -} - -/// Expand a possibly empty generics list with a new generic -fn expand_generics(generics: TokenStream, new: TokenStream) -> TokenStream { - if generics.is_empty() { - quote!(#new) - } else { - quote!(#generics, #new) - } -} - -/// Expand a possibly emppty where clause with a new generic constraint -fn expand_where_clause(where_clause: TokenStream, generic: TokenStream) -> TokenStream { - if where_clause.is_empty() { - quote!(where #generic) - } else { - quote!(#where_clause #generic) - } -} diff --git a/crates/tools/riddle/src/rust/standalone.rs b/crates/tools/riddle/src/rust/standalone.rs deleted file mode 100644 index 795fb6c34b..0000000000 --- a/crates/tools/riddle/src/rust/standalone.rs +++ /dev/null @@ -1,264 +0,0 @@ -use super::*; - -pub fn standalone_imp(writer: &Writer) -> String { - let mut types = BTreeSet::new(); - let mut functions = BTreeSet::new(); - let mut constants = BTreeSet::new(); - - for item in writer.reader.items(writer.filter) { - item_collect_standalone(writer.reader, item.clone(), &mut types); - - match item { - Item::Type(_) => {} - Item::Fn(def, namespace) => _ = functions.insert((def, namespace.clone())), - Item::Const(def) => _ = constants.insert(def), - } - } - - let mut sorted = SortedTokens::default(); - - for ty in types { - match ty { - Type::HRESULT if writer.sys => { - sorted.insert("HRESULT", quote! { pub type HRESULT = i32; }) - } - Type::String if writer.sys => sorted.insert( - "HSTRING", - quote! { pub type HSTRING = *mut ::core::ffi::c_void; }, - ), - Type::IUnknown if writer.sys => sorted.insert( - "IUnknown", - quote! { pub type IUnknown = *mut ::core::ffi::c_void; }, - ), - Type::IInspectable if writer.sys => sorted.insert( - "IInspectable", - quote! { pub type IInspectable = *mut ::core::ffi::c_void; }, - ), - Type::PSTR if writer.sys => sorted.insert("PSTR", quote! { pub type PSTR = *mut u8; }), - Type::PWSTR if writer.sys => { - sorted.insert("PWSTR", quote! { pub type PWSTR = *mut u16; }) - } - Type::PCSTR if writer.sys => { - sorted.insert("PCSTR", quote! { pub type PCSTR = *const u8; }) - } - Type::PCWSTR if writer.sys => { - sorted.insert("PCWSTR", quote! { pub type PCWSTR = *const u16; }) - } - Type::BSTR if writer.sys => { - sorted.insert("BSTR", quote! { pub type BSTR = *const u16; }) - } - Type::GUID if writer.sys => { - sorted.insert("GUID", quote! { - #[repr(C)] - pub struct GUID { - pub data1: u32, - pub data2: u16, - pub data3: u16, - pub data4: [u8; 8], - } - impl ::core::marker::Copy for GUID {} - impl ::core::clone::Clone for GUID { - fn clone(&self) -> Self { - *self - } - } - impl GUID { - pub const fn from_u128(uuid: u128) -> Self { - Self { data1: (uuid >> 96) as u32, data2: (uuid >> 80 & 0xffff) as u16, data3: (uuid >> 64 & 0xffff) as u16, data4: (uuid as u64).to_be_bytes() } - } - } - }); - } - Type::TypeDef(def, _) => { - let kind = writer.reader.type_def_kind(def); - match kind { - TypeKind::Class => { - let name = writer.reader.type_def_name(def); - if writer.sys { - let ident = to_ident(name); - sorted.insert( - name, - quote! { pub type #ident = *mut ::core::ffi::c_void; }, - ); - } else { - sorted.insert(name, classes::writer(writer, def)); - } - } - TypeKind::Interface => { - let name = writer.reader.type_def_name(def); - if writer.sys { - let ident = to_ident(name); - sorted.insert( - name, - quote! { pub type #ident = *mut ::core::ffi::c_void; }, - ); - } else { - sorted.insert(name, interfaces::writer(writer, def)); - } - } - TypeKind::Enum => { - sorted.insert(writer.reader.type_def_name(def), enums::writer(writer, def)); - } - TypeKind::Struct => { - let name = writer.reader.type_def_name(def); - if writer.reader.type_def_fields(def).next().is_none() { - if let Some(guid) = writer.reader.type_def_guid(def) { - let ident = to_ident(name); - let value = writer.guid(&guid); - let guid = writer.type_name(&Type::GUID); - sorted.insert( - name, - quote! { - pub const #ident: #guid = #value; - }, - ); - continue; - } - } - sorted.insert(name, structs::writer(writer, def)); - } - TypeKind::Delegate => { - sorted.insert( - writer.reader.type_def_name(def), - delegates::writer(writer, def), - ); - } - } - } - _ => {} - } - } - - for (function, namespace) in functions { - sorted.insert( - &format!( - ".{}.{}", - writer.reader.method_def_module_name(function), - writer.reader.method_def_name(function) - ), - functions::writer(writer, &namespace, function), - ); - } - - for constant in constants { - sorted.insert( - writer.reader.field_name(constant), - constants::writer(writer, constant), - ); - } - - let mut tokens = TokenStream::new(); - sorted.0.values().for_each(|value| tokens.combine(value)); - tokens.into_string() -} - -#[derive(Default)] -struct SortedTokens(BTreeMap); - -impl SortedTokens { - fn insert(&mut self, key: &str, tokens: TokenStream) { - self.0.entry(key.to_string()).or_default().combine(&tokens); - } -} - -fn item_collect_standalone(reader: &Reader, item: Item, set: &mut BTreeSet) { - match item { - Item::Type(def) => type_collect_standalone(reader, &Type::TypeDef(def, vec![]), set), - Item::Const(def) => { - type_collect_standalone(reader, &reader.field_type(def, None).to_const_type(), set) - } - Item::Fn(def, namespace) => { - let signature = method_def_signature(reader, &namespace, def, &[]); - type_collect_standalone(reader, &signature.return_type, set); - signature - .params - .iter() - .for_each(|param| type_collect_standalone(reader, ¶m.ty, set)); - } - } -} -// TODO: remove or move to riddle -fn type_collect_standalone(reader: &Reader, ty: &Type, set: &mut BTreeSet) { - let ty = ty.to_underlying_type(); - if !set.insert(ty.clone()) { - return; - } - - let Type::TypeDef(def, generics) = &ty else { - return; - }; - - let def = *def; - - // Ensure that we collect all the typedefs of the same name. We need to - // do this in the case where the user specifies a top level item that - // references a typedef by name, but that name resolves to more than 1 - // Type based on target architecture (typically) - // - // Note this is a bit overeager as we can collect a typedef that is used - // by one architecture but not by another - let type_name = reader.type_def_type_name(def); - if !type_name.namespace.is_empty() { - for row in reader.get_type_def(type_name) { - if def != row { - type_collect_standalone(reader, &Type::TypeDef(row, Vec::new()), set); - } - } - } - - for generic in generics { - type_collect_standalone(reader, generic, set); - } - for field in reader.type_def_fields(def) { - let ty = reader.field_type(field, Some(def)); - if let Type::TypeDef(def, _) = &ty { - if reader.type_def_namespace(*def).is_empty() { - continue; - } - } - type_collect_standalone(reader, &ty, set); - } - for method in reader.type_def_methods(def) { - // Skip delegate pseudo-constructors. - if reader.method_def_name(method) == ".ctor" { - continue; - } - let signature = - method_def_signature(reader, reader.type_def_namespace(def), method, generics); - type_collect_standalone(reader, &signature.return_type, set); - signature - .params - .iter() - .for_each(|param| type_collect_standalone(reader, ¶m.ty, set)); - } - for interface in type_interfaces(reader, &ty) { - type_collect_standalone(reader, &interface.ty, set); - } - if reader.type_def_kind(def) == TypeKind::Struct - && reader.type_def_fields(def).next().is_none() - && reader.type_def_guid(def).is_some() - { - set.insert(Type::GUID); - } - - type_collect_standalone_nested(reader, def, set); -} - -fn type_collect_standalone_nested(reader: &Reader, td: TypeDef, set: &mut BTreeSet) { - for nested in reader.nested_types(td) { - type_collect_standalone_nested(reader, nested, set); - - for field in reader.type_def_fields(nested) { - let ty = reader.field_type(field, Some(nested)); - if let Type::TypeDef(def, _) = &ty { - // Skip the fields that actually refer to the anonymous nested - // type, otherwise it will get added to the typeset and emitted - if reader.type_def_namespace(*def).is_empty() { - continue; - } - - type_collect_standalone(reader, &ty, set); - } - } - } -} diff --git a/crates/tools/riddle/src/rust/structs.rs b/crates/tools/riddle/src/rust/structs.rs deleted file mode 100644 index 0799cb9868..0000000000 --- a/crates/tools/riddle/src/rust/structs.rs +++ /dev/null @@ -1,350 +0,0 @@ -use super::*; - -pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { - if writer.reader.has_attribute(def, "ApiContractAttribute") { - return quote! {}; - } - - if writer.reader.type_def_is_handle(def) { - return handles::writer(writer, def); - } - - gen_struct_with_name( - writer, - def, - writer.reader.type_def_name(def), - &Cfg::default(), - ) -} - -fn gen_struct_with_name( - writer: &Writer, - def: TypeDef, - struct_name: &str, - cfg: &Cfg, -) -> TokenStream { - let name = to_ident(struct_name); - - if writer.reader.type_def_fields(def).next().is_none() { - let mut tokens = quote! { - #[repr(C)] - pub struct #name(pub u8); - impl ::core::marker::Copy for #name {} - impl ::core::clone::Clone for #name { - fn clone(&self) -> Self { - *self - } - } - }; - if !writer.sys { - tokens.combine("e! { - impl ::windows_core::TypeKind for #name { - type TypeKind = ::windows_core::CopyType; - } - }); - } - return tokens; - } - - let flags = writer.reader.type_def_flags(def); - let cfg = cfg.union(&type_def_cfg(writer.reader, def, &[])); - - let repr = if let Some(layout) = writer.reader.type_def_class_layout(def) { - let packing = Literal::usize_unsuffixed(writer.reader.class_layout_packing_size(layout)); - quote! { #[repr(C, packed(#packing))] } - } else { - quote! { #[repr(C)] } - }; - - let fields = writer.reader.type_def_fields(def).map(|f| { - let name = to_ident(writer.reader.field_name(f)); - let ty = writer.reader.field_type(f, Some(def)); - - if writer - .reader - .field_flags(f) - .contains(FieldAttributes::Literal) - { - quote! {} - } else if !writer.sys - && flags.contains(TypeAttributes::ExplicitLayout) - && !writer.reader.field_is_copyable(f, def) - { - let ty = writer.type_default_name(&ty); - quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } - } else if !writer.sys - && !flags.contains(TypeAttributes::WindowsRuntime) - && !writer.reader.field_is_blittable(f, def) - { - if let Type::Win32Array(ty, len) = ty { - let ty = writer.type_default_name(&ty); - quote! { pub #name: [::std::mem::ManuallyDrop<#ty>; #len], } - } else { - let ty = writer.type_default_name(&ty); - quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } - } - } else { - let ty = writer.type_default_name(&ty); - quote! { pub #name: #ty, } - } - }); - - let struct_or_union = if flags.contains(TypeAttributes::ExplicitLayout) { - quote! { union } - } else { - quote! { struct } - }; - - let doc = writer.cfg_doc(&cfg); - let features = writer.cfg_features(&cfg); - - let mut tokens = quote! { - #repr - #doc - #features - pub #struct_or_union #name {#(#fields)*} - }; - - tokens.combine(&gen_struct_constants(writer, def, &name, &cfg)); - tokens.combine(&gen_copy_clone(writer, def, &name, &cfg)); - tokens.combine(&gen_debug(writer, def, &name, &cfg)); - tokens.combine(&gen_windows_traits(writer, def, &name, &cfg)); - tokens.combine(&gen_compare_traits(writer, def, &name, &cfg)); - - if !writer.sys { - tokens.combine("e! { - #features - impl ::core::default::Default for #name { - fn default() -> Self { - unsafe { ::core::mem::zeroed() } - } - } - }); - } - - for (index, nested_type) in writer.reader.nested_types(def).enumerate() { - let nested_name = format!("{struct_name}_{index}"); - tokens.combine(&gen_struct_with_name( - writer, - nested_type, - &nested_name, - &cfg, - )); - } - - tokens -} - -fn gen_windows_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { - if writer.sys { - quote! {} - } else { - let features = writer.cfg_features(cfg); - let is_copy = writer.reader.type_def_is_blittable(def); - - let type_kind = if is_copy { - quote! { CopyType } - } else { - quote! { ValueType } - }; - - let mut tokens = quote! { - #features - impl ::windows_core::TypeKind for #name { - type TypeKind = ::windows_core::#type_kind; - } - }; - - if writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - let signature = - Literal::byte_string(writer.reader.type_def_signature(def, &[]).as_bytes()); - - tokens.combine("e! { - #features - impl ::windows_core::RuntimeType for #name { - const SIGNATURE: ::windows_core::imp::ConstBuffer = ::windows_core::imp::ConstBuffer::from_slice(#signature); - } - }); - } - - tokens - } -} - -fn gen_compare_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { - let features = writer.cfg_features(cfg); - - if writer.sys - || writer.reader.type_def_has_explicit_layout(def) - || writer.reader.type_def_has_packing(def) - || type_def_has_callback(writer.reader, def) - { - quote! {} - } else { - let fields = writer.reader.type_def_fields(def).filter_map(|f| { - let name = to_ident(writer.reader.field_name(f)); - if writer - .reader - .field_flags(f) - .contains(FieldAttributes::Literal) - { - None - } else { - Some(quote! { self.#name == other.#name }) - } - }); - - quote! { - #features - impl ::core::cmp::PartialEq for #name { - fn eq(&self, other: &Self) -> bool { - #(#fields)&&* - } - } - #features - impl ::core::cmp::Eq for #name {} - } - } -} - -fn gen_debug(writer: &Writer, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> TokenStream { - if writer.sys - || writer.reader.type_def_has_explicit_layout(def) - || writer.reader.type_def_has_packing(def) - { - quote! {} - } else { - let name = ident.as_str(); - let features = writer.cfg_features(cfg); - - let fields = writer.reader.type_def_fields(def).filter_map(|f| { - if writer - .reader - .field_flags(f) - .contains(FieldAttributes::Literal) - { - None - } else { - let name = writer.reader.field_name(f); - let ident = to_ident(name); - let ty = writer.reader.field_type(f, Some(def)); - if type_has_callback(writer.reader, &ty) { - None - } else { - Some(quote! { .field(#name, &self.#ident) }) - } - } - }); - - quote! { - #features - impl ::core::fmt::Debug for #ident { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_struct(#name) #(#fields)* .finish() - } - } - } - } -} - -fn gen_copy_clone(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { - let features = writer.cfg_features(cfg); - - if writer.sys || writer.reader.type_def_is_copyable(def) { - quote! { - #features - impl ::core::marker::Copy for #name {} - #features - impl ::core::clone::Clone for #name { - fn clone(&self) -> Self { - *self - } - } - } - } else if writer.reader.type_def_class_layout(def).is_some() { - // Don't support copy/clone of packed structs: https://github.com/rust-lang/rust/issues/82523 - quote! {} - } else if !writer - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - quote! { - #features - impl ::core::clone::Clone for #name { - fn clone(&self) -> Self { - unsafe { ::core::mem::transmute_copy(self) } - } - } - } - } else { - let fields = writer.reader.type_def_fields(def).map(|f| { - let name = to_ident(writer.reader.field_name(f)); - if writer - .reader - .field_flags(f) - .contains(FieldAttributes::Literal) - { - quote! {} - } else if writer.reader.field_is_blittable(f, def) { - quote! { #name: self.#name } - } else { - quote! { #name: self.#name.clone() } - } - }); - - quote! { - #features - impl ::core::clone::Clone for #name { - fn clone(&self) -> Self { - Self { #(#fields),* } - } - } - } - } -} - -fn gen_struct_constants( - writer: &Writer, - def: TypeDef, - struct_name: &TokenStream, - cfg: &Cfg, -) -> TokenStream { - let features = writer.cfg_features(cfg); - - let constants = writer.reader.type_def_fields(def).filter_map(|f| { - if writer - .reader - .field_flags(f) - .contains(FieldAttributes::Literal) - { - if let Some(constant) = writer.reader.field_constant(f) { - let name = to_ident(writer.reader.field_name(f)); - let value = writer.typed_value(&writer.reader.constant_value(constant)); - - return Some(quote! { - pub const #name: #value; - }); - } - } - - None - }); - - let mut tokens = quote! { #(#constants)* }; - - if !tokens.is_empty() { - tokens = quote! { - #features - impl #struct_name { - #tokens - } - }; - } - - tokens -} diff --git a/crates/tools/riddle/src/rust/try_format.rs b/crates/tools/riddle/src/rust/try_format.rs deleted file mode 100644 index fc0ac96a25..0000000000 --- a/crates/tools/riddle/src/rust/try_format.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::io::Write; - -pub fn try_format(writer: &super::Writer, tokens: &str) -> String { - let version = std::env!("CARGO_PKG_VERSION"); - - // Packaging - e.g. windows/windows-sys crates - assumes the crate will allow whatever warnings it deems fit. - let allow = if writer.package { - "" - } else { - "#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]\n" - }; - - let tokens = format!( - r#"// Bindings generated by `riddle` {version} - -{allow}{tokens}"# - ); - - let Ok(mut child) = std::process::Command::new("rustfmt") - .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::null()) - .spawn() - else { - return tokens; - }; - - let Some(mut stdin) = child.stdin.take() else { - return tokens; - }; - - if stdin.write_all(tokens.as_bytes()).is_err() { - return tokens; - } - - drop(stdin); - - let Ok(output) = child.wait_with_output() else { - return tokens; - }; - - if !output.status.success() { - return tokens; - } - - if let Ok(result) = String::from_utf8(output.stdout) { - result - } else { - tokens - } -} diff --git a/crates/tools/riddle/src/rust/winrt_methods.rs b/crates/tools/riddle/src/rust/winrt_methods.rs deleted file mode 100644 index 7f9c8acfba..0000000000 --- a/crates/tools/riddle/src/rust/winrt_methods.rs +++ /dev/null @@ -1,271 +0,0 @@ -use super::*; - -// TODO take Signature instead of MethodDef (wherever MethodDef is found) -pub fn writer( - writer: &Writer, - def: TypeDef, - generic_types: &[Type], - kind: InterfaceKind, - method: MethodDef, - method_names: &mut MethodNames, - virtual_names: &mut MethodNames, -) -> TokenStream { - let signature = method_def_signature( - writer.reader, - writer.reader.type_def_namespace(def), - method, - generic_types, - ); - let params = &signature.params; - let name = method_names.add(writer, method); - let interface_name = writer.type_def_name(def, generic_types); - let vname = virtual_names.add(writer, method); - let generics = writer.constraint_generics(params); - let where_clause = writer.where_clause(params); - let mut cfg = signature_cfg(writer.reader, method); - type_def_cfg_combine(writer.reader, def, generic_types, &mut cfg); - let doc = writer.cfg_method_doc(&cfg); - let features = writer.cfg_features(&cfg); - let args = gen_winrt_abi_args(writer, params); - let params = gen_winrt_params(writer, params); - - let return_type_tokens = match &signature.return_type { - Type::Void => quote! { () }, - _ => { - let tokens = writer.type_name(&signature.return_type); - if signature.return_type.is_winrt_array() { - quote! { ::windows_core::Array<#tokens> } - } else { - quote! { #tokens } - } - } - }; - - let return_arg = match &signature.return_type { - Type::Void => quote! {}, - _ => { - if signature.return_type.is_winrt_array() { - let return_type = writer.type_name(&signature.return_type); - quote! { ::windows_core::Array::<#return_type>::set_abi_len(::std::mem::transmute(&mut result__)), result__.as_mut_ptr() as *mut _ as _ } - } else { - quote! { &mut result__ } - } - } - }; - - let vcall = match &signature.return_type { - Type::Void => { - quote! { - (::windows_core::Interface::vtable(this).#vname)(::windows_core::Interface::as_raw(this), #args).ok() - } - } - _ if signature.return_type.is_winrt_array() => { - quote! { - let mut result__ = ::core::mem::MaybeUninit::zeroed(); - (::windows_core::Interface::vtable(this).#vname)(::windows_core::Interface::as_raw(this), #args #return_arg) - .and_then(|| result__.assume_init()) - } - } - _ => { - quote! { - let mut result__ = ::std::mem::zeroed(); - (::windows_core::Interface::vtable(this).#vname)(::windows_core::Interface::as_raw(this), #args #return_arg) - .from_abi(result__) - } - } - }; - - match kind { - InterfaceKind::Default => quote! { - #doc - #features - pub fn #name<#generics>(&self, #params) -> ::windows_core::Result<#return_type_tokens> #where_clause { - let this = self; - unsafe { - #vcall - } - } - }, - InterfaceKind::None | InterfaceKind::Base | InterfaceKind::Overridable => { - quote! { - #doc - #features - pub fn #name<#generics>(&self, #params) -> ::windows_core::Result<#return_type_tokens> #where_clause { - let this = &::windows_core::ComInterface::cast::<#interface_name>(self)?; - unsafe { - #vcall - } - } - } - } - InterfaceKind::Static => { - quote! { - #doc - #features - pub fn #name<#generics>(#params) -> ::windows_core::Result<#return_type_tokens> #where_clause { - Self::#interface_name(|this| unsafe { #vcall }) - } - } - } - } -} - -fn gen_winrt_params(writer: &Writer, params: &[SignatureParam]) -> TokenStream { - let mut result = quote! {}; - - let mut generic_params = writer.generic_params(params); - for param in params.iter() { - let name = writer.param_name(param.def); - let kind = writer.type_name(¶m.ty); - let default_type = writer.type_default_name(¶m.ty); - - if writer - .reader - .param_flags(param.def) - .contains(ParamAttributes::In) - { - if param.ty.is_winrt_array() { - result.combine("e! { #name: &[#default_type], }); - } else if signature_param_is_convertible(writer.reader, param) { - let (position, _) = generic_params.next().unwrap(); - let kind: TokenStream = format!("P{position}").into(); - result.combine("e! { #name: #kind, }); - } else if writer.reader.type_is_blittable(¶m.ty) { - result.combine("e! { #name: #kind, }); - } else { - result.combine("e! { #name: &#kind, }); - } - } else if param.ty.is_winrt_array() { - result.combine("e! { #name: &mut [#default_type], }); - } else if param.ty.is_winrt_array_ref() { - result.combine("e! { #name: &mut ::windows_core::Array<#kind>, }); - } else { - result.combine("e! { #name: &mut #default_type, }); - } - } - - result -} - -fn gen_winrt_abi_args(writer: &Writer, params: &[SignatureParam]) -> TokenStream { - let mut tokens = TokenStream::new(); - for param in params { - let name = writer.param_name(param.def); - - let param = if writer - .reader - .param_flags(param.def) - .contains(ParamAttributes::In) - { - if param.ty.is_winrt_array() { - if writer.reader.type_is_blittable(¶m.ty) { - quote! { #name.len() as u32, #name.as_ptr(), } - } else { - quote! { #name.len() as u32, ::core::mem::transmute(#name.as_ptr()), } - } - } else if type_is_non_exclusive_winrt_interface(writer.reader, ¶m.ty) { - quote! { #name.try_into_param()?.abi(), } - } else if signature_param_is_borrowed(writer.reader, param) { - quote! { #name.into_param().abi(), } - } else if writer.reader.type_is_blittable(¶m.ty) { - if param.ty.is_const_ref() { - quote! { &#name, } - } else { - quote! { #name, } - } - } else { - quote! { ::core::mem::transmute_copy(#name), } - } - } else if param.ty.is_winrt_array() { - if writer.reader.type_is_blittable(¶m.ty) { - quote! { #name.len() as u32, #name.as_mut_ptr(), } - } else { - quote! { #name.len() as u32, ::core::mem::transmute_copy(&#name), } - } - } else if param.ty.is_winrt_array_ref() { - quote! { #name.set_abi_len(), #name as *mut _ as _, } - } else if writer.reader.type_is_blittable(¶m.ty) { - quote! { #name, } - } else { - quote! { #name as *mut _ as _, } - }; - tokens.combine(¶m); - } - tokens -} - -pub fn gen_upcall(writer: &Writer, sig: &Signature, inner: TokenStream) -> TokenStream { - let invoke_args = sig - .params - .iter() - .map(|param| gen_winrt_invoke_arg(writer, param)); - - match &sig.return_type { - Type::Void => quote! { - #inner(#(#invoke_args,)*).into() - }, - _ if sig.return_type.is_winrt_array() => { - quote! { - match #inner(#(#invoke_args,)*) { - ::core::result::Result::Ok(ok__) => { - let (ok_data__, ok_data_len__) = ok__.into_abi(); - // use `core::ptr::write` since `result` could be uninitialized - ::core::ptr::write(result__, ok_data__); - ::core::ptr::write(result_size__, ok_data_len__); - ::windows_core::HRESULT(0) - } - ::core::result::Result::Err(err) => err.into() - } - } - } - _ => { - let forget = if writer.reader.type_is_blittable(&sig.return_type) { - quote! {} - } else { - quote! { ::core::mem::forget(ok__); } - }; - - quote! { - match #inner(#(#invoke_args,)*) { - ::core::result::Result::Ok(ok__) => { - // use `core::ptr::write` since `result` could be uninitialized - ::core::ptr::write(result__, ::core::mem::transmute_copy(&ok__)); - #forget - ::windows_core::HRESULT(0) - } - ::core::result::Result::Err(err) => err.into() - } - } - } - } -} - -fn gen_winrt_invoke_arg(writer: &Writer, param: &SignatureParam) -> TokenStream { - let name = writer.param_name(param.def); - let abi_size_name: TokenStream = - format!("{}_array_size", writer.reader.param_name(param.def)).into(); - - if writer - .reader - .param_flags(param.def) - .contains(ParamAttributes::In) - { - if param.ty.is_winrt_array() { - quote! { ::core::slice::from_raw_parts(::core::mem::transmute_copy(&#name), #abi_size_name as usize) } - } else if writer.reader.type_is_primitive(¶m.ty) { - quote! { #name } - } else if param.ty.is_const_ref() { - quote! { ::core::mem::transmute_copy(&#name) } - } else if writer.reader.type_is_nullable(¶m.ty) { - quote! { ::windows_core::from_raw_borrowed(&#name) } - } else { - quote! { ::core::mem::transmute(&#name) } - } - } else if param.ty.is_winrt_array() { - quote! { ::core::slice::from_raw_parts_mut(::core::mem::transmute_copy(&#name), #abi_size_name as usize) } - } else if param.ty.is_winrt_array_ref() { - quote! { ::windows_core::ArrayProxy::from_raw_parts(::core::mem::transmute_copy(&#name), #abi_size_name).as_array() } - } else { - quote! { ::core::mem::transmute_copy(&#name) } - } -} diff --git a/crates/tools/riddle/src/rust/writer.rs b/crates/tools/riddle/src/rust/writer.rs deleted file mode 100644 index 909179fa50..0000000000 --- a/crates/tools/riddle/src/rust/writer.rs +++ /dev/null @@ -1,1419 +0,0 @@ -use super::*; - -#[derive(Clone)] -pub struct Writer<'a> { - pub reader: &'a Reader<'a>, - pub filter: &'a metadata::Filter<'a>, - pub output: &'a str, - pub namespace: &'a str, - pub implement: bool, // TODO: ideally we can use this to generate implementation traits on the fly and - // and have a single interface definition macro for consumption that expands to include - // impl traits when the `implement` cfg flag is set and then this writer option would be - // unecessary. - // - // Maybe this macro is the embedable version of the IDL format?! like a more intelligient - // version of the existing interface macro... - pub std: bool, // tweaks for internal std library support - pub sys: bool, // writer sys-style bindings - pub flatten: bool, // strips out namespaces - implies !package - pub package: bool, // default is single file with no cfg - implies !flatten - pub minimal: bool, // strips out enumerators - in future possibly other helpers as well -} - -impl<'a> Writer<'a> { - pub fn new(reader: &'a Reader, filter: &'a metadata::Filter, output: &'a str) -> Self { - Self { - reader, - filter, - output, - namespace: "", - implement: false, - std: false, - sys: false, - flatten: false, - package: false, - minimal: false, - } - } - - // - // TypeDef - // - - pub fn type_def_name(&self, def: TypeDef, generics: &[Type]) -> TokenStream { - self.type_def_name_imp(def, generics, "") - } - pub fn type_def_vtbl_name(&self, def: TypeDef, generics: &[Type]) -> TokenStream { - self.type_def_name_imp(def, generics, "_Vtbl") - } - pub fn type_def_name_imp(&self, def: TypeDef, generics: &[Type], suffix: &str) -> TokenStream { - let type_name = self.reader.type_def_type_name(def); - - if type_name.namespace.is_empty() { - to_ident(&self.scoped_name(def)) - } else { - let mut namespace = self.namespace(type_name.namespace); - let mut name = to_ident(type_name.name); - name.push_str(suffix); - - if generics.is_empty() || self.sys { - namespace.combine(&name); - namespace - } else { - let colon_separated = if !namespace.as_str().is_empty() { - quote! { :: } - } else { - quote! {} - }; - - let generics = generics.iter().map(|ty| self.type_name(ty)); - quote! { #namespace #name #colon_separated<#(#generics),*> } - } - } - } - - // - // Type - // - - pub fn type_default_name(&self, ty: &Type) -> TokenStream { - if let Type::WinrtArray(ty) = ty { - self.type_default_name(ty) - } else { - let kind = self.type_name(ty); - - if ty.is_generic() { - quote! { <#kind as ::windows_core::Type<#kind>>::Default } - } else if self.reader.type_is_nullable(ty) && !self.sys { - quote! { ::core::option::Option<#kind> } - } else { - kind - } - } - } - - pub(crate) fn type_name(&self, ty: &Type) -> TokenStream { - match ty { - Type::Void => quote! { ::core::ffi::c_void }, - Type::Bool => quote! { bool }, - Type::Char => quote! { u16 }, - Type::I8 => quote! { i8 }, - Type::U8 => quote! { u8 }, - Type::I16 => quote! { i16 }, - Type::U16 => quote! { u16 }, - Type::I32 => quote! { i32 }, - Type::U32 => quote! { u32 }, - Type::I64 => quote! { i64 }, - Type::U64 => quote! { u64 }, - Type::F32 => quote! { f32 }, - Type::F64 => quote! { f64 }, - Type::ISize => quote! { isize }, - Type::USize => quote! { usize }, - Type::String => { - let crate_name = self.crate_name(); - quote! { #crate_name HSTRING } - } - Type::BSTR => { - let crate_name = self.crate_name(); - quote! { #crate_name BSTR } - } - Type::IInspectable => { - let crate_name = self.crate_name(); - quote! { #crate_name IInspectable } - } - Type::GUID => { - let crate_name = self.crate_name(); - quote! { #crate_name GUID } - } - Type::IUnknown => { - let crate_name = self.crate_name(); - quote! { #crate_name IUnknown } - } - Type::HRESULT => { - let crate_name = self.crate_name(); - quote! { #crate_name HRESULT } - } - Type::PSTR => { - let crate_name = self.crate_name(); - quote! { #crate_name PSTR } - } - Type::PWSTR => { - let crate_name = self.crate_name(); - quote! { #crate_name PWSTR } - } - Type::PCSTR => { - let crate_name = self.crate_name(); - quote! { #crate_name PCSTR } - } - Type::PCWSTR => { - let crate_name = self.crate_name(); - quote! { #crate_name PCWSTR } - } - Type::Win32Array(ty, len) => { - let name = self.type_default_name(ty); - let len = Literal::usize_unsuffixed(*len); - quote! { [#name; #len] } - } - Type::GenericParam(generic) => self.reader.generic_param_name(*generic).into(), - Type::TypeDef(def, generics) => self.type_def_name(*def, generics), - Type::MutPtr(ty, pointers) => { - let pointers = mut_ptrs(*pointers); - let ty = self.type_default_name(ty); - quote! { #pointers #ty } - } - Type::ConstPtr(ty, pointers) => { - let pointers = const_ptrs(*pointers); - let ty = self.type_default_name(ty); - quote! { #pointers #ty } - } - Type::WinrtArray(ty) => self.type_name(ty), - Type::WinrtArrayRef(ty) => self.type_name(ty), - Type::ConstRef(ty) => self.type_name(ty), - Type::PrimitiveOrEnum(_, ty) => self.type_name(ty), - rest => unimplemented!("{rest:?}"), - } - } - pub fn type_vtbl_name(&self, ty: &Type) -> TokenStream { - match ty { - Type::TypeDef(def, generics) => self.type_def_vtbl_name(*def, generics), - rest => unimplemented!("{rest:?}"), - } - } - pub fn type_abi_name(&self, ty: &Type) -> TokenStream { - if self.sys { - return match ty { - Type::PrimitiveOrEnum(ty, _) => self.type_default_name(ty), - _ => self.type_default_name(ty), - }; - } - - match ty { - Type::IUnknown | Type::IInspectable => { - quote! { *mut ::core::ffi::c_void } - } - Type::String => { - quote! { ::std::mem::MaybeUninit<::windows_core::HSTRING> } - } - Type::BSTR => { - quote! { ::std::mem::MaybeUninit<::windows_core::BSTR> } - } - Type::Win32Array(kind, len) => { - let name = self.type_abi_name(kind); - let len = Literal::usize_unsuffixed(*len); - quote! { [#name; #len] } - } - Type::GenericParam(generic) => { - let name = to_ident(self.reader.generic_param_name(*generic)); - quote! { ::windows_core::AbiType<#name> } - } - Type::TypeDef(def, _) => match self.reader.type_def_kind(*def) { - TypeKind::Enum => self.type_def_name(*def, &[]), - TypeKind::Struct => { - let tokens = self.type_def_name(*def, &[]); - if self.reader.type_def_is_blittable(*def) { - tokens - } else { - quote! { ::std::mem::MaybeUninit<#tokens> } - } - } - TypeKind::Delegate => { - if self - .reader - .type_def_flags(*def) - .contains(TypeAttributes::WindowsRuntime) - { - quote! { *mut ::core::ffi::c_void } - } else { - self.type_def_name(*def, &[]) - } - } - _ => quote! { *mut ::core::ffi::c_void }, - }, - Type::MutPtr(kind, pointers) => { - let pointers_tokens = gen_mut_ptrs(*pointers); - let kind = if *pointers > 1 { - self.type_name(kind) - } else { - self.type_abi_name(kind) - }; - quote! { #pointers_tokens #kind } - } - Type::ConstPtr(kind, pointers) => { - let pointers_tokens = gen_const_ptrs(*pointers); - let kind = if *pointers > 1 { - self.type_name(kind) - } else { - self.type_abi_name(kind) - }; - quote! { #pointers_tokens #kind } - } - Type::WinrtArray(kind) => self.type_abi_name(kind), - Type::WinrtArrayRef(kind) => self.type_abi_name(kind), - Type::PrimitiveOrEnum(ty, _) => self.type_name(ty), - _ => self.type_name(ty), - } - } - - // - // Constraints - // - - pub fn generic_phantoms(&self, generics: &[Type]) -> TokenStream { - let mut tokens = TokenStream::new(); - for generic in generics { - let generic = self.type_name(generic); - tokens.combine("e! { ::core::marker::PhantomData::<#generic>, }); - } - tokens - } - pub fn generic_named_phantoms(&self, generics: &[Type]) -> Vec { - generics - .iter() - .map(|generic| { - let generic = self.type_name(generic); - quote! { #generic: ::core::marker::PhantomData::<#generic>, } - }) - .collect() - } - pub fn generic_constraints(&self, generics: &[Type]) -> TokenStream { - let mut tokens = TokenStream::new(); - for generic in generics { - let generic = self.type_name(generic); - tokens.combine("e! { #generic: ::windows_core::RuntimeType + 'static, }); - } - tokens - } - pub fn generic_names(&self, generics: &[Type]) -> TokenStream { - let mut tokens = TokenStream::new(); - for generic in generics { - let generic = self.type_name(generic); - tokens.combine("e! { #generic, }); - } - tokens - } - /// The signature params which are generic (along with their relative index) - pub fn generic_params<'b>( - &'b self, - params: &'b [SignatureParam], - ) -> impl Iterator + 'b { - params - .iter() - .filter(move |param| signature_param_is_convertible(self.reader, param)) - .enumerate() - } - /// The generic param names (i.e., `T` in `fn foo()`) - pub fn constraint_generics(&self, params: &[SignatureParam]) -> TokenStream { - let mut generics = self - .generic_params(params) - .map(|(position, _)| -> TokenStream { format!("P{position}").into() }) - .peekable(); - - if generics.peek().is_some() { - quote!(#(#generics),*) - } else { - TokenStream::new() - } - } - /// A `where` clause for some constrained generic params - pub fn where_clause(&self, params: &[SignatureParam]) -> TokenStream { - let constraints = self.param_constraints(params); - - if !constraints.is_empty() { - quote!(where #constraints) - } else { - quote!() - } - } - fn param_constraints(&self, params: &[SignatureParam]) -> TokenStream { - let mut tokens = TokenStream::new(); - let gen_name = |position| { - let name: TokenStream = format!("P{position}").into(); - name - }; - for (position, param) in self.generic_params(params) { - match param.kind { - SignatureParamKind::TryInto => { - let name: TokenStream = gen_name(position); - let into = self.type_name(¶m.ty); - tokens.combine("e! { #name: ::windows_core::TryIntoParam<#into>, }); - } - SignatureParamKind::IntoParam => { - let name: TokenStream = gen_name(position); - let into = self.type_name(¶m.ty); - tokens.combine("e! { #name: ::windows_core::IntoParam<#into>, }); - } - _ => {} - } - } - tokens - } - - // - // Cfg - // - - /// Generates doc comments for types, free functions, and constants. - pub(crate) fn cfg_doc(&self, cfg: &Cfg) -> TokenStream { - if !self.package { - quote! {} - } else { - let mut tokens = format!(r#"`\"{}\"`"#, to_feature(self.namespace)); - let features = self.cfg_features_imp(cfg, self.namespace); - - for features in features { - write!(tokens, r#", `\"{}\"`"#, to_feature(features)).unwrap(); - } - - if cfg.implement { - tokens.push_str(r#", `\"implement\"`"#) - } - - format!(r#" #[doc = "*Required features: {tokens}*"]"#).into() - } - } - - /// Generates doc comments for member functions (methods) and avoids redundantly declaring the - /// enclosing module feature required by the method's type. - pub(crate) fn cfg_method_doc(&self, cfg: &Cfg) -> TokenStream { - if !self.package { - quote! {} - } else { - let features = self.cfg_features_imp(cfg, self.namespace); - if features.is_empty() { - quote! {} - } else { - let mut tokens = String::new(); - for features in features { - write!(tokens, r#"`\"{}\"`, "#, to_feature(features)).unwrap(); - } - tokens.truncate(tokens.len() - 2); - format!(r#"#[doc = "*Required features: {tokens}*"]"#).into() - } - } - } - - pub(crate) fn cfg_features(&self, cfg: &Cfg) -> TokenStream { - let arches = &cfg.arches; - let arch = match arches.len() { - 0 => quote! {}, - 1 => { - quote! { #[cfg(#(target_arch = #arches),*)] } - } - _ => { - quote! { #[cfg(any(#(target_arch = #arches),*))] } - } - }; - - let features = self.cfg_features_imp(cfg, self.namespace); - - let features = match features.len() { - 0 => quote! {}, - 1 => { - let features = features.iter().cloned().map(to_feature); - quote! { #[cfg(#(feature = #features)*)] } - } - _ => { - let features = features.iter().cloned().map(to_feature); - quote! { #[cfg(all( #(feature = #features),* ))] } - } - }; - - quote! { #arch #features } - } - - fn cfg_features_imp(&self, cfg: &'a Cfg, namespace: &'a str) -> Vec<&'a str> { - let mut compact = Vec::<&'static str>::new(); - if self.package { - for feature in cfg.types.keys() { - if !feature.is_empty() && !starts_with(namespace, feature) { - for pos in 0..compact.len() { - if starts_with(feature, unsafe { compact.get_unchecked(pos) }) { - compact.remove(pos); - break; - } - } - compact.push(feature); - } - } - } - compact - } - - fn cfg_not_features(&self, cfg: &Cfg) -> TokenStream { - let features = self.cfg_features_imp(cfg, self.namespace); - if features.is_empty() { - quote! {} - } else { - match features.len() { - 0 => quote! {}, - 1 => { - let features = features.iter().cloned().map(to_feature); - quote! { #[cfg(not(#(feature = #features)*))] } - } - _ => { - let features = features.iter().cloned().map(to_feature); - quote! { #[cfg(not(all( #(feature = #features),* )))] } - } - } - } - } - - // - // Other helpers - // - - pub(crate) fn namespace(&self, namespace: &str) -> TokenStream { - if self.flatten || namespace == self.namespace { - quote! {} - } else { - let is_external = - namespace.starts_with("Windows.") && !self.namespace.starts_with("Windows"); - let mut relative = self.namespace.split('.').peekable(); - let mut namespace = namespace.split('.').peekable(); - - while relative.peek() == namespace.peek() { - if relative.next().is_none() { - break; - } - - namespace.next(); - } - - let mut tokens = TokenStream::new(); - - if is_external { - tokens.push_str("::windows::"); - namespace.next(); - } else { - for _ in 0..relative.count() { - tokens.push_str("super::"); - } - } - - for namespace in namespace { - tokens.push_str(namespace); - tokens.push_str("::"); - } - - tokens - } - } - pub fn crate_name(&self) -> TokenStream { - if self.sys { - if self.flatten { - TokenStream::new() - } else { - "::windows_sys::core::".into() - } - } else { - "::windows_core::".into() - } - } - fn scoped_name(&self, def: TypeDef) -> String { - if let Some(enclosing_type) = self.reader.type_def_enclosing_type(def) { - for (index, nested_type) in self.reader.nested_types(enclosing_type).enumerate() { - if self.reader.type_def_name(nested_type) == self.reader.type_def_name(def) { - return format!("{}_{index}", &self.scoped_name(enclosing_type)); - } - } - } - self.reader.type_def_name(def).to_string() - } - pub fn value(&self, value: &Value) -> TokenStream { - match value { - Value::Bool(value) => quote! { #value }, - Value::U8(value) => quote! { #value }, - Value::I8(value) => quote! { #value }, - Value::U16(value) => quote! { #value }, - Value::I16(value) => quote! { #value }, - Value::U32(value) => quote! { #value }, - Value::I32(value) => quote! { #value }, - Value::U64(value) => quote! { #value }, - Value::I64(value) => quote! { #value }, - Value::F32(value) => quote! { #value }, - Value::F64(value) => quote! { #value }, - Value::String(value) => { - let mut tokens = "\"".to_string(); - - for u in value.chars() { - write!(tokens, "{}", u.escape_default()).unwrap(); - } - - tokens.push('\"'); - tokens.into() - } - rest => unimplemented!("{rest:?}"), - } - } - pub fn typed_value(&self, value: &Value) -> TokenStream { - let literal = self.value(value); - match value { - Value::Bool(_) => quote! { bool = #literal }, - Value::U8(_) => quote! { u8 = #literal }, - Value::I8(_) => quote! { i8 = #literal }, - Value::U16(_) => quote! { u16 = #literal }, - Value::I16(_) => quote! { i16 = #literal }, - Value::U32(_) => quote! { u32 = #literal }, - Value::I32(_) => quote! { i32 = #literal }, - Value::U64(_) => quote! { u64 = #literal }, - Value::I64(_) => quote! { i64 = #literal }, - Value::F32(_) => quote! { f32 = #literal }, - Value::F64(_) => quote! { f64 = #literal }, - Value::String(_) => { - quote! { &str = #literal } - } - rest => unimplemented!("{rest:?}"), - } - } - - pub fn guid(&self, value: &GUID) -> TokenStream { - let guid = self.type_name(&Type::GUID); - format!("{}::from_u128(0x{:08x?}_{:04x?}_{:04x?}_{:02x?}{:02x?}_{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?})", guid.into_string(), value.0, value.1, value.2, value.3, value.4, value.5, value.6, value.7, value.8, value.9, value.10).into() - } - pub fn interface_core_traits( - &self, - def: TypeDef, - _generics: &[Type], - ident: &TokenStream, - constraints: &TokenStream, - _phantoms: &TokenStream, - features: &TokenStream, - ) -> TokenStream { - let name = crate::trim_tick(self.reader.type_def_name(def)); - quote! { - #features - impl<#constraints> ::core::cmp::PartialEq for #ident { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - #features - impl<#constraints> ::core::cmp::Eq for #ident {} - #features - impl<#constraints> ::core::fmt::Debug for #ident { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple(#name).field(&self.0).finish() - } - } - } - } - pub fn agile( - &self, - def: TypeDef, - ident: &TokenStream, - constraints: &TokenStream, - features: &TokenStream, - ) -> TokenStream { - if self.reader.type_def_is_agile(def) { - quote! { - #features - unsafe impl<#constraints> ::core::marker::Send for #ident {} - #features - unsafe impl<#constraints> ::core::marker::Sync for #ident {} - } - } else { - quote! {} - } - } - pub fn async_get( - &self, - def: TypeDef, - generics: &[Type], - ident: &TokenStream, - constraints: &TokenStream, - _phantoms: &TokenStream, - features: &TokenStream, - ) -> TokenStream { - let mut kind = type_def_async_kind(self.reader, def); - let mut async_generics = generics.to_vec(); - - if kind == AsyncKind::None { - for interface in self.reader.type_def_interfaces(def, generics) { - if let Type::TypeDef(interface_def, interface_generics) = &interface { - kind = type_def_async_kind(self.reader, *interface_def); - if kind != AsyncKind::None { - async_generics = interface_generics.to_vec(); - break; - } - } - } - } - - if kind == AsyncKind::None { - quote! {} - } else { - let return_type = match kind { - AsyncKind::Operation | AsyncKind::OperationWithProgress => { - self.type_name(&async_generics[0]) - } - _ => quote! { () }, - }; - - let handler = match kind { - AsyncKind::Action => quote! { AsyncActionCompletedHandler }, - AsyncKind::ActionWithProgress => quote! { AsyncActionWithProgressCompletedHandler }, - AsyncKind::Operation => quote! { AsyncOperationCompletedHandler }, - AsyncKind::OperationWithProgress => { - quote! { AsyncOperationWithProgressCompletedHandler } - } - rest => unimplemented!("{rest:?}"), - }; - - let namespace = self.namespace("Windows.Foundation"); - - quote! { - #features - impl<#constraints> #ident { - pub fn get(&self) -> ::windows_core::Result<#return_type> { - if self.Status()? == #namespace AsyncStatus::Started { - let (_waiter, signaler) = ::windows_core::imp::Waiter::new()?; - self.SetCompleted(&#namespace #handler::new(move |_sender, _args| { - // Safe because the waiter will only be dropped after being signaled. - unsafe { signaler.signal(); } - Ok(()) - }))?; - } - self.GetResults() - } - } - #features - impl<#constraints> ::std::future::Future for #ident { - type Output = ::windows_core::Result<#return_type>; - - fn poll(self: ::std::pin::Pin<&mut Self>, context: &mut ::std::task::Context) -> ::std::task::Poll { - if self.Status()? == #namespace AsyncStatus::Started { - let waker = context.waker().clone(); - - let _ = self.SetCompleted(&#namespace #handler::new(move |_sender, _args| { - waker.wake_by_ref(); - Ok(()) - })); - - ::std::task::Poll::Pending - } else { - ::std::task::Poll::Ready(self.GetResults()) - } - } - } - } - } - } - pub fn interface_winrt_trait( - &self, - def: TypeDef, - generics: &[Type], - ident: &TokenStream, - constraints: &TokenStream, - _phantoms: &TokenStream, - features: &TokenStream, - ) -> TokenStream { - if self - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - let type_signature = if self.reader.type_def_kind(def) == TypeKind::Class { - let type_signature = - Literal::byte_string(self.reader.type_def_signature(def, generics).as_bytes()); - quote! { ::windows_core::imp::ConstBuffer::from_slice(#type_signature) } - } else { - let signature = Literal::byte_string( - // TODO: workaround for riddle winmd generation (no attribute support) - if let Some(guid) = self.reader.type_def_guid(def) { - format!("{{{:#?}}}", guid) - } else { - "TODO".to_string() - } - .as_bytes(), - ); - - if generics.is_empty() { - quote! { ::windows_core::imp::ConstBuffer::from_slice(#signature) } - } else { - let generics = generics.iter().enumerate().map(|(index, g)| { - let g = self.type_name(g); - let semi = if index != generics.len() - 1 { - Some(quote! { - .push_slice(b";") - }) - } else { - None - }; - - quote! { - .push_other(<#g as ::windows_core::RuntimeType>::SIGNATURE) - #semi - } - }); - - quote! { - { - ::windows_core::imp::ConstBuffer::new() - .push_slice(b"pinterface(") - .push_slice(#signature) - .push_slice(b";") - #(#generics)* - .push_slice(b")") - } - } - } - }; - - quote! { - #features - impl<#constraints> ::windows_core::RuntimeType for #ident { - const SIGNATURE: ::windows_core::imp::ConstBuffer = #type_signature; - } - } - } else { - quote! {} - } - } - pub fn runtime_name_trait( - &self, - def: TypeDef, - _generics: &[Type], - name: &TokenStream, - constraints: &TokenStream, - features: &TokenStream, - ) -> TokenStream { - if self - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - // TODO: this needs to use a ConstBuffer-like facility to accomodate generics - let runtime_name = format!("{}", self.reader.type_def_type_name(def)); - - quote! { - #features - impl<#constraints> ::windows_core::RuntimeName for #name { - const NAME: &'static str = #runtime_name; - } - } - } else { - quote! { - #features - impl ::windows_core::RuntimeName for #name {} - } - } - } - - pub fn interface_trait( - &self, - def: TypeDef, - generics: &[Type], - ident: &TokenStream, - constraints: &TokenStream, - features: &TokenStream, - has_unknown_base: bool, - ) -> TokenStream { - if let Some(default) = self.reader.type_def_default_interface(def) { - let default_name = self.type_name(&default); - let vtbl = self.type_vtbl_name(&default); - quote! { - #features - impl<#constraints> ::core::clone::Clone for #ident { - fn clone(&self) -> Self { - Self(self.0.clone()) - } - } - #features - unsafe impl ::windows_core::Interface for #ident { - type Vtable = #vtbl; - } - #features - unsafe impl ::windows_core::ComInterface for #ident { - const IID: ::windows_core::GUID = <#default_name as ::windows_core::ComInterface>::IID; - } - } - } else { - let vtbl = self.type_def_vtbl_name(def, generics); - let guid = if generics.is_empty() { - match self.reader.type_def_guid(def) { - Some(guid) => self.guid(&guid), - None => { - quote! { - ::windows_core::GUID::zeroed() - } - } - } - } else { - quote! { - ::windows_core::GUID::from_signature(::SIGNATURE) - } - }; - - let phantoms = self.generic_phantoms(generics); - - let mut tokens = quote! { - #features - unsafe impl<#constraints> ::windows_core::Interface for #ident { - type Vtable = #vtbl; - } - #features - impl<#constraints> ::core::clone::Clone for #ident { - fn clone(&self) -> Self { - Self(self.0.clone(), #phantoms) - } - } - }; - - if has_unknown_base { - tokens.combine("e! { - #features - unsafe impl<#constraints> ::windows_core::ComInterface for #ident { - const IID: ::windows_core::GUID = #guid; - } - }); - } - - tokens - } - } - pub fn interface_vtbl( - &self, - def: TypeDef, - generics: &[Type], - _ident: &TokenStream, - constraints: &TokenStream, - features: &TokenStream, - ) -> TokenStream { - let vtbl = self.type_def_vtbl_name(def, generics); - let mut methods = quote! {}; - let mut method_names = MethodNames::new(); - method_names.add_vtable_types(self, def); - let phantoms = self.generic_named_phantoms(generics); - - match self.reader.type_def_vtables(def).last() { - Some(Type::IUnknown) => { - methods.combine("e! { pub base__: ::windows_core::IUnknown_Vtbl, }) - } - Some(Type::IInspectable) => { - methods.combine("e! { pub base__: ::windows_core::IInspectable_Vtbl, }) - } - Some(Type::TypeDef(def, _)) => { - let vtbl = self.type_def_vtbl_name(*def, &[]); - methods.combine("e! { pub base__: #vtbl, }); - } - _ => {} - } - - for method in self.reader.type_def_methods(def) { - if self.reader.method_def_name(method) == ".ctor" { - continue; - } - let name = method_names.add(self, method); - let signature = method_def_signature( - self.reader, - self.reader.type_def_namespace(def), - method, - generics, - ); - let mut cfg = signature_cfg(self.reader, method); - let signature = self.vtbl_signature(def, generics, &signature); - cfg.add_feature(self.reader.type_def_namespace(def)); - let cfg_all = self.cfg_features(&cfg); - let cfg_not = self.cfg_not_features(&cfg); - - let signature = quote! { pub #name: unsafe extern "system" fn #signature, }; - - if cfg_all.is_empty() { - methods.combine(&signature); - } else { - methods.combine("e! { - #cfg_all - #signature - #cfg_not - #name: usize, - }); - } - } - - quote! { - #features - #[repr(C)] #[doc(hidden)] pub struct #vtbl where #constraints { - #methods - #(pub #phantoms)* - } - } - } - pub fn vtbl_signature( - &self, - def: TypeDef, - _generics: &[Type], - signature: &Signature, - ) -> TokenStream { - let is_winrt = self - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime); - - let crate_name = self.crate_name(); - - let (trailing_return_type, return_type, udt_return_type) = match &signature.return_type { - Type::Void if is_winrt => (quote! {}, quote! { -> #crate_name HRESULT }, quote! {}), - Type::Void => (quote! {}, quote! {}, quote! {}), - Type::WinrtArray(kind) => { - let tokens = self.type_abi_name(kind); - ( - quote! { result_size__: *mut u32, result__: *mut *mut #tokens }, - quote! { -> #crate_name HRESULT }, - quote! {}, - ) - } - _ if is_winrt => { - let tokens = self.type_abi_name(&signature.return_type); - ( - quote! { result__: *mut #tokens }, - quote! { -> #crate_name HRESULT }, - quote! {}, - ) - } - _ if self.reader.type_is_struct(&signature.return_type) => { - let tokens = self.type_abi_name(&signature.return_type); - (quote! {}, quote! {}, quote! { result__: *mut #tokens, }) - } - _ => { - let tokens = self.type_default_name(&signature.return_type); - (quote! {}, quote! { -> #tokens }, quote! {}) - } - }; - - let params = signature.params.iter().map(|p| { - let name = self.param_name(p.def); - if is_winrt { - let abi = self.type_abi_name(&p.ty); - let abi_size_name: TokenStream = - format!("{}_array_size", self.reader.param_name(p.def)).into(); - - if self.reader.param_flags(p.def).contains(ParamAttributes::In) { - if p.ty.is_winrt_array() { - quote! { #abi_size_name: u32, #name: *const #abi, } - } else if p.ty.is_const_ref() { - quote! { #name: &#abi, } - } else { - quote! { #name: #abi, } - } - } else if p.ty.is_winrt_array() { - quote! { #abi_size_name: u32, #name: *mut #abi, } - } else if p.ty.is_winrt_array_ref() { - quote! { #abi_size_name: *mut u32, #name: *mut *mut #abi, } - } else { - quote! { #name: *mut #abi, } - } - } else { - match p.kind { - SignatureParamKind::ValueType => { - let abi = self.type_default_name(&p.ty); - quote! { #name: #abi, } - } - _ => { - let abi = self.type_abi_name(&p.ty); - quote! { #name: #abi, } - } - } - } - }); - - quote! { (this: *mut ::core::ffi::c_void, #udt_return_type #(#params)* #trailing_return_type) #return_type } - } - pub fn param_name(&self, param: Param) -> TokenStream { - // In Rust, function parameters cannot be named the same as structs. This avoids some collisions that occur in the win32 metadata. - // See Icmp6SendEcho2 for an example. - to_ident(&self.reader.param_name(param).to_lowercase()) - } - pub fn return_sig(&self, signature: &Signature) -> TokenStream { - match &signature.return_type { - Type::Void - if self - .reader - .has_attribute(signature.def, "DoesNotReturnAttribute") => - { - " -> !".into() - } - Type::Void => " -> ()".into(), - _ => { - let tokens = self.type_default_name(&signature.return_type); - format!(" -> {}", tokens.as_str()).into() - } - } - } - pub fn win32_args(&self, params: &[SignatureParam], kind: SignatureKind) -> TokenStream { - let mut tokens = quote! {}; - - for (position, param) in params.iter().enumerate() { - let new = match kind { - SignatureKind::Query(query) if query.object == position => { - quote! { &mut result__, } - } - SignatureKind::ReturnValue | SignatureKind::ResultValue - if params.len() - 1 == position => - { - quote! { &mut result__, } - } - SignatureKind::QueryOptional(query) if query.object == position => { - quote! { result__ as *mut _ as *mut _, } - } - SignatureKind::Query(query) | SignatureKind::QueryOptional(query) - if query.guid == position => - { - quote! { &::IID, } - } - _ => { - let name = self.param_name(param.def); - let flags = self.reader.param_flags(param.def); - match param.kind { - SignatureParamKind::ArrayFixed(_) - | SignatureParamKind::ArrayRelativeLen(_) - | SignatureParamKind::ArrayRelativeByteLen(_) => { - let map = if flags.contains(ParamAttributes::Optional) { - quote! { #name.as_deref().map_or(::core::ptr::null(), |slice|slice.as_ptr()) } - } else { - quote! { #name.as_ptr() } - }; - quote! { ::core::mem::transmute(#map), } - } - SignatureParamKind::ArrayRelativePtr(relative) => { - let name = self.param_name(params[relative].def); - let flags = self.reader.param_flags(params[relative].def); - if flags.contains(ParamAttributes::Optional) { - quote! { #name.as_deref().map_or(0, |slice|slice.len() as _), } - } else { - quote! { #name.len() as _, } - } - } - SignatureParamKind::TryInto => { - quote! { #name.try_into_param()?.abi(), } - } - SignatureParamKind::IntoParam => { - quote! { #name.into_param().abi(), } - } - SignatureParamKind::OptionalPointer => { - if flags.contains(ParamAttributes::Out) { - quote! { ::core::mem::transmute(#name.unwrap_or(::std::ptr::null_mut())), } - } else { - quote! { ::core::mem::transmute(#name.unwrap_or(::std::ptr::null())), } - } - } - SignatureParamKind::ValueType => { - quote! { #name, } - } - SignatureParamKind::Blittable => { - if matches!(param.ty, Type::PrimitiveOrEnum(_, _)) { - quote! { #name.0 as _, } - } else { - quote! { ::core::mem::transmute(#name), } - } - } - SignatureParamKind::Other => { - quote! { ::core::mem::transmute_copy(#name), } - } - } - } - }; - tokens.combine(&new) - } - - tokens - } - pub fn win32_params(&self, params: &[SignatureParam], kind: SignatureKind) -> TokenStream { - let mut tokens = quote! {}; - - let mut generic_params = self.generic_params(params); - for (position, param) in params.iter().enumerate() { - match kind { - SignatureKind::Query(query) | SignatureKind::QueryOptional(query) => { - if query.object == position || query.guid == position { - continue; - } - } - SignatureKind::ReturnValue | SignatureKind::ResultValue - if params.len() - 1 == position => - { - continue; - } - _ => {} - } - - let name = self.param_name(param.def); - - match param.kind { - SignatureParamKind::ArrayFixed(fixed) => { - let ty = param.ty.deref(); - let ty = self.type_default_name(&ty); - let len = Literal::u32_unsuffixed(fixed as u32); - let ty = if self - .reader - .param_flags(param.def) - .contains(ParamAttributes::Out) - { - quote! { &mut [#ty; #len] } - } else { - quote! { &[#ty; #len] } - }; - if self - .reader - .param_flags(param.def) - .contains(ParamAttributes::Optional) - { - tokens.combine("e! { #name: ::core::option::Option<#ty>, }); - } else { - tokens.combine("e! { #name: #ty, }); - } - } - SignatureParamKind::ArrayRelativeLen(_) => { - let ty = param.ty.deref(); - let ty = self.type_default_name(&ty); - let ty = if self - .reader - .param_flags(param.def) - .contains(ParamAttributes::Out) - { - quote! { &mut [#ty] } - } else { - quote! { &[#ty] } - }; - if self - .reader - .param_flags(param.def) - .contains(ParamAttributes::Optional) - { - tokens.combine("e! { #name: ::core::option::Option<#ty>, }); - } else { - tokens.combine("e! { #name: #ty, }); - } - } - SignatureParamKind::ArrayRelativeByteLen(_) => { - let ty = if self - .reader - .param_flags(param.def) - .contains(ParamAttributes::Out) - { - quote! { &mut [u8] } - } else { - quote! { &[u8] } - }; - if self - .reader - .param_flags(param.def) - .contains(ParamAttributes::Optional) - { - tokens.combine("e! { #name: ::core::option::Option<#ty>, }); - } else { - tokens.combine("e! { #name: #ty, }); - } - } - SignatureParamKind::ArrayRelativePtr(_) => {} - SignatureParamKind::TryInto | SignatureParamKind::IntoParam => { - let (position, _) = generic_params.next().unwrap(); - let kind: TokenStream = format!("P{position}").into(); - tokens.combine("e! { #name: #kind, }); - } - SignatureParamKind::OptionalPointer => { - let kind = self.type_default_name(¶m.ty); - tokens.combine("e! { #name: ::core::option::Option<#kind>, }); - } - SignatureParamKind::ValueType | SignatureParamKind::Blittable => { - let kind = self.type_default_name(¶m.ty); - tokens.combine("e! { #name: #kind, }); - } - SignatureParamKind::Other => { - let kind = self.type_default_name(¶m.ty); - tokens.combine("e! { #name: &#kind, }); - } - } - } - - tokens - } - - pub fn impl_signature(&self, def: TypeDef, signature: &Signature) -> TokenStream { - if self - .reader - .type_def_flags(def) - .contains(TypeAttributes::WindowsRuntime) - { - let is_delegate = self.reader.type_def_kind(def) == TypeKind::Delegate; - let params = signature - .params - .iter() - .map(|p| self.winrt_produce_type(p, !is_delegate)); - - let return_type = match &signature.return_type { - Type::Void => quote! { () }, - _ => { - let tokens = self.type_name(&signature.return_type); - - if signature.return_type.is_winrt_array() { - quote! { ::windows_core::Array<#tokens> } - } else { - tokens - } - } - }; - - let this = if is_delegate { - quote! {} - } else { - quote! { &self, } - }; - - quote! { (#this #(#params),*) -> ::windows_core::Result<#return_type> } - } else { - let signature_kind = signature_kind(self.reader, signature); - let mut params = quote! {}; - - if signature_kind == SignatureKind::ResultValue { - for param in &signature.params[..signature.params.len() - 1] { - params.combine(&self.win32_produce_type(param)); - } - } else { - for param in &signature.params { - params.combine(&self.win32_produce_type(param)); - } - } - - let return_type = match signature_kind { - SignatureKind::ReturnVoid => quote! {}, - SignatureKind::Query(_) - | SignatureKind::QueryOptional(_) - | SignatureKind::ResultVoid => quote! { -> ::windows_core::Result<()> }, - SignatureKind::ResultValue => { - let return_type = signature.params[signature.params.len() - 1].ty.deref(); - let return_type = self.type_name(&return_type); - - quote! { -> ::windows_core::Result<#return_type> } - } - _ => self.return_sig(signature), - }; - - quote! { (&self, #params) #return_type } - } - } - fn winrt_produce_type(&self, param: &SignatureParam, include_param_names: bool) -> TokenStream { - let default_type = self.type_default_name(¶m.ty); - - let sig = if self - .reader - .param_flags(param.def) - .contains(ParamAttributes::In) - { - if param.ty.is_winrt_array() { - quote! { &[#default_type] } - } else if self.reader.type_is_primitive(¶m.ty) { - quote! { #default_type } - } else if self.reader.type_is_nullable(¶m.ty) { - let type_name = self.type_name(¶m.ty); - quote! { ::core::option::Option<&#type_name> } - } else { - quote! { &#default_type } - } - } else if param.ty.is_winrt_array() { - quote! { &mut [#default_type] } - } else if param.ty.is_winrt_array_ref() { - let kind = self.type_name(¶m.ty); - quote! { &mut ::windows_core::Array<#kind> } - } else { - quote! { &mut #default_type } - }; - - if include_param_names { - let name = self.param_name(param.def); - quote! { #name: #sig } - } else { - sig - } - } - fn win32_produce_type(&self, param: &SignatureParam) -> TokenStream { - let name = self.param_name(param.def); - let kind = self.type_default_name(¶m.ty); - - if self - .reader - .param_flags(param.def) - .contains(ParamAttributes::In) - { - if self.reader.type_is_primitive(¶m.ty) { - quote! { #name: #kind, } - } else if self.reader.type_is_nullable(¶m.ty) { - let kind = self.type_name(¶m.ty); - quote! { #name: ::core::option::Option<&#kind>, } - } else { - quote! { #name: &#kind, } - } - } else { - quote! { #name: #kind, } - } - } -} - -fn mut_ptrs(pointers: usize) -> TokenStream { - "*mut ".repeat(pointers).into() -} - -fn const_ptrs(pointers: usize) -> TokenStream { - "*const ".repeat(pointers).into() -} - -fn to_feature(name: &str) -> String { - let mut feature = String::new(); - - for name in name.split('.').skip(1) { - feature.push_str(name); - feature.push('_'); - } - - if feature.is_empty() { - feature = name.to_string(); - } else { - feature.truncate(feature.len() - 1); - } - - feature -} - -fn starts_with(namespace: &str, feature: &str) -> bool { - if namespace == feature { - return true; - } - - if namespace.len() > feature.len() && namespace.as_bytes().get(feature.len()) == Some(&b'.') { - return namespace.starts_with(feature); - } - - false -} - -fn gen_mut_ptrs(pointers: usize) -> TokenStream { - "*mut ".repeat(pointers).into() -} - -fn gen_const_ptrs(pointers: usize) -> TokenStream { - "*const ".repeat(pointers).into() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_starts_with() { - assert!(starts_with( - "Windows.Win32.Graphics.Direct3D11on12", - "Windows.Win32.Graphics.Direct3D11on12" - )); - assert!(starts_with( - "Windows.Win32.Graphics.Direct3D11on12", - "Windows.Win32.Graphics" - )); - assert!(!starts_with( - "Windows.Win32.Graphics.Direct3D11on12", - "Windows.Win32.Graphics.Direct3D11" - )); - assert!(!starts_with( - "Windows.Win32.Graphics.Direct3D", - "Windows.Win32.Graphics.Direct3D11" - )); - } -} diff --git a/crates/tools/riddle/src/tokens/mod.rs b/crates/tools/riddle/src/tokens/mod.rs deleted file mode 100644 index ea10b7bbb7..0000000000 --- a/crates/tools/riddle/src/tokens/mod.rs +++ /dev/null @@ -1,446 +0,0 @@ -#![allow(dead_code)] - -mod to_tokens; -mod token_stream; - -pub mod runtime; -pub use to_tokens::*; -pub use token_stream::*; - -/// The whole point. -/// -/// Performs variable interpolation against the input and produces it as -/// [`TokenStream`]. -/// -/// # Interpolation -/// -/// Variable interpolation is done with `#var` (similar to `$var` in -/// `macro_rules!` macros). This grabs the `var` variable that is currently in -/// scope and inserts it in that location in the output tokens. Any type -/// implementing the [`ToTokens`] trait can be interpolated. This includes most -/// Rust primitive types. -/// -/// [`ToTokens`]: trait.ToTokens.html -/// -/// Repetition is done using `#(...)*` or `#(...),*` again similar to -/// `macro_rules!`. This iterates through the elements of any variable -/// interpolated within the repetition and inserts a copy of the repetition body -/// for each one. The variables in an interpolation may be a `Vec`, slice, -/// `BTreeSet`, or any `Iterator`. -/// -/// - `#(#var)*` — no separators -/// - `#(#var),*` — the character before the asterisk is used as a separator -/// - `#( struct #var; )*` — the repetition can contain other tokens -/// - `#( #k => println!("{}", #v), )*` — even multiple interpolations -#[macro_export] -macro_rules! quote { - () => { - $crate::tokens::TokenStream::new() - }; - ($($tt:tt)*) => {{ - let mut _s = $crate::tokens::TokenStream::new(); - $crate::quote_each_token!(_s $($tt)*); - _s - }}; -} - -pub use quote; - -/// Formatting macro for constructing a `TokenStream`. -/// -///
-/// -/// # Syntax -/// -/// Syntax is copied from the [`format!`] macro, supporting both positional and -/// named arguments. -#[macro_export] -macro_rules! format_token { - ($($fmt:tt)*) => { - $crate::TokenStream::from(format!($($fmt)*)) - }; -} - -// Extract the names of all #metavariables and pass them to the $call macro. -// -// in: pounded_var_names!(then!(...) a #b c #( #d )* #e) -// out: then!(... b); -// then!(... d); -// then!(... e); -#[macro_export] -#[doc(hidden)] -macro_rules! pounded_var_names { - ($call:ident! $extra:tt $($tts:tt)*) => { - $crate::pounded_var_names_with_context!($call! $extra - (@ $($tts)*) - ($($tts)* @) - ) - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! pounded_var_names_with_context { - ($call:ident! $extra:tt ($($b1:tt)*) ($($curr:tt)*)) => { - $( - $crate::pounded_var_with_context!($call! $extra $b1 $curr); - )* - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! pounded_var_with_context { - ($call:ident! $extra:tt $b1:tt ( $($inner:tt)* )) => { - $crate::pounded_var_names!($call! $extra $($inner)*); - }; - - ($call:ident! $extra:tt $b1:tt [ $($inner:tt)* ]) => { - $crate::pounded_var_names!($call! $extra $($inner)*); - }; - - ($call:ident! $extra:tt $b1:tt { $($inner:tt)* }) => { - $crate::pounded_var_names!($call! $extra $($inner)*); - }; - - ($call:ident!($($extra:tt)*) # $var:ident) => { - $crate::$call!($($extra)* $var); - }; - - ($call:ident! $extra:tt $b1:tt $curr:tt) => {}; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! quote_bind_into_iter { - ($has_iter:ident $var:ident) => { - // `mut` may be unused if $var occurs multiple times in the list. - #[allow(unused_mut)] - let (mut $var, i) = $var.quote_into_iter(); - let $has_iter = $has_iter | i; - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! quote_bind_next_or_break { - ($var:ident) => { - let $var = match $var.next() { - Some(_x) => $crate::tokens::runtime::RepInterp(_x), - None => break, - }; - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! quote_each_token { - ($tokens:ident $($tts:tt)*) => { - $crate::quote_tokens_with_context!($tokens - (@ @ @ @ @ @ $($tts)*) - (@ @ @ @ @ $($tts)* @) - (@ @ @ @ $($tts)* @ @) - (@ @ @ $(($tts))* @ @ @) - (@ @ $($tts)* @ @ @ @) - (@ $($tts)* @ @ @ @ @) - ($($tts)* @ @ @ @ @ @) - ); - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! quote_tokens_with_context { - ($tokens:ident - ($($b3:tt)*) ($($b2:tt)*) ($($b1:tt)*) - ($($curr:tt)*) - ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*) - ) => { - $( - $crate::quote_token_with_context!($tokens $b3 $b2 $b1 $curr $a1 $a2 $a3); - )* - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! quote_token_with_context { - ($tokens:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {}; - - ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{ - use $crate::tokens::runtime::ext::*; - let has_iter = $crate::tokens::runtime::ThereIsNoIteratorInRepetition; - $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*); - let _: $crate::tokens::runtime::HasIterator = has_iter; - // This is `while true` instead of `loop` because if there are no - // iterators used inside of this repetition then the body would not - // contain any `break`, so the compiler would emit unreachable code - // warnings on anything below the loop. We use has_iter to detect and - // fail to compile when there are no iterators, so here we just work - // around the unneeded extra warning. - while true { - $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*); - $crate::quote_each_token!($tokens $($inner)*); - } - }}; - ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {}; - ($tokens:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {}; - - ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{ - use $crate::tokens::runtime::ext::*; - let mut _i = 0usize; - let has_iter = $crate::tokens::runtime::ThereIsNoIteratorInRepetition; - $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*); - let _: $crate::tokens::runtime::HasIterator = has_iter; - while true { - $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*); - if _i > 0 { - $crate::quote_token!($tokens $sep); - } - _i += 1; - $crate::quote_each_token!($tokens $($inner)*); - } - }}; - ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {}; - ($tokens:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {}; - ($tokens:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => { - // https://github.com/dtolnay/quote/issues/130 - $crate::quote_token!($tokens *); - }; - ($tokens:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {}; - - ($tokens:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => { - $crate::tokens::ToTokens::to_tokens(&$var, &mut $tokens); - }; - ($tokens:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {}; - ($tokens:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => { - $crate::quote_token!($tokens $curr); - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! quote_token { - ($tokens:ident ( $($inner:tt)* )) => { - $crate::tokens::runtime::push_group( - &mut $tokens, - $crate::tokens::Delimiter::Parenthesis, - $crate::quote!($($inner)*), - ); - }; - - ($tokens:ident [ $($inner:tt)* ]) => { - $crate::tokens::runtime::push_group( - &mut $tokens, - $crate::tokens::Delimiter::Bracket, - $crate::quote!($($inner)*), - ); - }; - - ($tokens:ident { $($inner:tt)* }) => { - $crate::tokens::runtime::push_group( - &mut $tokens, - $crate::tokens::Delimiter::Brace, - $crate::quote!($($inner)*), - ); - }; - - ($tokens:ident +) => { - $crate::tokens::runtime::push_add(&mut $tokens); - }; - - ($tokens:ident +=) => { - $crate::tokens::runtime::push_add_eq(&mut $tokens); - }; - - ($tokens:ident &) => { - $crate::tokens::runtime::push_and(&mut $tokens); - }; - - ($tokens:ident &&) => { - $crate::tokens::runtime::push_and_and(&mut $tokens); - }; - - ($tokens:ident &=) => { - $crate::tokens::runtime::push_and_eq(&mut $tokens); - }; - - ($tokens:ident @) => { - $crate::tokens::runtime::push_at(&mut $tokens); - }; - - ($tokens:ident !) => { - $crate::tokens::runtime::push_bang(&mut $tokens); - }; - - ($tokens:ident ^) => { - $crate::tokens::runtime::push_caret(&mut $tokens); - }; - - ($tokens:ident ^=) => { - $crate::tokens::runtime::push_caret_eq(&mut $tokens); - }; - - ($tokens:ident :) => { - $crate::tokens::runtime::push_colon(&mut $tokens); - }; - - ($tokens:ident ::) => { - $crate::tokens::runtime::push_colon2(&mut $tokens); - }; - - ($tokens:ident ,) => { - $crate::tokens::runtime::push_comma(&mut $tokens); - }; - - ($tokens:ident /) => { - $crate::tokens::runtime::push_div(&mut $tokens); - }; - - ($tokens:ident /=) => { - $crate::tokens::runtime::push_div_eq(&mut $tokens); - }; - - ($tokens:ident .) => { - $crate::tokens::runtime::push_dot(&mut $tokens); - }; - - ($tokens:ident ..) => { - $crate::tokens::runtime::push_dot2(&mut $tokens); - }; - - ($tokens:ident ...) => { - $crate::tokens::runtime::push_dot3(&mut $tokens); - }; - - ($tokens:ident ..=) => { - $crate::tokens::runtime::push_dot_dot_eq(&mut $tokens); - }; - - ($tokens:ident =) => { - $crate::tokens::runtime::push_eq(&mut $tokens); - }; - - ($tokens:ident ==) => { - $crate::tokens::runtime::push_eq_eq(&mut $tokens); - }; - - ($tokens:ident >=) => { - $crate::tokens::runtime::push_ge(&mut $tokens); - }; - - ($tokens:ident >) => { - $crate::tokens::runtime::push_gt(&mut $tokens); - }; - - ($tokens:ident <=) => { - $crate::tokens::runtime::push_le(&mut $tokens); - }; - - ($tokens:ident <) => { - $crate::tokens::runtime::push_lt(&mut $tokens); - }; - - ($tokens:ident *=) => { - $crate::tokens::runtime::push_mul_eq(&mut $tokens); - }; - - ($tokens:ident !=) => { - $crate::tokens::runtime::push_ne(&mut $tokens); - }; - - ($tokens:ident |) => { - $crate::tokens::runtime::push_or(&mut $tokens); - }; - - ($tokens:ident |=) => { - $crate::tokens::runtime::push_or_eq(&mut $tokens); - }; - - ($tokens:ident ||) => { - $crate::tokens::runtime::push_or_or(&mut $tokens); - }; - - ($tokens:ident #) => { - $crate::tokens::runtime::push_pound(&mut $tokens); - }; - - ($tokens:ident ?) => { - $crate::tokens::runtime::push_question(&mut $tokens); - }; - - ($tokens:ident ->) => { - $crate::tokens::runtime::push_rarrow(&mut $tokens); - }; - - ($tokens:ident <-) => { - $crate::tokens::runtime::push_larrow(&mut $tokens); - }; - - ($tokens:ident %) => { - $crate::tokens::runtime::push_rem(&mut $tokens); - }; - - ($tokens:ident %=) => { - $crate::tokens::runtime::push_rem_eq(&mut $tokens); - }; - - ($tokens:ident =>) => { - $crate::tokens::runtime::push_fat_arrow(&mut $tokens); - }; - - ($tokens:ident ;) => { - $crate::tokens::runtime::push_semi(&mut $tokens); - }; - - ($tokens:ident <<) => { - $crate::tokens::runtime::push_shl(&mut $tokens); - }; - - ($tokens:ident <<=) => { - $crate::tokens::runtime::push_shl_eq(&mut $tokens); - }; - - ($tokens:ident >>) => { - $crate::tokens::runtime::push_shr(&mut $tokens); - }; - - ($tokens:ident >>=) => { - $crate::tokens::runtime::push_shr_eq(&mut $tokens); - }; - - ($tokens:ident *) => { - $crate::tokens::runtime::push_star(&mut $tokens); - }; - - ($tokens:ident -) => { - $crate::tokens::runtime::push_sub(&mut $tokens); - }; - - ($tokens:ident -=) => { - $crate::tokens::runtime::push_sub_eq(&mut $tokens); - }; - - ($tokens:ident $ident:ident) => { - $crate::tokens::runtime::push_ident(&mut $tokens, stringify!($ident)); - }; - - ($tokens:ident $other:tt) => { - $crate::tokens::runtime::parse(&mut $tokens, stringify!($other)); - }; -} - -pub fn to_ident(name: &str) -> TokenStream { - // keywords list based on https://doc.rust-lang.org/reference/keywords.html - match name { - "abstract" | "as" | "become" | "box" | "break" | "const" | "continue" | "crate" | "do" - | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in" - | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "override" | "priv" - | "pub" | "ref" | "return" | "static" | "struct" | "super" | "trait" | "true" | "type" - | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield" - | "try" | "async" | "await" | "dyn" => format!("r#{name}").into(), - "Self" | "self" => format!("{name}_").into(), - "_" => "unused".into(), - _ => crate::trim_tick(name).into(), - } -} diff --git a/crates/tools/riddle/src/tokens/runtime.rs b/crates/tools/riddle/src/tokens/runtime.rs deleted file mode 100644 index 83bc42a040..0000000000 --- a/crates/tools/riddle/src/tokens/runtime.rs +++ /dev/null @@ -1,274 +0,0 @@ -use super::{Delimiter, ToTokens, TokenStream}; -use core::ops::BitOr; - -pub struct HasIterator; // True -pub struct ThereIsNoIteratorInRepetition; // False - -impl BitOr for ThereIsNoIteratorInRepetition { - type Output = ThereIsNoIteratorInRepetition; - fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition { - ThereIsNoIteratorInRepetition - } -} - -impl BitOr for HasIterator { - type Output = HasIterator; - fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator { - HasIterator - } -} - -impl BitOr for ThereIsNoIteratorInRepetition { - type Output = HasIterator; - fn bitor(self, _rhs: HasIterator) -> HasIterator { - HasIterator - } -} - -impl BitOr for HasIterator { - type Output = HasIterator; - fn bitor(self, _rhs: HasIterator) -> HasIterator { - HasIterator - } -} - -/// Extension traits used by the implementation of `quote!`. These are defined -/// in separate traits, rather than as a single trait due to ambiguity issues. -/// -/// These traits expose a `quote_into_iter` method which should allow calling -/// whichever impl happens to be applicable. Calling that method repeatedly on -/// the returned value should be idempotent. -pub mod ext { - use super::RepInterp; - use super::ToTokens; - use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter}; - use core::slice; - use std::collections::btree_set::{self, BTreeSet}; - - /// Extension trait providing the `quote_into_iter` method on iterators. - pub trait RepIteratorExt: Iterator + Sized { - fn quote_into_iter(self) -> (Self, HasIter) { - (self, HasIter) - } - } - - impl RepIteratorExt for T {} - - /// Extension trait providing the `quote_into_iter` method for - /// non-iterable types. These types interpolate the same value in each - /// iteration of the repetition. - pub trait RepToTokensExt { - /// Pretend to be an iterator for the purposes of `quote_into_iter`. - /// This allows repeated calls to `quote_into_iter` to continue - /// correctly returning DoesNotHaveIter. - fn next(&self) -> Option<&Self> { - Some(self) - } - - fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) { - (self, DoesNotHaveIter) - } - } - - impl RepToTokensExt for T {} - - /// Extension trait providing the `quote_into_iter` method for types that - /// can be referenced as an iterator. - pub trait RepAsIteratorExt<'q> { - type Iter: Iterator; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter); - } - - impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a T { - type Iter = T::Iter; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { - ::quote_into_iter(*self) - } - } - - impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a mut T { - type Iter = T::Iter; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { - ::quote_into_iter(*self) - } - } - - impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] { - type Iter = slice::Iter<'q, T>; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { - (self.iter(), HasIter) - } - } - - impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec { - type Iter = slice::Iter<'q, T>; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { - (self.iter(), HasIter) - } - } - - impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet { - type Iter = btree_set::Iter<'q, T>; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { - (self.iter(), HasIter) - } - } - - macro_rules! array_rep_slice { - ($($l:tt)*) => { - $( - impl<'q, T: 'q> RepAsIteratorExt<'q> for [T; $l] { - type Iter = slice::Iter<'q, T>; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { - (self.iter(), HasIter) - } - } - )* - } - } - - array_rep_slice!( - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 - ); - - impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp { - type Iter = T::Iter; - - fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { - self.0.quote_into_iter() - } - } -} - -// Helper type used within interpolations to allow for repeated binding names. -// Implements the relevant traits, and exports a dummy `next()` method. -#[derive(Copy, Clone)] -pub struct RepInterp(pub T); - -impl RepInterp { - // This method is intended to look like `Iterator::next`, and is called when - // a name is bound multiple times, as the previous binding will shadow the - // original `Iterator` object. This allows us to avoid advancing the - // iterator multiple times per iteration. - pub fn next(self) -> Option { - Some(self.0) - } -} - -impl Iterator for RepInterp { - type Item = T::Item; - - fn next(&mut self) -> Option { - self.0.next() - } -} - -impl ToTokens for RepInterp { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.0.to_tokens(tokens); - } -} - -pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) { - tokens.push_space(); - tokens.push(delimiter.open()); - tokens.combine(&inner); - tokens.push_space(); - tokens.push(delimiter.close()); -} - -pub fn parse(tokens: &mut TokenStream, s: &str) { - tokens.push_space(); - tokens.push_str(s); -} - -pub fn push_ident(tokens: &mut TokenStream, s: &str) { - match tokens.0.chars().last() { - None | Some(':') => {} - _ => tokens.0.push(' '), - } - tokens.push_str(s); -} - -pub fn push_colon2(tokens: &mut TokenStream) { - match tokens.0.chars().last() { - Some(':') => tokens.push_str(" ::"), - _ => tokens.push_str("::"), - } -} - -macro_rules! push_punct { - ($name:ident $char1:tt) => { - pub fn $name(tokens: &mut TokenStream) { - tokens.push_space(); - tokens.push($char1); - } - }; - ($name:ident $char1:tt $char2:tt) => { - pub fn $name(tokens: &mut TokenStream) { - tokens.push_space(); - tokens.push($char1); - tokens.push($char2); - } - }; - ($name:ident $char1:tt $char2:tt $char3:tt) => { - pub fn $name(tokens: &mut TokenStream) { - tokens.push(' '); - tokens.push($char1); - tokens.push($char2); - tokens.push($char3); - } - }; -} - -push_punct!(push_add '+'); -push_punct!(push_add_eq '+' '='); -push_punct!(push_and '&'); -push_punct!(push_and_and '&' '&'); -push_punct!(push_and_eq '&' '='); -push_punct!(push_at '@'); -push_punct!(push_bang '!'); -push_punct!(push_caret '^'); -push_punct!(push_caret_eq '^' '='); -push_punct!(push_colon ':'); -push_punct!(push_comma ','); -push_punct!(push_div '/'); -push_punct!(push_div_eq '/' '='); -push_punct!(push_dot '.'); -push_punct!(push_dot2 '.' '.'); -push_punct!(push_dot3 '.' '.' '.'); -push_punct!(push_dot_dot_eq '.' '.' '='); -push_punct!(push_eq '='); -push_punct!(push_eq_eq '=' '='); -push_punct!(push_ge '>' '='); -push_punct!(push_gt '>'); -push_punct!(push_le '<' '='); -push_punct!(push_lt '<'); -push_punct!(push_mul_eq '*' '='); -push_punct!(push_ne '!' '='); -push_punct!(push_or '|'); -push_punct!(push_or_eq '|' '='); -push_punct!(push_or_or '|' '|'); -push_punct!(push_pound '#'); -push_punct!(push_question '?'); -push_punct!(push_rarrow '-' '>'); -push_punct!(push_larrow '<' '-'); -push_punct!(push_rem '%'); -push_punct!(push_rem_eq '%' '='); -push_punct!(push_fat_arrow '=' '>'); -push_punct!(push_semi ';'); -push_punct!(push_shl '<' '<'); -push_punct!(push_shl_eq '<' '<' '='); -push_punct!(push_shr '>' '>'); -push_punct!(push_shr_eq '>' '>' '='); -push_punct!(push_star '*'); -push_punct!(push_sub '-'); -push_punct!(push_sub_eq '-' '='); diff --git a/crates/tools/riddle/src/tokens/to_tokens.rs b/crates/tools/riddle/src/tokens/to_tokens.rs deleted file mode 100644 index cb614f33d7..0000000000 --- a/crates/tools/riddle/src/tokens/to_tokens.rs +++ /dev/null @@ -1,149 +0,0 @@ -use std::borrow::Cow; -use std::rc::Rc; - -use super::{Literal, TokenStream}; - -/// Types that can be interpolated inside a `quote!` invocation. -/// -/// [`quote!`]: macro.quote.html -pub trait ToTokens { - /// Write `self` to the given `TokenStream`. - fn to_tokens(&self, tokens: &mut TokenStream); - - /// Convert `self` directly into a `TokenStream` object. - /// - /// This method is implicitly implemented using `to_tokens`, and acts as a - /// convenience method for consumers of the `ToTokens` trait. - fn to_token_stream(&self) -> TokenStream { - let mut tokens = TokenStream::new(); - self.to_tokens(&mut tokens); - tokens - } - - /// Convert `self` directly into a `TokenStream` object. - /// - /// This method is implicitly implemented using `to_tokens`, and acts as a - /// convenience method for consumers of the `ToTokens` trait. - fn into_token_stream(self) -> TokenStream - where - Self: Sized, - { - self.to_token_stream() - } -} - -impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T { - fn to_tokens(&self, tokens: &mut TokenStream) { - (**self).to_tokens(tokens); - } -} - -impl<'a, T: ?Sized + ToTokens> ToTokens for &'a mut T { - fn to_tokens(&self, tokens: &mut TokenStream) { - (**self).to_tokens(tokens); - } -} - -impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> { - fn to_tokens(&self, tokens: &mut TokenStream) { - (**self).to_tokens(tokens); - } -} - -impl ToTokens for Box { - fn to_tokens(&self, tokens: &mut TokenStream) { - (**self).to_tokens(tokens); - } -} - -impl ToTokens for Rc { - fn to_tokens(&self, tokens: &mut TokenStream) { - (**self).to_tokens(tokens); - } -} - -impl ToTokens for Option { - fn to_tokens(&self, tokens: &mut TokenStream) { - if let Some(ref t) = *self { - t.to_tokens(tokens); - } - } -} - -impl ToTokens for str { - fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.push_str(" \""); - tokens.push_str(self); - tokens.push('"'); - } -} - -impl ToTokens for String { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.as_str().to_tokens(tokens); - } -} - -macro_rules! primitive { - ($($t:ident => $name:ident)*) => ($( - impl ToTokens for $t { - fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.push_space(); - tokens.push_str(&self.to_string()); - tokens.push_str(stringify!($t)); - } - } - )*) -} - -primitive! { - i8 => i8_suffixed - i16 => i16_suffixed - i32 => i32_suffixed - i64 => i64_suffixed - i128 => i128_suffixed - isize => isize_suffixed - - u8 => u8_suffixed - u16 => u16_suffixed - u32 => u32_suffixed - u64 => u64_suffixed - u128 => u128_suffixed - usize => usize_suffixed - - f32 => f32_suffixed - f64 => f64_suffixed -} - -impl ToTokens for char { - fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.push_space(); - tokens.push('\''); - tokens.push(*self); - tokens.push('\''); - } -} - -impl ToTokens for bool { - fn to_tokens(&self, tokens: &mut TokenStream) { - let word = if *self { "true" } else { "false" }; - tokens.push_space(); - tokens.push_str(word); - } -} - -impl ToTokens for Literal { - fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.push_str(self.as_str()); - } -} - -impl ToTokens for TokenStream { - fn to_tokens(&self, dst: &mut TokenStream) { - dst.combine(self); - } - - fn into_token_stream(self) -> TokenStream { - self - } -} diff --git a/crates/tools/riddle/src/tokens/token_stream.rs b/crates/tools/riddle/src/tokens/token_stream.rs deleted file mode 100644 index 7bee9124e5..0000000000 --- a/crates/tools/riddle/src/tokens/token_stream.rs +++ /dev/null @@ -1,171 +0,0 @@ -/// A stream of tokens -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct TokenStream(pub String); - -impl From for TokenStream { - fn from(tokens: String) -> Self { - Self(tokens) - } -} - -impl From<&String> for TokenStream { - fn from(tokens: &String) -> Self { - Self(tokens.to_string()) - } -} - -impl From<&str> for TokenStream { - fn from(tokens: &str) -> Self { - Self(tokens.to_string()) - } -} - -impl TokenStream { - pub fn new() -> Self { - Self(String::new()) - } - - /// Appends another stream to the stream - /// - /// note: a space will be inserted before the other stream - pub fn combine(&mut self, other: &TokenStream) { - self.push_space(); - self.0.push_str(&other.0) - } - - #[must_use] - pub fn join(&self, value: &str) -> Self { - Self(format!("{}{value}", self.0)) - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// View the stream as a string - pub fn as_str(&self) -> &str { - &self.0 - } - - /// Convert the stream into a `String` - pub fn into_string(self) -> String { - self.0 - } - - /// Parse the token stream as something - /// - /// Mostly used with `proc_macro2::TokenStream` or `proc_macro::TokenStream` - pub fn parse(self) -> Result { - self.into_string().parse() - } - - pub(crate) fn push_space(&mut self) { - match self.last_char() { - None | Some(' ') => {} - _ => self.0.push(' '), - } - } - - pub fn push(&mut self, c: char) { - self.0.push(c) - } - - pub fn push_str(&mut self, str: &str) { - self.0.push_str(str) - } - - fn last_char(&self) -> Option { - self.0.chars().last() - } -} - -impl Default for TokenStream { - fn default() -> Self { - Self::new() - } -} - -impl core::iter::FromIterator for TokenStream { - fn from_iter>(iter: I) -> Self { - iter.into_iter() - .fold(None, |accum: Option, n| { - let mut ts = accum.unwrap_or_default(); - ts.combine(&n); - Some(ts) - }) - .unwrap_or_else(TokenStream::new) - } -} - -/// A delimiter around a block of code -#[derive(Copy, Clone)] -pub enum Delimiter { - /// `[]` - Bracket, - /// `{}` - Brace, - /// `()` - Parenthesis, -} - -impl Delimiter { - /// The opening delimiter - pub fn open(self) -> char { - match self { - Delimiter::Bracket => '[', - Delimiter::Brace => '{', - Delimiter::Parenthesis => '(', - } - } - - /// The closing delimiter - pub fn close(self) -> char { - match self { - Delimiter::Bracket => ']', - Delimiter::Brace => '}', - Delimiter::Parenthesis => ')', - } - } -} - -/// A literal of some sort -pub struct Literal { - inner: String, -} - -macro_rules! unsuffixed { - ($ty:ty => $name:ident) => { - pub fn $name(n: $ty) -> Self { - Self { - inner: n.to_string(), - } - } - }; -} - -impl Literal { - unsuffixed!(i64 => i64_unsuffixed); - unsuffixed!(usize => usize_unsuffixed); - unsuffixed!(u32 => u32_unsuffixed); - unsuffixed!(u16 => u16_unsuffixed); - unsuffixed!(u8 => u8_unsuffixed); - - pub fn byte_string(s: &[u8]) -> Self { - Self { - inner: format!( - "b\"{}\"", - core::str::from_utf8(s).expect("Could not turn bytes into byte literal") - ), - } - } - - pub fn as_str(&self) -> &str { - &self.inner - } -} - -impl core::fmt::Display for TokenStream { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", self.as_str()) - } -} diff --git a/crates/tools/riddle/src/tree.rs b/crates/tools/riddle/src/tree.rs deleted file mode 100644 index e9c46c0351..0000000000 --- a/crates/tools/riddle/src/tree.rs +++ /dev/null @@ -1,48 +0,0 @@ -use super::*; - -#[derive(Debug)] -pub struct Tree<'a> { - pub namespace: &'a str, - pub nested: std::collections::BTreeMap<&'a str, Tree<'a>>, -} - -impl<'a> Tree<'a> { - pub fn new(reader: &'a metadata::Reader, filter: &'a metadata::Filter) -> Self { - let mut tree = Tree::from_namespace(""); - for ns in reader.namespaces() { - if filter.includes_namespace(ns) { - tree.insert_namespace(ns, 0); - } - } - tree - } - - fn from_namespace(namespace: &'a str) -> Self { - Self { - namespace, - nested: std::collections::BTreeMap::new(), - } - } - fn insert_namespace(&mut self, namespace: &'a str, pos: usize) -> &mut Self { - if let Some(next) = namespace[pos..].find('.') { - let next = pos + next; - self.nested - .entry(&namespace[pos..next]) - .or_insert_with(|| Self::from_namespace(&namespace[..next])) - .insert_namespace(namespace, next + 1) - } else { - self.nested - .entry(&namespace[pos..]) - .or_insert_with(|| Self::from_namespace(namespace)) - } - } - pub fn flatten(&self) -> Vec<&Self> { - let mut flatten = if self.namespace.is_empty() { - vec![] - } else { - vec![self] - }; - flatten.extend(self.nested.values().flat_map(|tree| tree.flatten())); - flatten - } -} diff --git a/crates/tools/riddle/src/winmd/from_reader.rs b/crates/tools/riddle/src/winmd/from_reader.rs deleted file mode 100644 index c355ee762d..0000000000 --- a/crates/tools/riddle/src/winmd/from_reader.rs +++ /dev/null @@ -1,179 +0,0 @@ -use super::*; -use crate::winmd::{self, writer}; -use metadata::RowReader; - -pub fn from_reader( - reader: &metadata::Reader, - filter: &metadata::Filter, - config: std::collections::BTreeMap<&str, &str>, - output: &str, -) -> crate::Result<()> { - let mut writer = winmd::Writer::new(output); - - // TODO: do we need any configuration values for winmd generation? - // Maybe per-namespace winmd files for namespace-splitting - be sure to use - // the same key as for winmd generation. - - if let Some((key, _)) = config.first_key_value() { - return Err(crate::Error::new(&format!( - "invalid configuration value `{key}`" - ))); - } - - // TODO: just use the reader directly since we now have everything in the reader, there's no need to abstract - // away the source format. Few reprs is always better. - - for item in reader.items(filter) { - // TODO: cover all variants - let metadata::Item::Type(def) = item else { - continue; - }; - - let generics = &metadata::type_def_generics(reader, def); - - let extends = if let Some(extends) = reader.type_def_extends(def) { - writer.insert_type_ref(extends.namespace, extends.name) - } else { - 0 - }; - - writer.tables.TypeDef.push(writer::TypeDef { - Extends: extends, - FieldList: writer.tables.Field.len() as u32, - Flags: reader.type_def_flags(def).0, - MethodList: writer.tables.MethodDef.len() as u32, - TypeName: writer.strings.insert(reader.type_def_name(def)), - TypeNamespace: writer.strings.insert(reader.type_def_namespace(def)), - }); - - for generic in reader.type_def_generics(def) { - writer.tables.GenericParam.push(writer::GenericParam { - Number: reader.generic_param_number(generic), - Flags: 0, - Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1) - .encode(), - Name: writer.strings.insert(reader.generic_param_name(generic)), - }); - } - - for imp in reader.type_def_interface_impls(def) { - let ty = reader.interface_impl_type(imp, generics); - let ty = winmd_type(reader, &ty); - - let reference = match &ty { - winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => { - writer.insert_type_ref(&type_name.namespace, &type_name.name) - } - winmd::Type::TypeRef(_) => writer.insert_type_spec(ty), - rest => unimplemented!("{rest:?}"), - }; - - writer.tables.InterfaceImpl.push(writer::InterfaceImpl { - Class: writer.tables.TypeDef.len() as u32 - 1, - Interface: reference, - }); - } - - // TODO: if the class is "Apis" then should we sort the fields (constants) and methods (functions) for stability - - for field in reader.type_def_fields(def) { - let ty = winmd_type(reader, &reader.field_type(field, Some(def))); - let signature = writer.insert_field_sig(&ty); - - writer.tables.Field.push(writer::Field { - Flags: reader.field_flags(field).0, - Name: writer.strings.insert(reader.field_name(field)), - Signature: signature, - }); - } - - for method in reader.type_def_methods(def) { - let signature = reader.method_def_signature(method, generics); - let return_type = winmd_type(reader, &signature.return_type); - let param_types: Vec = signature - .params - .iter() - .map(|param| winmd_type(reader, param)) - .collect(); - - let signature = - writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); - - writer.tables.MethodDef.push(winmd::MethodDef { - RVA: 0, - ImplFlags: reader.method_def_impl_flags(method).0, - Flags: reader.method_def_flags(method).0, - Name: writer.strings.insert(reader.method_def_name(method)), - Signature: signature, - ParamList: writer.tables.Param.len() as u32, - }); - - for param in reader.method_def_params(method) { - writer.tables.Param.push(writer::Param { - Flags: reader.param_flags(param).0, - Sequence: reader.param_sequence(param), - Name: writer.strings.insert(reader.param_name(param)), - }); - } - } - } - - // TODO: In theory, `config` could instruct this function to balance the types across a number of winmd files - // like mdmerge supports for namespace-splitting. - crate::write_to_file(output, writer.into_stream()).map_err(|err| err.with_path(output)) -} - -// TODO: keep the basic type conversion -fn winmd_type(reader: &metadata::Reader, ty: &metadata::Type) -> winmd::Type { - match ty { - metadata::Type::Void => winmd::Type::Void, - metadata::Type::Bool => winmd::Type::Bool, - metadata::Type::Char => winmd::Type::Char, - metadata::Type::I8 => winmd::Type::I8, - metadata::Type::U8 => winmd::Type::U8, - metadata::Type::I16 => winmd::Type::I16, - metadata::Type::U16 => winmd::Type::U16, - metadata::Type::I32 => winmd::Type::I32, - metadata::Type::U32 => winmd::Type::U32, - metadata::Type::I64 => winmd::Type::I64, - metadata::Type::U64 => winmd::Type::U64, - metadata::Type::F32 => winmd::Type::F32, - metadata::Type::F64 => winmd::Type::F64, - metadata::Type::ISize => winmd::Type::ISize, - metadata::Type::USize => winmd::Type::USize, - metadata::Type::String => winmd::Type::String, - metadata::Type::GUID => winmd::Type::GUID, - metadata::Type::IUnknown => winmd::Type::IUnknown, - metadata::Type::IInspectable => winmd::Type::IInspectable, - metadata::Type::HRESULT => winmd::Type::HRESULT, - metadata::Type::PSTR => winmd::Type::PSTR, - metadata::Type::PWSTR => winmd::Type::PWSTR, - metadata::Type::PCSTR => winmd::Type::PCSTR, - metadata::Type::PCWSTR => winmd::Type::PCWSTR, - metadata::Type::BSTR => winmd::Type::BSTR, - metadata::Type::TypeName => winmd::Type::TypeName, - metadata::Type::TypeDef(def, generics) => winmd::Type::TypeRef(winmd::TypeName { - namespace: reader.type_def_namespace(*def).to_string(), - name: reader.type_def_name(*def).to_string(), - generics: generics.iter().map(|ty| winmd_type(reader, ty)).collect(), - }), - metadata::Type::GenericParam(generic) => { - winmd::Type::GenericParam(reader.generic_param_number(*generic)) - } - metadata::Type::ConstRef(ty) => winmd::Type::ConstRef(Box::new(winmd_type(reader, ty))), - metadata::Type::WinrtArrayRef(ty) => { - winmd::Type::WinrtArrayRef(Box::new(winmd_type(reader, ty))) - } - metadata::Type::WinrtArray(ty) => winmd::Type::WinrtArray(Box::new(winmd_type(reader, ty))), - metadata::Type::MutPtr(ty, pointers) => { - winmd::Type::MutPtr(Box::new(winmd_type(reader, ty)), *pointers) - } - metadata::Type::ConstPtr(ty, pointers) => { - winmd::Type::ConstPtr(Box::new(winmd_type(reader, ty)), *pointers) - } - metadata::Type::Win32Array(ty, len) => { - winmd::Type::Win32Array(Box::new(winmd_type(reader, ty)), *len) - } - rest => unimplemented!("{rest:?}"), - } -} diff --git a/crates/tools/riddle/src/winmd/mod.rs b/crates/tools/riddle/src/winmd/mod.rs deleted file mode 100644 index f01afa218a..0000000000 --- a/crates/tools/riddle/src/winmd/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod from_reader; -mod verify; -pub mod writer; -use super::*; -pub use from_reader::from_reader; -pub use verify::verify; -pub use writer::*; diff --git a/crates/tools/riddle/src/winmd/verify.rs b/crates/tools/riddle/src/winmd/verify.rs deleted file mode 100644 index dc892224eb..0000000000 --- a/crates/tools/riddle/src/winmd/verify.rs +++ /dev/null @@ -1,38 +0,0 @@ -use super::*; -use metadata::RowReader; - -pub fn verify(reader: &metadata::Reader, filter: &metadata::Filter) -> crate::Result<()> { - for item in reader.items(filter) { - // TODO: cover all variants - let metadata::Item::Type(def) = item else { - continue; - }; - - let generics = &metadata::type_def_generics(reader, def); - - reader - .type_def_fields(def) - .try_for_each(|field| not_type_ref(reader, &reader.field_type(field, Some(def))))?; - - reader.type_def_methods(def).try_for_each(|method| { - let sig = reader.method_def_signature(method, generics); - not_type_ref(reader, &sig.return_type)?; - - sig.params - .iter() - .try_for_each(|param| not_type_ref(reader, param)) - })?; - } - - Ok(()) -} - -fn not_type_ref(reader: &metadata::Reader, ty: &metadata::Type) -> crate::Result<()> { - if let metadata::Type::TypeRef(ty) = ty { - return Err(crate::Error::new(&format!( - "missing type definition `{}`", - reader.type_def_or_ref(*ty) - ))); - } - Ok(()) -} diff --git a/crates/tools/riddle/src/winmd/writer/blobs.rs b/crates/tools/riddle/src/winmd/writer/blobs.rs deleted file mode 100644 index 60fdb0affe..0000000000 --- a/crates/tools/riddle/src/winmd/writer/blobs.rs +++ /dev/null @@ -1,51 +0,0 @@ -use super::*; -use std::collections::hash_map::*; - -pub struct Blobs { - map: HashMap, u32>, - stream: Vec, -} - -impl Default for Blobs { - fn default() -> Self { - Self { - map: Default::default(), - stream: vec![0], - } - } -} - -impl Blobs { - pub fn insert(&mut self, value: &[u8]) -> u32 { - if value.is_empty() { - return 0; - } - - match self.map.entry(value.to_vec()) { - Entry::Vacant(entry) => { - let offset = *entry.insert(self.stream.len() as u32); - let len = value.len(); - match len { - 0..=0x7F => self.stream.push(len as u8), - 0x80..=0x3FFF => { - self.stream.push((0x80 | len >> 8) as u8); - self.stream.push((0xFF & len) as u8); - } - _ => { - self.stream.push((0xC0 | len >> 24) as u8); - self.stream.push((0xFF & len >> 16) as u8); - self.stream.push((0xFF & len >> 8) as u8); - self.stream.push((0xFF & len) as u8); - } - } - self.stream.extend_from_slice(value); - offset - } - Entry::Occupied(entry) => *entry.get(), - } - } - - pub fn into_stream(self) -> Vec { - self.stream.into_stream() - } -} diff --git a/crates/tools/riddle/src/winmd/writer/codes.rs b/crates/tools/riddle/src/winmd/writer/codes.rs deleted file mode 100644 index c5aa789e0a..0000000000 --- a/crates/tools/riddle/src/winmd/writer/codes.rs +++ /dev/null @@ -1,71 +0,0 @@ -#![allow(dead_code, clippy::enum_variant_names)] - -/// A `ResolutionScope` is an index into a certain table indicating the scope in which a TypeRef can be resolved. -#[derive(Clone)] -pub enum ResolutionScope { - Module(u32), - ModuleRef(u32), - AssemblyRef(u32), - TypeRef(u32), -} - -impl ResolutionScope { - pub fn encode(&self) -> u32 { - match self { - Self::Module(row) => (row + 1) << 2, - Self::ModuleRef(row) => ((row + 1) << 2) + 1, - Self::AssemblyRef(row) => ((row + 1) << 2) + 2, - Self::TypeRef(row) => ((row + 1) << 2) + 3, - } - } -} - -/// A `TypeDefOrRef` is an index into a certain table used to locate a type definition. -#[derive(Clone)] -pub enum TypeDefOrRef { - TypeDef(u32), - TypeRef(u32), - TypeSpec(u32), -} - -impl TypeDefOrRef { - pub fn encode(&self) -> u32 { - match self { - Self::TypeDef(row) => (row + 1) << 2, - Self::TypeRef(row) => ((row + 1) << 2) + 1, - Self::TypeSpec(row) => ((row + 1) << 2) + 2, - } - } -} - -/// A `HasConstant` is an index into a certain table used to identify the parent of a row in the `Constant` table. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum HasConstant { - Field(u32), - Param(u32), - Property(u32), -} - -impl HasConstant { - pub fn encode(&self) -> u32 { - match self { - Self::Field(row) => (row + 1) << 2, - Self::Param(row) => ((row + 1) << 2) + 1, - Self::Property(row) => ((row + 1) << 2) + 2, - } - } -} - -/// A `TypeOrMethodDef` is an index into a certain table used to locate the owner of a generic parameter. -#[derive(Clone)] -pub enum TypeOrMethodDef { - TypeDef(u32), -} - -impl TypeOrMethodDef { - pub fn encode(&self) -> u32 { - match self { - Self::TypeDef(row) => (row + 1) << 1, - } - } -} diff --git a/crates/tools/riddle/src/winmd/writer/file.rs b/crates/tools/riddle/src/winmd/writer/file.rs deleted file mode 100644 index e1099003b8..0000000000 --- a/crates/tools/riddle/src/winmd/writer/file.rs +++ /dev/null @@ -1,169 +0,0 @@ -use super::*; -use metadata::imp::*; -use std::mem::*; - -pub fn write(mut tables: Vec, mut strings: Vec, mut blobs: Vec) -> Vec { - if [tables.len(), strings.len(), blobs.len()] - .iter() - .any(|len| *len > u32::MAX as usize) - { - panic!("heap too large"); - } - - unsafe { - let mut guids = vec![0; 16]; // zero guid - let size_of_streams = tables.len() + guids.len() + strings.len() + blobs.len(); - - let mut dos: IMAGE_DOS_HEADER = zeroed(); - dos.e_magic = IMAGE_DOS_SIGNATURE; - dos.e_lfarlc = 64; - dos.e_lfanew = size_of::() as i32; - - let mut file: IMAGE_FILE_HEADER = zeroed(); - file.Machine = IMAGE_FILE_MACHINE_I386; - file.NumberOfSections = 1; - file.SizeOfOptionalHeader = size_of::() as u16; - file.Characteristics = - IMAGE_FILE_DLL | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE; - - let mut optional: IMAGE_OPTIONAL_HEADER32 = zeroed(); - optional.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC; - optional.MajorLinkerVersion = 11; - optional.SizeOfInitializedData = 1024; - optional.ImageBase = 0x400000; - optional.SectionAlignment = SECTION_ALIGNMENT; - optional.FileAlignment = 512; - optional.MajorOperatingSystemVersion = 6; - optional.MinorOperatingSystemVersion = 2; - optional.MajorSubsystemVersion = 6; - optional.MinorSubsystemVersion = 2; - optional.SizeOfHeaders = 512; - optional.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; - optional.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT - | IMAGE_DLLCHARACTERISTICS_NO_SEH - | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; - optional.SizeOfStackReserve = 0x100000; - optional.SizeOfHeapReserve = 4096; - optional.LoaderFlags = 0x100000; - optional.NumberOfRvaAndSizes = 16; - - let mut section: IMAGE_SECTION_HEADER = zeroed(); - section.Name = *b".text\0\0\0"; - section.Characteristics = 0x4000_0020; - section.VirtualAddress = SECTION_ALIGNMENT; - - let mut clr: IMAGE_COR20_HEADER = zeroed(); - clr.cb = size_of::() as u32; - clr.MajorRuntimeVersion = 2; - clr.MinorRuntimeVersion = 5; - clr.Flags = 1; - - let metadata = METADATA_HEADER { - signature: METADATA_SIGNATURE, - major_version: 1, - minor_version: 1, - length: 20, - version: *b"WindowsRuntime 1.4\0\0", - streams: 4, - ..Default::default() - }; - - type TablesHeader = StreamHeader<4>; - type StringsHeader = StreamHeader<12>; - type GuidsHeader = StreamHeader<8>; - type BlobsHeader = StreamHeader<8>; - - let size_of_stream_headers = size_of::() - + size_of::() - + size_of::() - + size_of::(); - let size_of_image = optional.FileAlignment as usize - + size_of::() - + size_of::() - + size_of_stream_headers - + size_of_streams; - - optional.SizeOfImage = round(size_of_image, optional.SectionAlignment as usize) as u32; - section.Misc.VirtualSize = size_of_image as u32 - optional.FileAlignment; - section.SizeOfRawData = round( - section.Misc.VirtualSize as usize, - optional.FileAlignment as usize, - ) as u32; - - optional.DataDirectory[14] = IMAGE_DATA_DIRECTORY { - VirtualAddress: SECTION_ALIGNMENT, - Size: size_of::() as u32, - }; - section.PointerToRawData = optional.FileAlignment; - clr.MetaData.VirtualAddress = SECTION_ALIGNMENT + size_of::() as u32; - clr.MetaData.Size = section.Misc.VirtualSize - size_of::() as u32; - - let mut buffer = Vec::::new(); - - buffer.write_header(&dos); - buffer.write_u32(IMAGE_NT_SIGNATURE); - buffer.write_header(&file); - buffer.write_header(&optional); - buffer.write_header(§ion); - debug_assert!(buffer.len() < optional.FileAlignment as usize); - buffer.resize(optional.FileAlignment as usize, 0); - buffer.write_header(&clr); - let metadata_offset = buffer.len(); - buffer.write_header(&metadata); - - let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers; - let tables_header = TablesHeader::new(stream_offset as u32, tables.len() as u32, b"#~\0\0"); - let strings_header = StringsHeader::new( - tables_header.next_offset(), - strings.len() as u32, - b"#Strings\0\0\0\0", - ); - let guids_header = GuidsHeader::new( - strings_header.next_offset(), - guids.len() as u32, - b"#GUID\0\0\0", - ); - let blobs_header = BlobsHeader::new( - guids_header.next_offset(), - blobs.len() as u32, - b"#Blob\0\0\0", - ); - - buffer.write_header(&tables_header); - buffer.write_header(&strings_header); - buffer.write_header(&guids_header); - buffer.write_header(&blobs_header); - - buffer.append(&mut tables); - buffer.append(&mut strings); - buffer.append(&mut guids); - buffer.append(&mut blobs); - - assert_eq!(clr.MetaData.Size as usize, buffer.len() - metadata_offset); - assert_eq!(size_of_image, buffer.len()); - - buffer - } -} - -const SECTION_ALIGNMENT: u32 = 4096; - -#[repr(C)] -struct StreamHeader { - offset: u32, - size: u32, - name: [u8; LEN], -} - -impl StreamHeader { - fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self { - Self { - offset, - size, - name: *name, - } - } - fn next_offset(&self) -> u32 { - self.offset + self.size - } -} diff --git a/crates/tools/riddle/src/winmd/writer/mod.rs b/crates/tools/riddle/src/winmd/writer/mod.rs deleted file mode 100644 index 63fc0eaf96..0000000000 --- a/crates/tools/riddle/src/winmd/writer/mod.rs +++ /dev/null @@ -1,365 +0,0 @@ -mod blobs; -mod codes; -mod file; -mod strings; -mod tables; -mod traits; -mod r#type; - -use super::*; -use blobs::Blobs; -pub use codes::*; -use metadata::imp::*; -pub use r#type::*; -use std::collections::HashMap; -use strings::Strings; -pub use tables::*; -use traits::*; - -pub struct Writer { - pub blobs: Blobs, - pub strings: Strings, - pub tables: Tables, - pub scopes: HashMap, - // TODO: is this faster than jsut using a single HashMap with a (String,String) key? - pub type_refs: HashMap>, - pub type_specs: HashMap, -} - -impl Writer { - pub fn new(name: &str) -> Self { - let mut writer = Self { - blobs: Default::default(), - strings: Default::default(), - tables: Default::default(), - scopes: Default::default(), - type_refs: Default::default(), - type_specs: Default::default(), - }; - - writer.tables.TypeDef.push(TypeDef { - TypeName: writer.strings.insert(""), - ..Default::default() - }); - - let name = name - .rsplit_once(&['/', '\\']) - .map_or(name, |(_, name)| name); - - writer.tables.Module.push(Module { - Name: writer.strings.insert(name), - Mvid: 1, - ..Default::default() - }); - - let name = name.rsplit_once('.').map_or(name, |(_, name)| name); - - writer.tables.Assembly.push(Assembly { - Name: writer.strings.insert(name), - HashAlgId: 0x00008004, - MajorVersion: 0xFF, - MinorVersion: 0xFF, - BuildNumber: 0xFF, - RevisionNumber: 0xFF, - Flags: metadata::AssemblyFlags::WindowsRuntime.0, - ..Default::default() - }); - - // Some winmd parsers will fail to read without an `mscorlib` reference. The `insert_module_types` function will typically include it - // automatically but a minimal `Module` tree may not add this dependency. - writer.insert_scope("System"); - - writer - } - - pub fn into_stream(self) -> Vec { - file::write( - self.tables.into_stream(), - self.strings.into_stream(), - self.blobs.into_stream(), - ) - } - - pub fn insert_method_sig( - &mut self, - call_flags: metadata::MethodCallAttributes, - return_type: &Type, - param_types: &[Type], - ) -> u32 { - let mut blob = vec![call_flags.0]; - usize_blob(param_types.len(), &mut blob); - self.type_blob(return_type, &mut blob); - - for ty in param_types { - self.type_blob(ty, &mut blob); - } - - self.blobs.insert(&blob) - } - - pub fn insert_field_sig(&mut self, ty: &Type) -> u32 { - // TODO: can either cache in Writer, like we do for scopes and type_refs, or regenerate each time. - // Profile once we can stress test this with field/method signatures. - - let mut blob = vec![0x6]; // FIELD - self.type_blob(ty, &mut blob); - - self.blobs.insert(&blob) - } - - fn insert_scope(&mut self, namespace: &str) -> u32 { - if let Some(scope) = self.scopes.get(namespace) { - *scope - } else if namespace == "System" { - let scope = ResolutionScope::AssemblyRef( - self.tables.AssemblyRef.push2(AssemblyRef { - Name: self.strings.insert("mscorlib"), - MajorVersion: 4, - PublicKeyOrToken: self - .blobs - .insert(&[0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]), // TODO: comment on this - ..Default::default() - }), - ) - .encode(); - self.scopes.insert(namespace.to_string(), scope); - scope - } else { - // TODO: may need to capture the original assembly info for external type_refs. - let scope = ResolutionScope::AssemblyRef(self.tables.AssemblyRef.push2(AssemblyRef { - Name: self.strings.insert(namespace), - MajorVersion: 0xFF, - MinorVersion: 0xFF, - BuildNumber: 0xFF, - RevisionNumber: 0xFF, - Flags: metadata::AssemblyFlags::WindowsRuntime.0, - ..Default::default() - })) - .encode(); - self.scopes.insert(namespace.to_string(), scope); - scope - } - } - - pub fn insert_type_ref(&mut self, namespace: &str, name: &str) -> u32 { - if let Some(key) = self.type_refs.get(namespace) { - if let Some(reference) = key.get(name) { - return *reference; - } - } - - let scope = self.insert_scope(namespace); - - let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { - TypeName: self.strings.insert(name), - TypeNamespace: self.strings.insert(namespace), - ResolutionScope: scope, - })) - .encode(); - self.type_refs - .entry(namespace.to_string()) - .or_default() - .insert(name.to_string(), reference); - reference - } - - pub fn insert_type_spec(&mut self, ty: Type) -> u32 { - if let Some(key) = self.type_specs.get(&ty) { - return *key; - } - - let mut blob = vec![]; - self.type_blob(&ty, &mut blob); - let signature = self.blobs.insert(&blob); - - let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { - Signature: signature, - })) - .encode(); - - self.type_specs.insert(ty, reference); - reference - } - - fn type_blob(&mut self, ty: &Type, blob: &mut Vec) { - match ty { - Type::Void => blob.push(ELEMENT_TYPE_VOID), - Type::Bool => blob.push(ELEMENT_TYPE_BOOLEAN), - Type::Char => blob.push(ELEMENT_TYPE_CHAR), - Type::I8 => blob.push(ELEMENT_TYPE_I1), - Type::U8 => blob.push(ELEMENT_TYPE_U1), - Type::I16 => blob.push(ELEMENT_TYPE_I2), - Type::U16 => blob.push(ELEMENT_TYPE_U2), - Type::I32 => blob.push(ELEMENT_TYPE_I4), - Type::U32 => blob.push(ELEMENT_TYPE_U4), - Type::I64 => blob.push(ELEMENT_TYPE_I8), - Type::U64 => blob.push(ELEMENT_TYPE_U8), - Type::F32 => blob.push(ELEMENT_TYPE_R4), - Type::F64 => blob.push(ELEMENT_TYPE_R8), - Type::ISize => blob.push(ELEMENT_TYPE_I), - Type::USize => blob.push(ELEMENT_TYPE_U), - Type::String => blob.push(ELEMENT_TYPE_STRING), - Type::IInspectable => blob.push(ELEMENT_TYPE_OBJECT), - Type::GUID => { - let code = self.insert_type_ref("System", "Guid"); - blob.push(ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); - } - Type::HRESULT => { - let code = self.insert_type_ref("Windows.Foundation", "HResult"); - blob.push(ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); - } - Type::TypeRef(ty) => { - if !ty.generics.is_empty() { - blob.push(ELEMENT_TYPE_GENERICINST); - } - let code = self.insert_type_ref(&ty.namespace, &ty.name); - blob.push(ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); - - if !ty.generics.is_empty() { - usize_blob(ty.generics.len(), blob); - - for ty in &ty.generics { - self.type_blob(ty, blob); - } - } - } - Type::BSTR => { - let code = self.insert_type_ref("Windows.Win32.Foundation", "BSTR"); - blob.push(ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); - } - Type::IUnknown => { - let code = self.insert_type_ref("Windows.Win32.Foundation", "IUnknown"); - blob.push(ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); - } - Type::PCWSTR | Type::PWSTR => { - let code = self.insert_type_ref("Windows.Win32.Foundation", "PWSTR"); - blob.push(ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); - } - Type::PCSTR | Type::PSTR => { - let code = self.insert_type_ref("Windows.Win32.Foundation", "PSTR"); - blob.push(ELEMENT_TYPE_VALUETYPE); - usize_blob(code as usize, blob); - } - Type::ConstRef(ty) => { - usize_blob(ELEMENT_TYPE_CMOD_OPT as usize, blob); - usize_blob( - self.insert_type_ref("System.Runtime.CompilerServices", "IsConst") as usize, - blob, - ); - usize_blob(ELEMENT_TYPE_BYREF as usize, blob); - self.type_blob(ty, blob); - } - Type::WinrtArrayRef(ty) => { - usize_blob(ELEMENT_TYPE_BYREF as usize, blob); - usize_blob(ELEMENT_TYPE_SZARRAY as usize, blob); - self.type_blob(ty, blob); - } - Type::WinrtArray(ty) => { - usize_blob(ELEMENT_TYPE_SZARRAY as usize, blob); - self.type_blob(ty, blob); - } - Type::Win32Array(ty, bounds) => { - usize_blob(ELEMENT_TYPE_ARRAY as usize, blob); - self.type_blob(ty, blob); - usize_blob(1, blob); // rank - usize_blob(1, blob); // count - usize_blob(*bounds, blob); - } - Type::TypeName => { - let code = self.insert_type_ref("System", "Type"); - blob.push(ELEMENT_TYPE_CLASS); - usize_blob(code as usize, blob); - } - Type::MutPtr(ty, pointers) | Type::ConstPtr(ty, pointers) => { - for _ in 0..*pointers { - usize_blob(ELEMENT_TYPE_PTR as usize, blob); - } - self.type_blob(ty, blob); - } - Type::GenericParam(index) => { - blob.push(ELEMENT_TYPE_VAR); - usize_blob(*index as usize, blob); - } - } - } -} - -fn round(size: usize, round: usize) -> usize { - let round = round - 1; - (size + round) & !round -} - -fn usize_blob(value: usize, blob: &mut Vec) { - // See II.23.2 in ECMA-335 - assert!(value < 0x20000000); - - if value < 0x80 { - blob.push(value as u8); - } else if value < 0x4000 { - blob.push((0x80 | (value & 0x3F00) >> 8) as u8); - blob.push((value & 0xFF) as u8); - } else { - blob.push((0xC0 | (value & 0x1F000000) >> 24) as u8); - blob.push(((value & 0xFF0000) >> 16) as u8); - blob.push(((value & 0xFF00) >> 8) as u8); - blob.push((value & 0xFF) as u8); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_usize_blob() { - let mut blob = vec![]; - usize_blob(0, &mut blob); - usize_blob(1, &mut blob); - usize_blob(2, &mut blob); - - usize_blob(0x80 - 2, &mut blob); - usize_blob(0x80 - 1, &mut blob); - usize_blob(0x80, &mut blob); - usize_blob(0x80 + 1, &mut blob); - usize_blob(0x80 + 2, &mut blob); - - usize_blob(0x4000 - 2, &mut blob); - usize_blob(0x4000 - 1, &mut blob); - usize_blob(0x4000, &mut blob); - usize_blob(0x4000 + 1, &mut blob); - usize_blob(0x4000 + 2, &mut blob); - - usize_blob(0x20000000 - 3, &mut blob); - usize_blob(0x20000000 - 2, &mut blob); - usize_blob(0x20000000 - 1, &mut blob); - - let mut blob = metadata::Blob::new(0, &blob); - assert_eq!(blob.read_usize(), 0); - assert_eq!(blob.read_usize(), 1); - assert_eq!(blob.read_usize(), 2); - - assert_eq!(blob.read_usize(), 0x80 - 2); - assert_eq!(blob.read_usize(), 0x80 - 1); - assert_eq!(blob.read_usize(), 0x80); - assert_eq!(blob.read_usize(), 0x80 + 1); - assert_eq!(blob.read_usize(), 0x80 + 2); - - assert_eq!(blob.read_usize(), 0x4000 - 2); - assert_eq!(blob.read_usize(), 0x4000 - 1); - assert_eq!(blob.read_usize(), 0x4000); - assert_eq!(blob.read_usize(), 0x4000 + 1); - assert_eq!(blob.read_usize(), 0x4000 + 2); - - assert_eq!(blob.read_usize(), 0x20000000 - 3); - assert_eq!(blob.read_usize(), 0x20000000 - 2); - assert_eq!(blob.read_usize(), 0x20000000 - 1); - - assert_eq!(blob.slice.len(), 0); - } -} diff --git a/crates/tools/riddle/src/winmd/writer/strings.rs b/crates/tools/riddle/src/winmd/writer/strings.rs deleted file mode 100644 index f7c3dd9c06..0000000000 --- a/crates/tools/riddle/src/winmd/writer/strings.rs +++ /dev/null @@ -1,38 +0,0 @@ -use super::*; -use std::collections::hash_map::*; - -pub struct Strings { - map: HashMap, - stream: Vec, -} - -impl Default for Strings { - fn default() -> Self { - Self { - map: Default::default(), - stream: vec![0], - } - } -} - -impl Strings { - pub fn insert(&mut self, value: &str) -> u32 { - if value.is_empty() { - return 0; - } - - match self.map.entry(value.to_string()) { - Entry::Vacant(entry) => { - let offset = *entry.insert(self.stream.len() as u32); - self.stream.extend_from_slice(value.as_bytes()); - self.stream.push(0); - offset - } - Entry::Occupied(entry) => *entry.get(), - } - } - - pub fn into_stream(self) -> Vec { - self.stream.into_stream() - } -} diff --git a/crates/tools/riddle/src/winmd/writer/tables.rs b/crates/tools/riddle/src/winmd/writer/tables.rs deleted file mode 100644 index 3e590dde73..0000000000 --- a/crates/tools/riddle/src/winmd/writer/tables.rs +++ /dev/null @@ -1,390 +0,0 @@ -#![allow(non_snake_case)] - -use super::Write; -use super::*; -use metadata::imp::coded_index_size; - -#[derive(Default)] -pub struct Tables { - // TODO: use BTreeSet for tables that have a primary key, unless they are naturally sorted. - pub Assembly: Vec, - pub AssemblyRef: Vec, - pub ClassLayout: Vec, - pub Constant: Vec, - pub CustomAttribute: Vec, - pub Field: Vec, - pub GenericParam: Vec, - pub ImplMap: Vec, - pub InterfaceImpl: Vec, - pub MemberRef: Vec, - pub MethodDef: Vec, - pub Module: Vec, - pub ModuleRef: Vec, - pub NestedClass: Vec, - pub Param: Vec, - pub Property: Vec, - pub TypeDef: Vec, - pub TypeRef: Vec, - pub TypeSpec: Vec, -} - -#[derive(Default)] -pub struct Assembly { - pub HashAlgId: u32, - pub MajorVersion: u16, - pub MinorVersion: u16, - pub BuildNumber: u16, - pub RevisionNumber: u16, - pub Flags: u32, - pub PublicKey: u32, - pub Name: u32, - pub Culture: u32, -} - -#[derive(Default)] -pub struct AssemblyRef { - pub MajorVersion: u16, - pub MinorVersion: u16, - pub BuildNumber: u16, - pub RevisionNumber: u16, - pub Flags: u32, - pub PublicKeyOrToken: u32, - pub Name: u32, - pub Culture: u32, - pub HashValue: u32, -} - -#[derive(Default)] -pub struct ClassLayout { - pub PackingSize: u16, - pub ClassSize: u32, - pub Parent: u32, -} - -#[derive(Default)] -pub struct Constant { - pub Type: u16, - pub Parent: u32, - pub Value: u32, -} - -#[derive(Default)] -pub struct CustomAttribute { - pub Parent: u32, - pub Type: u32, - pub Value: u32, -} - -#[derive(Default)] -pub struct Field { - pub Flags: u16, - pub Name: u32, - pub Signature: u32, -} - -#[derive(Default)] -pub struct GenericParam { - pub Number: u16, - pub Flags: u16, - pub Owner: u32, - pub Name: u32, -} - -#[derive(Default)] -pub struct ImplMap { - pub MappingFlags: u16, - pub MemberForwarded: u32, - pub ImportName: u32, - pub ImportScope: u32, -} - -#[derive(Default)] -pub struct InterfaceImpl { - pub Class: u32, - pub Interface: u32, -} - -#[derive(Default)] -pub struct MemberRef { - pub Class: u32, - pub Name: u32, - pub Signature: u32, -} - -#[derive(Default)] -pub struct MethodDef { - pub RVA: u32, - pub ImplFlags: u16, - pub Flags: u16, - pub Name: u32, - pub Signature: u32, - pub ParamList: u32, -} - -#[derive(Default)] -pub struct Module { - pub Generation: u16, - pub Name: u32, - pub Mvid: u32, - pub EncId: u32, - pub EncBaseId: u32, -} - -#[derive(Default)] -pub struct ModuleRef { - pub Name: u32, -} - -#[derive(Default)] -pub struct NestedClass { - pub NestedClass: u32, - pub EnclosingClass: u32, -} - -#[derive(Default)] -pub struct Param { - pub Flags: u16, - pub Sequence: u16, - pub Name: u32, -} - -#[derive(Default)] -pub struct Property { - pub Flags: u16, - pub Name: u32, - pub Type: u32, -} - -#[derive(Default)] -pub struct TypeDef { - pub Flags: u32, - pub TypeName: u32, - pub TypeNamespace: u32, - pub Extends: u32, - pub FieldList: u32, - pub MethodList: u32, -} - -#[derive(Default)] -pub struct TypeRef { - pub ResolutionScope: u32, - pub TypeName: u32, - pub TypeNamespace: u32, -} - -#[derive(Default)] -pub struct TypeSpec { - pub Signature: u32, -} - -impl Tables { - pub fn into_stream(self) -> Vec { - if [ - self.AssemblyRef.len(), - self.ClassLayout.len(), - self.Constant.len(), - self.CustomAttribute.len(), - self.Field.len(), - self.GenericParam.len(), - self.ImplMap.len(), - self.InterfaceImpl.len(), - self.MemberRef.len(), - self.MethodDef.len(), - self.Module.len(), - self.ModuleRef.len(), - self.NestedClass.len(), - self.Param.len(), - self.Property.len(), - self.TypeDef.len(), - self.TypeRef.len(), - self.TypeSpec.len(), - ] - .iter() - .any(|len| *len > u32::MAX as usize) - { - panic!("metadata table too large"); - } - - let resolution_scope = coded_index_size(&[ - self.Module.len(), - self.ModuleRef.len(), - self.AssemblyRef.len(), - self.TypeRef.len(), - ]); - - let type_def_or_ref = - coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()]); - - let has_constant = - coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]); - - let type_or_method_def = coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]); - - let valid_tables: u64 = 1 << 0 | // Module - 1 << 0x01 | // TypeRef - 1 << 0x02 | // TypeDef - 1 << 0x04 | // Field - 1 << 0x06 | // MethodDef - 1 << 0x08 | // Param - 1 << 0x09 | // InterfaceImpl - 1 << 0x0A | // MemberRef - 1 << 0x0B | // Constant - 1 << 0x0C | // CustomAttribute - 1 << 0x0F | // ClassLayout - 1 << 0x17 | // Property - 1 << 0x1A | // ModuleRef - 1 << 0x1B | // TypeSpec - 1 << 0x1C | // ImplMap - 1 << 0x20 | // Assembly - 1 << 0x23 | // AssemblyRef - 1 << 0x29 | // NestedClass - 1 << 0x2A; // GenericParam - - // The table stream header... - - let mut buffer = Vec::new(); - buffer.write_u32(0); // Reserved - buffer.write_u8(2); // MajorVersion - buffer.write_u8(0); // MinorVersion - buffer.write_u8(0b111); // HeapSizes - buffer.write_u8(0); // Reserved - buffer.write_u64(valid_tables); - buffer.write_u64(0); // Sorted - - // Followed by the length of each of the valid tables... - - buffer.write_u32(self.Module.len() as u32); - buffer.write_u32(self.TypeRef.len() as u32); - buffer.write_u32(self.TypeDef.len() as u32); - buffer.write_u32(self.Field.len() as u32); - buffer.write_u32(self.MethodDef.len() as u32); - buffer.write_u32(self.Param.len() as u32); - buffer.write_u32(self.InterfaceImpl.len() as u32); - buffer.write_u32(self.MemberRef.len() as u32); - buffer.write_u32(self.Constant.len() as u32); - buffer.write_u32(self.CustomAttribute.len() as u32); - buffer.write_u32(self.ClassLayout.len() as u32); - buffer.write_u32(self.Property.len() as u32); - buffer.write_u32(self.ModuleRef.len() as u32); - buffer.write_u32(self.TypeSpec.len() as u32); - buffer.write_u32(self.ImplMap.len() as u32); - buffer.write_u32(self.Assembly.len() as u32); - buffer.write_u32(self.AssemblyRef.len() as u32); - buffer.write_u32(self.NestedClass.len() as u32); - buffer.write_u32(self.GenericParam.len() as u32); - - // Followed by each table's rows... - - for x in self.Module { - buffer.write_u16(x.Generation); - buffer.write_u32(x.Name); - buffer.write_u32(x.Mvid); - buffer.write_u32(x.EncId); - buffer.write_u32(x.EncBaseId); - } - - for x in self.TypeRef { - buffer.write_code(x.ResolutionScope, resolution_scope); - buffer.write_u32(x.TypeName); - buffer.write_u32(x.TypeNamespace); - } - - for x in &self.TypeDef { - buffer.write_u32(x.Flags); - buffer.write_u32(x.TypeName); - buffer.write_u32(x.TypeNamespace); - buffer.write_code(x.Extends, type_def_or_ref); - buffer.write_index(x.FieldList, self.Field.len()); - buffer.write_index(x.MethodList, self.MethodDef.len()); - } - - for x in self.Field { - buffer.write_u16(x.Flags); - buffer.write_u32(x.Name); - buffer.write_u32(x.Signature); - } - - for x in self.MethodDef { - buffer.write_u32(x.RVA); - buffer.write_u16(x.ImplFlags); - buffer.write_u16(x.Flags); - buffer.write_u32(x.Name); - buffer.write_u32(x.Signature); - buffer.write_index(x.ParamList, self.Param.len()); - } - - for x in self.Param { - buffer.write_u16(x.Flags); - buffer.write_u16(x.Sequence); - buffer.write_u32(x.Name); - } - - for x in self.InterfaceImpl { - buffer.write_index(x.Class, self.TypeDef.len()); - buffer.write_code(x.Interface, type_def_or_ref); - } - - for x in self.Constant { - buffer.write_u16(x.Type); - buffer.write_code(x.Parent, has_constant); - buffer.write_u32(x.Value); - } - - for x in self.TypeSpec { - buffer.write_u32(x.Signature); - } - - for x in self.Assembly { - buffer.write_u32(x.HashAlgId); - buffer.write_u16(x.MajorVersion); - buffer.write_u16(x.MinorVersion); - buffer.write_u16(x.BuildNumber); - buffer.write_u16(x.RevisionNumber); - buffer.write_u32(x.Flags); - buffer.write_u32(x.PublicKey); - buffer.write_u32(x.Name); - buffer.write_u32(x.Culture); - } - - for x in self.AssemblyRef { - buffer.write_u16(x.MajorVersion); - buffer.write_u16(x.MinorVersion); - buffer.write_u16(x.BuildNumber); - buffer.write_u16(x.RevisionNumber); - buffer.write_u32(x.Flags); - buffer.write_u32(x.PublicKeyOrToken); - buffer.write_u32(x.Name); - buffer.write_u32(x.Culture); - buffer.write_u32(x.HashValue); - } - - for x in self.GenericParam { - buffer.write_u16(x.Number); - buffer.write_u16(x.Flags); - buffer.write_code(x.Owner, type_or_method_def); - buffer.write_u32(x.Name); - } - - // TODO: sort GenericParam table prior to writing. This needs to be done for all tables with a primary index. See II.22 - - // TODO: do these get naturally sorted by virtue of how they're pushed into "tables" in type def order? - - // Table Primary Key Column - // ClassLayout Parent - // Constant Parent - // CustomAttribute Parent - // DeclSecurity Parent - // FieldLayout Field - // FieldMarshal Parent - // FieldRVA Field - // GenericParam Owner - // GenericParamConstraint Owner - // ImplMap MemberForwarded - // InterfaceImpl Class - // MethodImpl Class - // MethodSemantics Association - // NestedClass NestedClass - - buffer.into_stream() - } -} diff --git a/crates/tools/riddle/src/winmd/writer/traits.rs b/crates/tools/riddle/src/winmd/writer/traits.rs deleted file mode 100644 index 20e18b3244..0000000000 --- a/crates/tools/riddle/src/winmd/writer/traits.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::*; - -pub trait Write { - unsafe fn write_header(&mut self, value: &T); - fn write_u8(&mut self, value: u8); - fn write_u16(&mut self, value: u16); - fn write_u32(&mut self, value: u32); - fn write_u64(&mut self, value: u64); - fn write_code(&mut self, value: u32, size: usize); - fn write_index(&mut self, index: u32, len: usize); - fn into_stream(self) -> Self; -} - -impl Write for Vec { - unsafe fn write_header(&mut self, value: &T) { - self.extend_from_slice(std::slice::from_raw_parts( - value as *const _ as _, - std::mem::size_of::(), - )); - } - - fn write_u8(&mut self, value: u8) { - self.extend_from_slice(&value.to_le_bytes()); - } - - fn write_u16(&mut self, value: u16) { - self.extend_from_slice(&value.to_le_bytes()); - } - - fn write_u32(&mut self, value: u32) { - self.extend_from_slice(&value.to_le_bytes()); - } - - fn write_u64(&mut self, value: u64) { - self.extend_from_slice(&value.to_le_bytes()); - } - - fn write_code(&mut self, value: u32, size: usize) { - if size == 2 { - self.write_u16(value as u16); - } else { - self.write_u32(value); - } - } - - fn write_index(&mut self, index: u32, len: usize) { - if len < (1 << 16) { - self.write_u16(index as u16 + 1); - } else { - self.write_u32(index + 1); - } - } - - fn into_stream(mut self) -> Self { - self.resize(round(self.len(), 4), 0); - self - } -} - -pub trait Push2 { - fn push2(&mut self, value: T) -> u32; -} - -impl Push2 for Vec { - fn push2(&mut self, value: T) -> u32 { - self.push(value); - (self.len() - 1) as u32 - } -} diff --git a/crates/tools/riddle/src/winmd/writer/type.rs b/crates/tools/riddle/src/winmd/writer/type.rs deleted file mode 100644 index 3f0178654a..0000000000 --- a/crates/tools/riddle/src/winmd/writer/type.rs +++ /dev/null @@ -1,80 +0,0 @@ -#![allow(dead_code, clippy::upper_case_acronyms)] - -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct TypeName { - pub namespace: String, - pub name: String, - pub generics: Vec, -} - -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub enum Type { - Void, - Bool, - Char, - I8, - U8, - I16, - U16, - I32, - U32, - I64, - U64, - F32, - F64, - ISize, - USize, - String, - GUID, - IUnknown, - IInspectable, - HRESULT, - PSTR, - PWSTR, - PCSTR, - PCWSTR, - BSTR, - TypeName, - TypeRef(TypeName), - GenericParam(u16), - MutPtr(Box, usize), - ConstPtr(Box, usize), - Win32Array(Box, usize), - WinrtArray(Box), - WinrtArrayRef(Box), - ConstRef(Box), -} - -impl Type { - pub fn into_mut_ptr(self) -> Self { - match self { - Self::MutPtr(ty, count) => Self::MutPtr(ty, count + 1), - Self::ConstPtr(ty, count) => Self::MutPtr(ty, count + 1), - _ => Self::MutPtr(Box::new(self), 1), - } - } - - pub fn into_const_ptr(self) -> Self { - match self { - Self::MutPtr(ty, count) => Self::ConstPtr(ty, count + 1), - Self::ConstPtr(ty, count) => Self::ConstPtr(ty, count + 1), - _ => Self::ConstPtr(Box::new(self), 1), - } - } - - pub fn into_array(self, len: usize) -> Self { - Self::Win32Array(Box::new(self), len) - } -} - -pub struct Signature { - pub params: Vec, - pub return_type: Type, - pub call_flags: u8, -} - -// TODO: just Param? -pub struct SignatureParam { - pub name: String, - pub ty: Type, -} diff --git a/crates/tools/sys/bindings.txt b/crates/tools/sys/bindings.txt index 018dd5500d..ae9b235e65 100644 --- a/crates/tools/sys/bindings.txt +++ b/crates/tools/sys/bindings.txt @@ -1,6 +1,6 @@ ---in crates/libs/metadata/default +--in crates/libs/bindgen/default --out crates/libs/sys/src/lib.rs ---config PACKAGE SYS +--config package sys --filter Windows.Wdk diff --git a/crates/tools/windows/bindings.txt b/crates/tools/windows/bindings.txt index a87eb2ef5b..548d49c094 100644 --- a/crates/tools/windows/bindings.txt +++ b/crates/tools/windows/bindings.txt @@ -1,6 +1,6 @@ ---in crates/libs/metadata/default +--in crates/libs/bindgen/default --out crates/libs/windows/src/lib.rs ---config PACKAGE +--config package --filter Windows diff --git a/docs/readme.md b/docs/readme.md index dc70d39704..f55ff2a082 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -1,6 +1,6 @@ ## Rust for Windows -The [windows](https://crates.io/crates/windows) and [windows-sys](https://crates.io/crates/windows-sys) crates let you call any Windows API past, present, and future using code generated on the fly directly from the [metadata describing the API](https://github.com/microsoft/windows-rs/tree/master/crates/libs/metadata/default) and right into your Rust package where you can call them as if they were just another Rust module. The Rust language projection follows in the tradition established by [C++/WinRT](https://github.com/microsoft/cppwinrt) of building language projections for Windows using standard languages and compilers, providing a natural and idiomatic way for Rust developers to call Windows APIs. +The [windows](https://crates.io/crates/windows) and [windows-sys](https://crates.io/crates/windows-sys) crates let you call any Windows API past, present, and future using code generated on the fly directly from the [metadata describing the API](https://github.com/microsoft/windows-rs/tree/master/crates/libs/bindgen/default) and right into your Rust package where you can call them as if they were just another Rust module. The Rust language projection follows in the tradition established by [C++/WinRT](https://github.com/microsoft/cppwinrt) of building language projections for Windows using standard languages and compilers, providing a natural and idiomatic way for Rust developers to call Windows APIs. * [Getting started](https://kennykerr.ca/rust-getting-started/) * [Samples](https://github.com/microsoft/windows-rs/tree/0.48.0/crates/samples)