summaryrefslogtreecommitdiffstats
path: root/rust/vendor/sawp-flags-derive
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
commita0aa2307322cd47bbf416810ac0292925e03be87 (patch)
tree37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/sawp-flags-derive
parentInitial commit. (diff)
downloadsuricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz
suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/vendor/sawp-flags-derive')
-rw-r--r--rust/vendor/sawp-flags-derive/.cargo-checksum.json1
-rw-r--r--rust/vendor/sawp-flags-derive/Cargo.toml52
-rw-r--r--rust/vendor/sawp-flags-derive/src/lib.rs214
3 files changed, 267 insertions, 0 deletions
diff --git a/rust/vendor/sawp-flags-derive/.cargo-checksum.json b/rust/vendor/sawp-flags-derive/.cargo-checksum.json
new file mode 100644
index 0000000..e6df821
--- /dev/null
+++ b/rust/vendor/sawp-flags-derive/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"fbd349b1231a07a0c1220af261a86b8a558d99a1820f9f074e4fadc8e5059152","src/lib.rs":"fb35a946c3367498d41d96a2eb5a2f17e7b67c62f1ec21fa4b19599a78ecf363"},"package":"49a585d3c22887d23bb06dd602b8ce96c2a716e1fa89beec8bfb49e466f2d643"} \ No newline at end of file
diff --git a/rust/vendor/sawp-flags-derive/Cargo.toml b/rust/vendor/sawp-flags-derive/Cargo.toml
new file mode 100644
index 0000000..2f074f9
--- /dev/null
+++ b/rust/vendor/sawp-flags-derive/Cargo.toml
@@ -0,0 +1,52 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+name = "sawp-flags-derive"
+version = "0.12.1"
+authors = ["Canadian Centre for Cyber Security <sa-sawp@cyber.gc.ca>"]
+include = [
+ "Cargo.toml",
+ "../LICENSE",
+ "../README.md",
+ "src/**/*.rs",
+]
+description = "SAWP BitFlags Handling and Storage Derive Macro"
+homepage = "https://github.com/CybercentreCanada/sawp"
+readme = "README.md"
+keywords = [
+ "bitflags",
+ "bit",
+ "flags",
+ "bitmask",
+ "derive",
+]
+license-file = "LICENSE"
+repository = "https://github.com/CybercentreCanada/sawp"
+
+[package.metadata.release]
+pre-release-replacements = []
+
+[lib]
+proc-macro = true
+
+[dependencies.proc-macro-crate]
+version = "= 1.1.0"
+
+[dependencies.proc-macro2]
+version = "1.0.36"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.syn]
+version = "1.0"
diff --git a/rust/vendor/sawp-flags-derive/src/lib.rs b/rust/vendor/sawp-flags-derive/src/lib.rs
new file mode 100644
index 0000000..fc84f87
--- /dev/null
+++ b/rust/vendor/sawp-flags-derive/src/lib.rs
@@ -0,0 +1,214 @@
+extern crate proc_macro;
+use proc_macro2::{Ident, Span, TokenStream, TokenTree};
+use quote::quote;
+
+#[proc_macro_derive(BitFlags)]
+pub fn derive_sawp_flags(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let ast: syn::DeriveInput = syn::parse(input).unwrap();
+ impl_sawp_flags(&ast).into()
+}
+
+fn impl_sawp_flags(ast: &syn::DeriveInput) -> TokenStream {
+ let name = &ast.ident;
+ let repr = if let Some(repr) = get_repr(ast) {
+ repr
+ } else {
+ panic!("BitFlags enum must have a `repr` attribute with numeric argument");
+ };
+ match &ast.data {
+ syn::Data::Enum(data) => impl_enum_traits(name, &repr, data),
+ _ => panic!("Bitflags is only supported on enums"),
+ }
+}
+
+fn get_repr(ast: &syn::DeriveInput) -> Option<Ident> {
+ ast.attrs.iter().find_map(|attr| {
+ if let Some(path) = attr.path.get_ident() {
+ if path == "repr" {
+ if let Some(tree) = attr.tokens.clone().into_iter().next() {
+ match tree {
+ TokenTree::Group(group) => {
+ if let Some(ident) = group.stream().into_iter().next() {
+ match ident {
+ TokenTree::Ident(ident) => Some(ident),
+ _ => None,
+ }
+ } else {
+ None
+ }
+ }
+ _ => None,
+ }
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ })
+}
+
+fn impl_enum_traits(name: &syn::Ident, repr: &Ident, data: &syn::DataEnum) -> TokenStream {
+ // TODO: compile error when these items are reused.
+ let list_items = data.variants.iter().map(|variant| &variant.ident);
+ let list_all = list_items.clone();
+ let display_items = list_items.clone();
+ let from_str_items = list_items.clone();
+ let from_str_items_str = list_items.clone().map(|variant| {
+ Ident::new(
+ variant.to_string().to_lowercase().as_str(),
+ Span::call_site(),
+ )
+ });
+
+ quote! {
+ impl Flag for #name {
+ type Primitive = #repr;
+
+ const ITEMS: &'static [Self] = &[#(#name::#list_items),*];
+
+ fn bits(self) -> Self::Primitive {
+ self as #repr
+ }
+
+ fn none() -> Flags<Self> {
+ Flags::from_bits(0)
+ }
+
+ fn all() -> Flags<Self> {
+ Flags::from_bits(#(#name::#list_all as Self::Primitive)|*)
+ }
+ }
+
+ impl std::ops::BitOr for #name {
+ type Output = Flags<#name>;
+
+ fn bitor(self, other: Self) -> Self::Output {
+ Flags::from_bits(self.bits() | other.bits())
+ }
+ }
+
+ impl std::ops::BitAnd for #name {
+ type Output = Flags<#name>;
+
+ fn bitand(self, other: Self) -> Self::Output {
+ Flags::from_bits(self.bits() & other.bits())
+ }
+ }
+
+ impl std::ops::BitXor for #name {
+ type Output = Flags<#name>;
+
+ fn bitxor(self, other: Self) -> Self::Output {
+ Flags::from_bits(self.bits() ^ other.bits())
+ }
+ }
+
+ impl std::ops::Not for #name {
+ type Output = Flags<#name>;
+
+ fn not(self) -> Self::Output {
+ Flags::from_bits(!self.bits())
+ }
+ }
+
+ impl std::fmt::Display for #name {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let empty = self.bits() == Self::none().bits();
+ let mut first = true;
+ #(
+ if self.bits() & #name::#display_items.bits() == #name::#display_items.bits() {
+ write!(f, "{}{}", if first { "" } else { " | " }, stringify!(#display_items))?;
+ first = false;
+
+ if empty {
+ return Ok(());
+ }
+ }
+ )*
+
+ if empty {
+ write!(f, "NONE")?;
+ }
+
+ Ok(())
+ }
+ }
+
+ impl std::str::FromStr for #name {
+ type Err = ();
+ fn from_str(val: &str) -> std::result::Result<#name, Self::Err> {
+ match val.to_lowercase().as_str() {
+ #(stringify!(#from_str_items_str) => Ok(#name::#from_str_items),)*
+ _ => Err(()),
+ }
+ }
+ }
+
+ impl PartialEq<Flags<Self>> for #name {
+ fn eq(&self, other: &Flags<Self>) -> bool {
+ self.bits() == other.bits()
+ }
+ }
+
+ impl std::fmt::Binary for #name {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Binary::fmt(&self.bits(), f)
+ }
+ }
+ }
+}
+
+/// BitFlags derive macro tests
+///
+/// `#[derive(BitFlags)]` can't be used here and `impl_sawp_flags`
+/// is being called directly instead.
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_macro_enum() {
+ let input = r#"
+ #[repr(u8)]
+ enum Test {
+ A = 0b0000,
+ B = 0b0001,
+ C = 0b0010,
+ D = 0b0100,
+ }
+ "#;
+ let parsed: syn::DeriveInput = syn::parse_str(input).unwrap();
+ impl_sawp_flags(&parsed);
+ }
+
+ #[test]
+ #[should_panic(expected = "BitFlags enum must have a `repr` attribute")]
+ fn test_macro_repr_panic() {
+ let input = r#"
+ enum Test {
+ A = 0b0000,
+ B = 0b0001,
+ C = 0b0010,
+ D = 0b0100,
+ }
+ "#;
+ let parsed: syn::DeriveInput = syn::parse_str(input).unwrap();
+ impl_sawp_flags(&parsed);
+ }
+
+ #[test]
+ #[should_panic(expected = "Bitflags is only supported on enums")]
+ fn test_macro_not_enum_panic() {
+ let input = r#"
+ #[repr(u8)]
+ struct Test {
+ }
+ "#;
+ let parsed: syn::DeriveInput = syn::parse_str(input).unwrap();
+ impl_sawp_flags(&parsed);
+ }
+}