这条奇怪的线做了什么?

Fre*_*ios 13 rust deobfuscation

一个pull请求已经与锈编译一个新的测试完成.它验证一个奇怪的行可以编译:

fn main() {
    let val = !((|(..):(_,_),__@_|__)((&*"\\",'@')/**/,{})=={&[..=..][..];})//
    ;
    assert!(!val);
}
Run Code Online (Sandbox Code Playgroud)

这条线到底做了什么?

Luk*_*odt 23

让我们分解吧!首先,我重新格式化了这条线,以增加"可读性".

let val = !(
    (
        |(..): (_, _), __@_| __
    )(
        (
            &*"\\", 
            '@'
        ) /**/, 
        {}
    )
    ==
    {
        &[..=..][..];
    }
)//
;
Run Code Online (Sandbox Code Playgroud)

它始于let val =和结束//<newline>;.所以这是一个简单的绑定表单let val = ?v?;.我们来讨论一下?v?:

  • 通过not运算符的否定:!( ?_? )
    • 比较通过==: ?lhs? == ?rhs?
      • ⟨lhs⟩:闭包的函数调用( ?closure? )( ?args? )
        • ⟨closure⟩:闭包定义|?first_param?, ?second_param?| ?body?
          • ⟨first_param⟩:(..): (_, _).此参数具有类型注释,(_, _)意味着它是2元组.模式(通常情况下,您会找到一个名称)是(..)指:元组,但忽略它的所有元素.
          • ⟨second_param⟩:__@_.这是一种通常从匹配绑定中获知的模式:name @ pattern.所以实际模式是_(它不绑定任何东西),并且值通过@名称绑定__(两个下划线,这是一种有效的标识符).
          • ⟨body⟩:__.这只是我们将第二个参数绑定到的标识符.所以封闭基本上相当于|_, x| x.
        • ⟨args⟩:两个参数的列表,其间有内联注释/**/:?first_arg?/**/, ?second_arg?
          • ⟨first_arg⟩:(&*"\\", '@').这只是一个2元组,其中第一个元素是包含反斜杠的字符串,第二个元素是char'@'.第&*一个元素取消了.
          • ⟨second_arg⟩:{}.这是一个具有类型的空块().所以作为第二个论点,一个单位被传递.
      • ⟨rhs⟩:一个带有一个声明的支撑块:{ ?stmt?; }.请注意,这是一个带分号的语句.这意味着结果不会从块返回.而是块返回()就像空块一样{}.
        • ⟨stmt⟩:索引表达式{ &?collection?[?index?] }.
          • ⟨收藏:[..=..].这是一个包含一个元素的数组.的元件是..= ..其是RangeToInclusive其中end的范围内的是RangeFull写入...
          • ⟨index⟩:...这只是RangeFull一次.

总而言之:我们将调用闭包的结果与计算结果的支撑块进行比较().闭包基本上是|_, x| x,我们传递给它的第二个参数是{}(计算结果()),所以整个闭包调用表达式求值为().

这意味着整个事情相当于:

  • let val = !( () == () );,相当于:
  • let val = !( true );,相当于:
  • let val = false;