scala-native-demangle-0.0.6/.cargo_vcs_info.json 0000644 00000000136 00000000001 0015160 0 ustar {
"git": {
"sha1": "034bf5e003437d3f15bf685311e3146fa93932b3"
},
"path_in_vcs": ""
} scala-native-demangle-0.0.6/.github/workflows/ci.yml 0000644 0000000 0000000 00000000466 10461020230 0020471 0 ustar 0000000 0000000 name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
scala-native-demangle-0.0.6/.gitignore 0000644 0000000 0000000 00000000024 10461020230 0015734 0 ustar 0000000 0000000 /target
/Cargo.lock
scala-native-demangle-0.0.6/Cargo.lock 0000644 00000013700 00000000001 0013134 0 ustar # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anstream"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"
[[package]]
name = "anstyle-parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "clap"
version = "4.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "proc-macro2"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "scala-native-demangle"
version = "0.0.6"
dependencies = [
"clap",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "2.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e02e55d62894af2a08aca894c6577281f76769ba47c94d5756bec8ac6e7373"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
scala-native-demangle-0.0.6/Cargo.toml 0000644 00000001743 00000000001 0013163 0 ustar # 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 = "scala-native-demangle"
version = "0.0.6"
description = "Demangle Scala Native identifiers"
homepage = "https://github.com/indoorvivants/scala-native-demangle-rs"
readme = "README.md"
keywords = [
"scala",
"scala-native",
"demangler",
]
license = "Apache-2.0"
repository = "https://github.com/indoorvivants/scala-native-demangle-rs"
[lib]
name = "scala_native_demangle"
path = "src/lib.rs"
[[example]]
name = "cli"
[dev-dependencies.clap]
version = "4.4.3"
features = ["derive"]
scala-native-demangle-0.0.6/Cargo.toml.orig 0000644 0000000 0000000 00000001152 10461020230 0016636 0 ustar 0000000 0000000 [package]
name = "scala-native-demangle"
version = "0.0.6"
edition = "2021"
license = "Apache-2.0"
description = "Demangle Scala Native identifiers"
homepage = "https://github.com/indoorvivants/scala-native-demangle-rs"
repository = "https://github.com/indoorvivants/scala-native-demangle-rs"
readme = "README.md"
keywords = ["scala", "scala-native", "demangler"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "scala_native_demangle"
path = "src/lib.rs"
[[example]]
name = "cli"
[dev-dependencies]
clap = { version = "4.4.3", features = ["derive"] }
scala-native-demangle-0.0.6/README.md 0000644 0000000 0000000 00000000376 10461020230 0015235 0 ustar 0000000 0000000 ## Scala Native demangler for Rust
Turn mangled Scala Native identifiers into a more readable form.
1. Name mangling rules: https://scala-native.org/en/latest/contrib/mangling.html
2. Scala implementation: https://github.com/indoorvivants/sn-demangler
scala-native-demangle-0.0.6/examples/cli.rs 0000644 0000000 0000000 00000004154 10461020230 0016707 0 ustar 0000000 0000000 use std::{
fs::File,
io::{self, BufRead},
path::Path,
};
use scala_native_demangle::{self, DemanglingConfig};
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Process a file of mangled identifiers, outputting results inline, separating mangled/unmangled names via ` = `
File {
name: String,
#[arg(long)]
debug: bool,
},
Id {
name: String,
#[arg(long)]
debug: bool,
},
}
fn main() {
let cli = Cli::parse();
match &cli.command {
Commands::File { name, debug } => {
if let Ok(lines) = read_lines(name) {
for line in lines {
if let Ok(ip) = line {
match scala_native_demangle::demangle(
&ip,
&DemanglingConfig {
debug: *debug,
..Default::default()
},
) {
Ok(res) => println!("{} = {}", ip, res),
Err(e) => println!("{} ERROR {}", ip, e),
}
}
}
}
}
Commands::Id { name, debug } => {
println!("{}", name);
println!(
"{}",
scala_native_demangle::demangle(
name,
&DemanglingConfig {
debug: *debug,
..Default::default()
}
)
.unwrap()
)
}
}
}
// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines
(filename: P) -> io::Result>>
where
P: AsRef,
{
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
scala-native-demangle-0.0.6/src/lib.rs 0000644 0000000 0000000 00000041664 10461020230 0015666 0 ustar 0000000 0000000 //! Demangle Scala Native identifiers
//!
//! Turn mangled Scala Native identifiers into a more readable form.
//!
//! 1. Name mangling rules: https://scala-native.org/en/latest/contrib/mangling.html
//! 2. Scala implementation: https://github.com/indoorvivants/sn-demangler
pub type DemangleError = String;
pub type ParsingResult = Result;
pub struct DemanglingConfig {
pub collapse_scala_names: bool,
pub debug: bool,
}
static DEFAULT_CONFIG: DemanglingConfig = DemanglingConfig {
collapse_scala_names: true,
debug: false,
};
impl Default for DemanglingConfig {
fn default() -> Self {
DemanglingConfig {
collapse_scala_names: true,
debug: false,
}
}
}
impl DemanglingConfig {
fn log(&self, str: &str) -> () {
if self.debug {
println!("{str}")
}
}
fn log_name(&self, name: &str, str: &str) -> () {
if self.debug {
println!("{name}: {str}")
}
}
}
pub fn demangle(input: &str, config: &DemanglingConfig) -> ParsingResult {
if !input.starts_with("_S") {
return Err("identifier doesn't start with _S".to_string());
} else {
config.log_name("demangle", &input[2..]);
return defn_name(&input[2..], config);
}
}
pub fn demangle_with_defaults(input: &str) -> ParsingResult {
return demangle(input, &DEFAULT_CONFIG);
}
// private sub parsers
// ::=
// T // top-level name
// M // member name
fn defn_name(input: &str, config: &DemanglingConfig) -> ParsingResult {
config.log_name("defn_name", input);
if input.starts_with("T") {
return toplevel_name(&input[1..], config);
} else if input.starts_with("M") {
return member_name(&input[1..], config);
} else {
if input.len() > 0 {
return Err(format!(
"defn_name: unknown name modifier '{}'",
input[0..0].to_string()
));
} else {
return Err("defn_name: unexpectedly empty rest of identifier".to_string());
}
}
}
fn toplevel_name(input: &str, config: &DemanglingConfig) -> ParsingResult {
config.log_name("toplevel_name", input);
return name(input, config).map(|t| t.1);
}
fn member_name(input: &str, config: &DemanglingConfig) -> ParsingResult {
config.log_name("member_name", input);
let (consumed, owner) = name(input, config)?;
let signature = sig_name(&input[consumed..], config);
return signature.and_then(|s| return Ok(format!("{}.{}", owner, s)));
}
// ::=
// F // field name
// R + E // constructor name
// D + E // method name
// P + E // proxy name
// C // c extern name
// G // generated name
// K + E // duplicate name
fn sig_name(input: &str, config: &DemanglingConfig) -> ParsingResult {
config.log_name("sig_name", input);
if input.starts_with("C") || input.starts_with("G") {
return Ok(name(&input[1..], config)?.1);
} else if input.starts_with("I") {
return Ok("".to_string());
} else if input.starts_with("F") {
let (consumed, field_name) = name(&input[1..], config)?;
// return field_name.and_then(|nm| {
let rest = &input[(1 + consumed)..];
return scope(rest, config).map(|sc| format!("{}{}", render_scope(sc), field_name));
// });
} else if input.starts_with("R") {
let type_names = read_type_names(&input[1..], config)?;
return Ok(type_names.1.join(", "));
} else if input.starts_with("K") {
// TODO: basically the same as D case below
let after_tag = &input[1..];
let (consumed, nm) = name(after_tag, config)?;
let after_name = &after_tag[consumed..];
let (_, type_names) = read_type_names(after_name, config)?;
let signature = match type_names.len() {
1 => format!("{}: {}", nm, type_names.join(",")),
n => format!(
"{}({}): {}",
nm,
type_names[0..n - 2].join(","),
type_names.get(n - 1).unwrap_or(&"???".to_string())
),
};
return Ok(signature);
} else if input.starts_with("P") {
// TODO: basically the same as D case below
let after_tag = &input[1..];
let (consumed, nm) = name(after_tag, config)?;
let after_name = &after_tag[consumed..];
let (_, type_names) = read_type_names(after_name, config)?;
let signature = match type_names.len() {
1 => format!("{}: {}", nm, type_names.join(",")),
n => format!(
"{}({}): {}",
nm,
type_names[0..n - 2].join(","),
type_names.get(n - 1).unwrap_or(&"???".to_string())
),
};
return Ok(signature);
} else if input.starts_with("D") {
let after_tag = &input[1..];
let (consumed, nm) = name(after_tag, config)?;
let after_name = &after_tag[consumed..];
let (consumed, type_names) = read_type_names(after_name, config)?;
let after_types = &after_name[consumed + 1..];
config.log_name(
"sig_name:D",
format!("type_names: {type_names:?}, after: {after_types}").as_str(),
);
let sc = scope(&after_types, config)?;
let signature = match type_names.len() {
1 => format!("{}{}: {}", render_scope(sc), nm, type_names.join(",")),
n => format!(
"{}{}({}): {}",
render_scope(sc),
nm,
type_names[0..n - 1].join(","),
type_names.get(n - 1).unwrap_or(&"???".to_string())
),
};
return Ok(signature);
} else {
return Err(format!(
"sig_name: expected to start with F/R/D/P/C/G/K/I, {}",
&input
)
.to_string());
}
}
fn read_type_names(input: &str, config: &DemanglingConfig) -> ParsingResult<(usize, Vec)> {
let mut pos = 0;
let mut result = Vec::new();
while !input[pos..].starts_with("E") {
let (consumed, nm) = type_name(&input[pos..], config)?;
result.push(nm);
pos += consumed;
}
return Ok((pos, result));
}
fn scala_root_name(name: &str, config: &DemanglingConfig) -> String {
if !config.collapse_scala_names {
return format!("scala.{name}");
} else {
return name.to_string();
};
}
fn common_type_name(name: String, config: &DemanglingConfig) -> String {
if !config.collapse_scala_names {
return name;
} else {
let immut = "scala.collection.immutable.";
if name == "java.lang.Object" {
return "Object".to_string();
} else if name == "java.lang.String" {
return "String".to_string();
} else if name == "java.lang.Throwable" {
return "Throwable".to_string();
} else if name.starts_with(immut) {
return name.strip_prefix(immut).unwrap_or(&name).to_string();
// return "Throwable".to_string();
} else {
return name;
}
}
}
// ::=
// v // c vararg
// R _ // c pointer type-name
// R + E // c function type-name
// S + E // c anonymous struct type-name
// A _ // c array type-name
// // signed integer type-name
// ::=
// b // scala.Byte
// s // scala.Short
// i // scala.Int
// j // scala.Long
// z // scala.Boolean
// c // scala.Char
// f // scala.Float
// d // scala.Double
// u // scala.Unit
// l // scala.Null
// n // scala.Nothing
// L // nullable type-name
// A _ // nonnull array type-name
// X // nonnull exact class type-name
// // nonnull class type-name
fn type_name(input: &str, config: &DemanglingConfig) -> ParsingResult<(usize, String)> {
let mut chars = input.chars();
config.log(format!("type_name: {input}").as_str());
let scala_root_namer = |name: &str| scala_root_name(name, config);
let common_type_namer = |name: String| common_type_name(name, config);
let result = match chars.next() {
Some('v') => Ok((1, "".to_string())),
Some('z') => Ok((1, scala_root_namer("Boolean"))),
Some('c') => Ok((1, scala_root_namer("Char"))),
Some('f') => Ok((1, scala_root_namer("Float"))),
Some('d') => Ok((1, scala_root_namer("Double"))),
Some('u') => Ok((1, scala_root_namer("Unit"))),
Some('l') => Ok((1, scala_root_namer("Null"))),
Some('n') => Ok((1, scala_root_namer("Nothing"))),
Some('b') => Ok((1, scala_root_namer("Byte"))),
Some('s') => Ok((1, scala_root_namer("Short"))),
Some('i') => Ok((1, scala_root_namer("Int"))),
Some('j') => Ok((1, scala_root_namer("Long"))),
Some('R') => match chars.next() {
Some('_') => Ok((2, "".to_string())),
Some(c) => Err(format!("type_name: after R expected _, got `{c}` instead").to_string()),
None => Err("type_name: unexpected end of input".to_string()),
},
Some('L') => {
let (consumed, type_name) = nullable_type_name(&input[1..], config)?;
Ok((consumed + 1, common_type_namer(type_name)))
}
Some('A') => {
let (consumed, tn) = type_name(&input[1..], config)?;
let after_type_name = &input[1 + consumed..];
let num = number(after_type_name);
Ok((
consumed + num + 1, /* "_" at the end */
format!("CArray[{}]", tn),
))
}
Some('X') => {
let (consumed, class_type_name) = name(&input[1..], config)?;
Ok((consumed + 1, class_type_name))
}
Some(other) => Err(format!("type_name: unexpected start character `{other}`").to_string()),
None => Err("type_name: unexpected end of input".to_string()),
};
return result;
}
fn number(input: &str) -> usize {
return input.chars().take_while(|c| c.is_digit(10)).count();
}
fn nullable_type_name(input: &str, config: &DemanglingConfig) -> ParsingResult<(usize, String)> {
let mut chars = input.chars();
match chars.next() {
Some('A') => {
let (consumed, ar) = type_name(&input[1..], config)?;
return Ok((consumed + 2, format!("Array[{}]", ar)));
}
Some('X') => {
let (consumed, n) = name(input, config)?;
return Ok((consumed + 1, n));
}
Some(d) if d.is_digit(10) => {
return name(input, config);
}
Some(a) => return Err(format!("nullable_type_name: unexpected start `{a}`")),
None => return Err("nullable_type_name: unexpected end of input".to_string()),
};
}
enum Scope {
Public,
PublicStatic,
Private(String),
PrivateStatic(String),
}
fn render_scope(scope: Scope) -> String {
return match scope {
Scope::Public => "".to_string(),
Scope::PublicStatic => "".to_string(),
Scope::Private(inn) => format!("", inn),
Scope::PrivateStatic(inn) => format!("", inn),
};
}
// ::=
// P // private to defn-name
// O // public
fn scope(input: &str, config: &DemanglingConfig) -> Result {
config.log_name("scope", input);
if input.starts_with("O") {
return Ok(Scope::Public);
} else if input.starts_with("o") {
return Ok(Scope::PublicStatic);
} else if input.starts_with("P") {
return defn_name(&input[1..], config).map(|i| return Scope::Private(i));
} else if input.starts_with("p") {
return defn_name(&input[1..], config).map(|i| return Scope::PrivateStatic(i));
} else {
return Err(format!("scope: cannot read `{}`", input).to_string());
}
}
fn name(input: &str, config: &DemanglingConfig) -> ParsingResult<(usize, String)> {
//println!("name: {}", input);
config.log_name("name", input);
let mut number_end: usize = 0;
for c in input.chars() {
if c.is_digit(10) {
number_end += 1
} else {
break;
}
}
if number_end >= 1 {
let (length, rest) = input.split_at(number_end);
match usize::from_str_radix(length, 10) {
Ok(res) => {
if rest.starts_with("-") {
return Ok((length.len() + 1 + res, rest[1..(1 + res)].to_string()));
} else {
return Ok((length.len() + res, rest[0..res].to_string()));
}
}
Err(_) => {
return Err("name: invalid length".to_string());
}
}
} else {
return Err(format!("name: invalid input `{}`", input.to_string()));
}
}
#[cfg(test)]
mod tests {
use crate::demangle;
fn run(s: &str) -> String {
return demangle(s, &Default::default()).unwrap();
}
fn run_raw(s: &str) -> String {
return demangle(
s,
&crate::DemanglingConfig {
collapse_scala_names: false,
..Default::default()
},
)
.unwrap();
}
#[test]
fn it_works() {
assert_eq!(run("_ST10__dispatch"), "__dispatch");
assert_eq!(
run_raw("_SM42sttp.model.headers.CacheDirective$MinFreshD12productArityiEO"),
"sttp.model.headers.CacheDirective$MinFresh.productArity: scala.Int"
);
assert_eq!(
run("_SM42sttp.model.headers.CacheDirective$MinFreshD12productArityiEO"),
"sttp.model.headers.CacheDirective$MinFresh.productArity: Int"
);
assert_eq!(run_raw("_SM42scala.scalanative.runtime.SymbolFormatter$D10inBounds$1L32scala.scalanative.unsigned.ULongizEPT42scala.scalanative.runtime.SymbolFormatter$"),
"scala.scalanative.runtime.SymbolFormatter$.inBounds$1(scala.scalanative.unsigned.ULong,scala.Int): scala.Boolean");
assert_eq!(run("_SM42scala.scalanative.runtime.SymbolFormatter$D10inBounds$1L32scala.scalanative.unsigned.ULongizEPT42scala.scalanative.runtime.SymbolFormatter$"),
"scala.scalanative.runtime.SymbolFormatter$.inBounds$1(scala.scalanative.unsigned.ULong,Int): Boolean");
assert_eq!(run_raw("_SM41scalaboot.template.scalatemplate$package$D10$anonfun$3L26scalaboot.template.ContextL15scala.Function1L23java.lang.StringBuilderL31scalaboot.template.UnsafeCursorL23scalaboot.template.MoveuEPT41scalaboot.template.scalatemplate$package$"),
"scalaboot.template.scalatemplate$package$.$anonfun$3(scalaboot.template.Context,scala.Function1,java.lang.StringBuilder,scalaboot.template.UnsafeCursor,scalaboot.template.Move): scala.Unit");
assert_eq!(run("_SM41scalaboot.template.scalatemplate$package$D10$anonfun$3L26scalaboot.template.ContextL15scala.Function1L23java.lang.StringBuilderL31scalaboot.template.UnsafeCursorL23scalaboot.template.MoveuEPT41scalaboot.template.scalatemplate$package$"),
"scalaboot.template.scalatemplate$package$.$anonfun$3(scalaboot.template.Context,scala.Function1,java.lang.StringBuilder,scalaboot.template.UnsafeCursor,scalaboot.template.Move): Unit");
assert_eq!(run("_SM33scala.scalanative.unsafe.package$D11fromCStringL28scala.scalanative.unsafe.PtrL24java.nio.charset.CharsetL16java.lang.StringEO"), "scala.scalanative.unsafe.package$.fromCString(scala.scalanative.unsafe.Ptr,java.nio.charset.Charset): String");
assert_eq!(
run("_SM17java.lang.IntegerD7compareiiiEo"),
"java.lang.Integer.compare(Int,Int): Int"
);
assert_eq!(
run("_SM38scala.scalanative.junit.JUnitFrameworkIE"),
"scala.scalanative.junit.JUnitFramework."
);
assert_eq!(run("_SM10fansi.TrieD17$init$$$anonfun$5cLAL10fansi.Trie_L12scala.Tuple2uEpT10fansi.Trie"), "fansi.Trie.$init$$$anonfun$5(Char,Array[fansi.Trie],scala.Tuple2): Unit")
}
}