{"id":13751209,"url":"https://github.com/boj-rs/basm-rs","last_synced_at":"2025-05-09T18:31:05.800Z","repository":{"id":37784533,"uuid":"498301218","full_name":"boj-rs/basm-rs","owner":"boj-rs","description":"Rust 코드를 컴파일한 후 실행 파일을 온라인 채점 환경에 제출할 수 있도록 변환합니다.","archived":false,"fork":false,"pushed_at":"2024-11-07T05:40:30.000Z","size":18142,"stargazers_count":108,"open_issues_count":7,"forks_count":12,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-11-07T06:28:23.859Z","etag":null,"topics":["assembly","c","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boj-rs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-31T11:10:34.000Z","updated_at":"2024-11-07T05:40:34.000Z","dependencies_parsed_at":"2023-01-21T12:16:11.765Z","dependency_job_id":"bd9a723f-9b5e-4d8b-b560-4ba9a932ea6a","html_url":"https://github.com/boj-rs/basm-rs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boj-rs%2Fbasm-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boj-rs%2Fbasm-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boj-rs%2Fbasm-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boj-rs%2Fbasm-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boj-rs","download_url":"https://codeload.github.com/boj-rs/basm-rs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224876989,"owners_count":17384699,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assembly","c","rust"],"created_at":"2024-08-03T09:00:39.025Z","updated_at":"2025-05-09T18:31:05.738Z","avatar_url":"https://github.com/boj-rs.png","language":"Rust","funding_links":[],"categories":["유틸리티"],"sub_categories":["기타"],"readme":"\u003cdiv align=\"center\" style=\"margin-bottom: 1em;\"\u003e\n\n# basm.rs\n\n\u003cimg src=\"./docs/assets/logo.png\" alt=\"basm.rs Logo\" width=300\u003e\u003c/img\u003e\n\n\u003c/div\u003e\n\nbasm.rs는 Rust 코드를 [백준 온라인 저지](https://www.acmicpc.net/)를 비롯한 온라인 저지에 제출 가능한 프로그램으로 성능 저하 없이 변환해 주는 프로젝트입니다.\n\n출력 파일 언어로는 C, Rust, JavaScript (wasm32), HTML을 지원합니다. 단, HTML은 제출용이 아니라 코드 공유를 목적으로 지원됩니다.\n\n\u003e 156KB의 자유를 누리십시오!\n\n## 바로 시작하기\n\n[GitHub Codespaces](https://codespaces.new/byeongkeunahn/basm-rs)에 접속하셔서 Codespace를 생성하시면 Visual Studio Code 창이 열립니다. GitHub 로그인이 필요합니다.\n\n로컬 환경에서 개발하시려면 `사용법` 섹션의 설명을 참고해주세요.\n\n기여를 원하시는 경우 [기여 가이드](CONTRIBUTING.md)를 참고해주세요.\n\n## 소개\n\n**[러스트(Rust)](https://www.rust-lang.org/)는 차세대 프로그래밍 언어로 C/C++보다 우수한 점이 여럿 있는데, 그 중 하나가 패키지 관리 기능입니다.** 러스트에서는 프로젝트 설정 파일(Cargo.toml)에 사용하고자 하는 외부 라이브러리(crate, 크레이트)를 지정하면, 해당 라이브러리의 기능을 아주 쉽게 가져다 쓸 수 있습니다. [crates.io](https://crates.io/), GitHub, 또는 로컬 컴퓨터에 있는 코드를 지정할 수 있어 선택의 폭이 매우 넓습니다. 바퀴를 재발명하지 않고 잘 만들어진 외부 라이브러리를 사용하면 실무에서는 개발 시간을 획기적으로 단축할 수 있으며, 알고리즘 문제 풀이 시에는 구현 시간을 획기적으로 단축하고 핵심 발상에 집중할 수 있습니다. 그렇지만 백준 온라인 저지를 비롯한 대부분의 온라인 저지에서는 아쉽게도 외부 라이브러리의 직접 사용이 지원되지 않습니다.\n\n**basm-rs를 사용하시면 외부 라이브러리를 이용해 알고리즘 문제 풀이를 할 수 있습니다.** basm-rs는 로컬에서 외부 라이브러리를 포함하여 전체 프로젝트를 빌드하여 실행 파일을 생성한 다음, 생성된 실행 파일의 머신 코드(어셈블리 언어)를 템플릿에 적재합니다. 외부 라이브러리를 빌드 시 의존성에 포함하고 결과물로 생성된 머신 코드를 직접 제출하므로, 제출하는 소스 코드에 외부 라이브러리 코드가 포함되어 있습니다. 따라서 백준, 스택, 코드포스\u003csup\u003e1\u003c/sup\u003e, 폴리곤 등 문제 풀이 사이트에서 외부 라이브러리를 자유롭게 사용하실 수 있습니다.\n\n또한, 다음과 같은 편의 기능을 제공합니다.\n- 백준 온라인 저지 등에 제출 시 **채점 결과로 표시되는 메모리 사용량이 줄어듭니다.**\n- **문제 풀이에 사용하기 편리한 입출력 인터페이스 구현이 내장되어 러스트로 문제 풀이를 하기에 편리합니다.** 러스트는 C/C++에 비해 문제 풀이에 필요한 형태의 입출력을 하기에는 다소 불편한 부분이 있는데 이를 해결해줍니다.\n- **러스트로 함수 구현 문제를 풀 수 있습니다.** (예제 참고)\n\n러스트의 풍성한 라이브러리 생태계를 활용하셔서 즐거운 문제 풀이를 하실 수 있기를 바랍니다.\n\n\u003e \u003csup\u003e1\u003c/sup\u003e 코드포스 연습 시에는 사용이 가능하지만 코드포스 대회에서는 오픈 핵 과정의 원활한 진행을 위해 난독화를 금지하는 규정에 따라 현재 사용하실 수 없습니다. 이용에 주의 부탁드립니다.\n\n## 효과\n\n- 입력이 매우 간편하고 직관적입니다.\n\n공백으로 구분된 a와 b를 받아 더한 결과를 출력하는 프로그램은 다음과 같이 작성할 수 있습니다.\n\n```rust\nuse std::io::Read;\nfn main() {\n    let mut s = String::new();\n    std::io::stdin().read_to_string(\u0026mut s).unwrap();\n    let mut input = s.split_whitespace().flat_map(str::parse);\n    let a: i64 = input.next().unwrap();\n    let b: i64 = input.next().unwrap();\n    println!(\"{}\", a + b);\n}\n```\n\n이를 basm에서는 다음과 같이 작성할 수 있습니다.\n\n\u003e basm에서는 `main()` 함수가 반드시 `pub`으로 선언되어야 컴파일이 가능함에 주의해 주세요.\n\n```rust\n// basm/src/solution.rs\nuse basm::platform::io::{Reader, ReaderTrait, Writer, Print};\npub fn main() {\n    let mut reader: Reader = Default::default();\n    let mut writer: Writer = Default::default();\n    let a = reader.i64();\n    let b = reader.i64();\n    writer.println(a + b);\n}\n```\n\n- 표시되는 메모리 사용량이 줄어듭니다.\n  - C의 경우 156KB부터, Rust의 경우 2188KB부터 시작합니다.\n  - 위의 예시 코드는 기본 설정에 따라 입출력 버퍼를 크게 할당합니다. 대부분의 상황에서는 기본 설정이 적절하지만, 156KB 메모리 사용량을 달성하려면 버퍼 크기를 줄여야 합니다. 다음 코드에서는 입출력 버퍼를 각각 128바이트로 설정하여 메모리 사용량을 줄입니다.\n```rust\n// basm/src/solution.rs\nuse basm::platform::io::{Reader, ReaderTrait, Writer};\npub fn main() {\n    let mut reader = Reader::\u003c128\u003e::new();\n    let mut writer = Writer::\u003c128\u003e::new();\n    let a = reader.i64();\n    let b = reader.i64();\n    writer.i64(a + b);\n}\n```\n\n- **외부 crate를 사용할 수 있습니다.**\n\n- **백준 온라인 저지(64비트), 폴리곤(32비트 및 64비트)에서 테스트되었습니다.**\n\n- AVX, AVX2, SSE 등의 SIMD를 사용할 수 있습니다.\n\n- 다양한 최적화 옵션을 선택할 수 있습니다.\n\n- 이미 구현된 자료구조와 알고리즘을 쉽게 가져다 쓸 수 있습니다.\n\n  - Jagged Array (인접 리스트에 사용할 수 있습니다)\n  \n  - Union-Find (by rank / rem algorithm)\n\n  - DFS (매크로)\n\n  - KMP (Iterator)\n\n  - Fenwick Tree\n\n  - Segment Tree\n\n## 사용법\n\n`basm.rs`는 그 자체로 완전한 Rust cargo 프로젝트입니다.\n\n`basm/src/solution.rs` main() 에 원하는 코드를 삽입하시고, 일반적인 cargo 프로젝트와 같은 방식으로 빌드 / 실행할 수 있습니다.\n\n\u003e cargo run 및 cargo run --release로 프로그램을 실행할 수 있고 cargo test나 cargo bench를 이용하여 테스트 및 성능 측정을 할 수 있습니다. 다만 로컬 환경에서 개발이 끝난 후 온라인 저지에 제출할 수 있는 형태로 빌드하기 위해서는 반드시 아래에 설명된 전용 스크립트를 사용해야 합니다.\n\nWindows 환경에서 빌드하는 방법입니다.\n\n* Windows 환경에서의 작동은 Python 3 라이브러리인 `pefile`을 필요로 하므로 `pip install pefile`로 설치하십시오.\n\n* `release-64bit-windows.cmd`를 Windows 64비트 환경에서 실행하면 64비트 환경(백준 온라인 저지, 코드포스 등)에 제출 가능한 C 코드가 출력됩니다.\n\n* `release-64bit-windows-rs.cmd`를 Windows 64비트 환경에서 실행하면 64비트 환경(백준 온라인 저지, 코드포스 등)에 제출 가능한 Rust 코드가 출력됩니다. 생성된 코드는 Windows와 Linux에서 모두 컴파일 가능합니다. 단, Windows에서 컴파일할 경우 DLL 대신 EXE를 생성하기 위해 생성된 코드 맨 앞의 `cdylib`를 `bin`으로 변경하거나 rustc 호출 시 `--crate-type=bin` 옵션을 추가해주세요.\n\n* `release-wasm32.cmd`를 실행하면 제출 가능한 JavaScript (wasm32) 코드가 출력됩니다.\n\n* `release-html.cmd`를 실행하면 입력에 대한 출력을 계산할 수 있는 인터랙티브 HTML 페이지가 출력됩니다.\n\n* VS Code의 `build-release-amd64-submit` Task를 실행하면 릴리즈 모드 빌드 후 64비트 환경에 제출 가능한 C 코드가 VS Code 편집기에서 열립니다.\n\n* VS Code의 `build-release-amd64-rs-submit` Task를 실행하면 릴리즈 모드 빌드 후 64비트 환경에 제출 가능한 Rust 코드가 VS Code 편집기에서 열립니다.\n\n* VS Code의 `build-release-wasm32-submit` Task를 실행하면 릴리즈 모드 빌드 후 제출 가능한 JavaScript (wasm32) 코드가 VS Code 편집기에서 열립니다.\n\nLinux (WSL 포함) 환경에서 빌드하는 방법입니다.\n\n* `release.sh` 또는 `release-64bit.sh`를 실행하면 64비트 환경(백준 온라인 저지, 코드포스 등)에 제출 가능한 C 코드가 출력됩니다.\n\n* `release-32bit.sh`를 실행하면 32비트 환경(코드포스 등)에 제출 가능한 C 코드가 출력됩니다.\n\n* `release-rs.sh`를 실행하면 64비트 리눅스 환경(백준 온라인 저지 등)에 제출 가능한 Rust 코드가 출력됩니다. 생성된 코드를 Windows에서 컴파일하려면 crate type을 `cdylib`에서 `bin`으로 변경해야 합니다.\n\n* Note: C 또는 Rust 코드로 출력하는 shell script에 `--features short` option을 전달하면 짧은 코드가 출력됩니다. 짧은 코드 생성 기능은 템플릿 길이 단축 및 basm-std 내부 구현 최적화를 통해 구현되어 있습니다. `--features short` option을 적용한 빌드는 Windows 및 Linux에서 가능하지만, 생성된 코드는 Linux x64 환경에서만 실행이 가능하고 Windows에서 실행이 불가능합니다. VS Code에서는 `build-release-amd64-short-submit` 및 `build-release-amd64-rs-short-submit` Task를 통해 사용이 가능합니다. 또한, `--features short`를 사용하여 C 또는 Rust 코드로 출력하는 경우 `--no-lzma` 옵션을 사용하여 LZMA 압축을 비활성화할 수 있으며, 코드 길이가 긴 경우 이를 통해 속도 향상이 가능합니다. `--no-lzma` 옵션을 사용하지 않는 경우 LZMA 압축 여부는 생성되는 코드 길이가 실제로 짧아지는지에 따라 결정됩니다.\n\n* `release-wasm32.sh`를 실행하면 제출 가능한 JavaScript (wasm32) 코드가 출력됩니다.\n\n* `release-html.sh`를 실행하면 입력에 대한 출력을 계산할 수 있는 인터랙티브 HTML 페이지가 출력됩니다.\n\n* VS Code의 `build-release-amd64-submit` Task를 실행하면 릴리즈 모드 빌드 후 64비트 환경에 제출 가능한 C 코드가 VS Code 편집기에서 열립니다.\n\n* VS Code의 `build-release-amd64-rs-submit` Task를 실행하면 릴리즈 모드 빌드 후 64비트 환경에 제출 가능한 Rust 코드가 VS Code 편집기에서 열립니다.\n\n* VS Code의 `build-release-wasm32-submit` Task를 실행하면 릴리즈 모드 빌드 후 제출 가능한 JavaScript (wasm32) 코드가 VS Code 편집기에서 열립니다.\n\nmacOS (AArch64) 환경에서 빌드하는 방법입니다.\n\n* `release-64bit-mingw.sh`를 실행하면 64비트 환경(백준 온라인 저지, 코드포스 등)에 제출 가능한 C 코드가 출력됩니다.\n\n* `release-rs-mingw.sh`를 실행하면 64비트 리눅스 환경(백준 온라인 저지 등)에 제출 가능한 Rust 코드가 출력됩니다. 생성된 코드를 Windows에서 컴파일하려면 crate type을 `cdylib`에서 `bin`으로 변경해야 합니다.\n\n* `release-wasm32.sh`를 실행하면 제출 가능한 JavaScript (wasm32) 코드가 출력됩니다.\n\n* `release-html.sh`를 실행하면 입력에 대한 출력을 계산할 수 있는 인터랙티브 HTML 페이지가 출력됩니다.\n\n* VS Code의 `build-release-wasm32-submit` Task를 실행하면 릴리즈 모드 빌드 후 제출 가능한 JavaScript (wasm32) 코드가 VS Code 편집기에서 열립니다.\n\n## 디버깅\n\n\u003e Windows 11 64비트, Windows Subsystems for Linux 2 (WSL2)에서 테스트되었습니다. 다른 환경에서 작동에 문제가 있을 시 이슈를 남겨주세요.\n\n1. Windows 또는 Linux에서 Visual Studio Code를 설치하신 다음, rust-analyzer 확장 및 CodeLLDB 확장을 설치해주세요. WSL을 사용하시는 경우 반드시 WSL 내부에 확장을 설치하셔야 합니다.\n\n2. F5를 눌러 디버깅을 진행해주세요.\n\n3. 디버깅이 완료된 후에는 위의 \"사용법\"에 기술된 대로 `release.sh` 등을 실행하시면 Release 모드로 최종 프로그램을 빌드하실 수 있습니다.\n\n## 주의사항\n\n- Nightly Rust를 요구합니다.\n\n- Python 3을 요구합니다.\n\n- Linux에서 Binutils를 요구합니다.\n\n- Windows 및 macOS에서 Python 3 라이브러리 `pefile`을 요구합니다.\n\n- Windows에서 빌드하기 위해서 Microsoft C/C++ 컴파일러가 필요합니다. 가장 간단한 방법은 최신 버전의 Visual Studio를 설치하는 것입니다. 아래 링크를 참고하시면 도움이 됩니다.\n  - https://learn.microsoft.com/ko-kr/windows/dev-environment/rust/setup\n  - https://rust-lang.github.io/rustup/installation/windows-msvc.html\n\n- macOS에서 빌드하기 위해서 MinGW가 필요합니다. 홈브루(패키지 매니저의 일종)를 설치하신 다음 `brew install mingw-w64`를 통해 설치해주세요.\n\n- `std`를 사용할 수 없습니다. 단, `cargo test` 시에는 `std`를 사용할 수 있습니다.\n\n- `libc`를 사용할 수 없습니다.\n\n## 문제 해결\n\n- 생성되는 코드가 느리다면 Cargo.toml에서 opt-level을 기본값인 \"z\" (크기 우선 최적화)에서 3 (속도 우선 최적화)으로 변경해보세요. 다만 생성되는 코드의 길이가 늘어날 수 있습니다.\n\n- 메모리 할당을 C runtime 없이 구현하기 위해 [dlmalloc](https://github.com/alexcrichton/dlmalloc-rs)이 적용되어 있습니다. 대부분의 경우 잘 작동하지만, 만약 실행시간이나 메모리 사용량이 2-3배 이상 과도하게 증가하는 등의 문제를 겪으신다면 꼭(!) 이슈를 남겨주세요.\n\n- Windows, Linux, macOS에서만 테스트되었습니다. 그 외의 환경에서 문제를 겪으시는 경우 이슈를 남겨주세요.\n\n- Linux 환경에서 빌드하여 출력된 코드를 Windows 환경에서 컴파일하여 실행하는 경우 정상 작동을 보장할 수 없습니다. 이는 Linux 컴파일러가 Windows에서 사용하는 `__chkstk` 메커니즘을 지원하지 않기 때문입니다. Windows 환경에서 컴파일하여 실행해야 하는 경우 가급적 Windows 환경에서 빌드해 주세요. 이것이 어렵다면 하나의 함수 내에서 스택을 한 번에 4KB를 초과하여 이용하지 않도록 주의해주세요. 한편, Windows 환경에서 빌드하여 출력된 코드는 `__chkstk` 메커니즘을 포함하고 있으나 Windows가 아닌 환경에서 실행되는 경우 이를 비활성화하도록 구현되어 있기 때문에 Windows 및 Linux에서 모두 정상 작동이 가능합니다.\n\n- Rust 코드 형태로 빌드한 경우 Windows 환경에서 컴파일하여 실행하기 위해서는 코드 상단에 crate type을 `cdylib`로 지정하는 부분을 제거해 주세요. (코드포스 등)\n\n- 코드 구조 수정으로 인해 Assembly 코드로 변환하는 기능은 지원되지 않습니다.\n\n- 현재 ARM은 macOS 64비트 (`aarch64-apple-darwin`) 한정으로 `cargo run`이 지원됩니다. 단, ARM 32비트는 지원하지 않습니다. 또한, macOS에서 ARM 타겟 제출용 빌드는 불가하며, 홈브루를 통해 `MinGW64`를 설치 후(`brew install mingw-w64`) \"mingw\"로 끝나는 셸 스크립트를 통해 제출용 x86_64 빌드가 가능합니다. 사용상 문제가 있으신 경우 이슈를 남겨주세요.\n\n- 기타 빌드 및 실행 또는 디버깅 등에 문제가 있는 경우 이슈를 남겨주세요.\n\n## 예제: 큰 수 A+B ([BOJ 10757](https://www.acmicpc.net/problem/10757))\n\n이 프로젝트를 다운로드 또는 클론한 다음, 위의 \"주의사항\"에 나열된 대로 Nightly Rust를 셋업합니다.\n\n그런 다음, Cargo.toml의 [dependencies] 항목에 다음을 추가합니다.\n\n```\ndashu = { version = \"0.4.2\", default-features = false }\n```\n\nbasm/src/solution.rs를 다음과 같이 수정합니다.\n\n```rust\nuse basm::platform::io::{Reader, ReaderTrait, Writer, Print};\nuse alloc::string::ToString;\nuse core::str::FromStr;\nuse dashu::Integer;\n\npub fn main() {\n    let mut reader: Reader = Default::default();\n    let mut writer: Writer = Default::default();\n    let a = Integer::from_str(\u0026reader.word()).unwrap();\n    let b = Integer::from_str(\u0026reader.word()).unwrap();\n    let ans = \u0026a + \u0026b;\n    writer.println(ans.to_string());\n}\n```\n\n이제 로컬에서 빌드합니다.\n\n### Windows\n\n다음 스크립트를 실행하면 64비트 환경(백준 온라인 저지 등)에 제출 가능한 C 코드가 출력됩니다.\n\n```\n./release-64bit-windows.cmd \u003e output.c\n```\n\n생성된 코드를 컴파일하여 실행합니다. (이를 실행하는 로컬 환경은 64비트라고 가정하고 있습니다)\n\n```\ncl output.c /F268435456\noutput\n```\n\nMicrosoft C/C++ 컴파일러 `cl`이 `PATH`에 있어야 하며 기타 환경 변수가 잘 설정되어 있어야 컴파일이 문제없이 진행됩니다. 따라서 가급적 `x64 Native Tools Command Prompt for VS 2022` (로컬 환경에 따라 연도는 2022가 아닐 수 있음)에서 실행하는 것이 좋습니다.\n\n### Linux\n\n다음 스크립트를 실행하면 64비트 환경(백준 온라인 저지 등)에 제출 가능한 C 코드가 출력됩니다.\n\n```\n./release-64bit.sh \u003e output.c\n```\n\n생성된 코드를 컴파일하여 실행합니다. (이를 실행하는 로컬 환경은 64비트라고 가정하고 있습니다)\n\n```\ngcc output.c -o output\nchmod +x ./output\n./output\n```\n\n32비트 환경(코드포스, 코드포스 폴리곤 등)에 제출 가능한 C 코드로 빌드하려면 다음과 같이 할 수 있습니다.\n```\n./release-32bit.sh \u003e output-32.c\n```\n\n마찬가지로 생성된 코드를 컴파일하여 실행합니다. (이를 실행하는 로컬 환경은 64비트라고 가정하고 있습니다)\n\n```\ngcc output-32.c -o output-32 -m32\nchmod +x ./output-32\n./output-32\n```\n\n## 예제: 할 수 있다([BOJ 1287](https://www.acmicpc.net/problem/1287))\n\n이 프로젝트를 다운로드 또는 클론한 다음, 위의 \"주의사항\"에 나열된 대로 Nightly Rust를 셋업합니다.\n\n그런 다음, Cargo.toml의 [dependencies] 항목에 다음을 추가합니다.\n\n```\nnom = { version = \"7.1.3\", default-features = false, features = [\"alloc\"] }\ndashu = { version = \"0.4.2\", default-features = false }\n```\n\nbasm/src/solution.rs를 다음과 같이 수정합니다.\n\n\n```rust\nuse basm::platform::io::{Reader, ReaderTrait, Writer, Print};\nuse alloc::string::ToString;\nuse core::str::FromStr;\nuse dashu::Integer;\n\nuse nom::{\n    IResult,\n    branch::alt,\n    bytes::complete::{tag, take_while},\n    character::is_digit,\n    character::complete::one_of,\n    combinator::{all_consuming, map_res},\n    multi::many0,\n    sequence::{delimited, pair},\n};\n\nfn number_literal(input: \u0026str) -\u003e IResult\u003c\u0026str, Integer\u003e {\n    map_res(take_while(|x: char| is_digit(x as u8)), |s: \u0026str| Integer::from_str(s))(input)\n}\nfn op(input: \u0026str) -\u003e IResult\u003c\u0026str, char\u003e {\n    one_of(\"+-*/\")(input)\n}\nfn wrapped(input: \u0026str) -\u003e IResult\u003c\u0026str, Integer\u003e {\n    delimited(tag(\"(\"), expr, tag(\")\"))(input)\n}\nfn number(input: \u0026str) -\u003e IResult\u003c\u0026str, Integer\u003e {\n    alt((number_literal, wrapped))(input)\n}\nfn expr(input: \u0026str) -\u003e IResult\u003c\u0026str, Integer\u003e {\n    map_res(\n        pair(number, many0(pair(op, number))),\n        |x| -\u003e Result\u003cInteger, usize\u003e {\n            let (mut a, mut b) = (Integer::ZERO, x.0);\n            for p in x.1 {\n                match p.0 {\n                    '+' =\u003e { (a, b) = (a + b, p.1); },\n                    '-' =\u003e { (a, b) = (a + b, -p.1); },\n                    '*' =\u003e { b *= p.1; },\n                    '/' =\u003e if p.1 == Integer::ZERO { return Err(1); } else { b /= p.1; },\n                    _ =\u003e unreachable!()\n                }\n            }\n            Ok(a + b)\n        }\n    )(input)\n}\n\npub fn main() {\n    let mut reader: Reader = Default::default();\n    let mut writer: Writer = Default::default();\n    let input = reader.word();\n    if let Ok((_, ans)) = all_consuming(expr)(\u0026input) {\n        writer.println(ans.to_string());\n    } else {\n        writer.println(\"ROCK\");\n    };\n}\n```\n\n이후 실행 과정은 위의 \"큰 수 A+B\"와 동일하게 진행하면 됩니다.\n\n## 예제: 오름세([BOJ 3745](https://www.acmicpc.net/problem/3745))\n\n이 예제는 하나의 입력 파일에 여러 개의 테스트 케이스가 있지만 개수가 따로 주어지지 않을 때 파일의 끝(end-of-file; EOF)을 검출하여 프로그램을 적절히 종료하는 방법을 보여줍니다.\n\n이 프로젝트를 다운로드 또는 클론한 다음, 위의 \"주의사항\"에 나열된 대로 Nightly Rust를 셋업합니다.\n\nbasm/src/solution.rs를 다음과 같이 수정합니다.\n\n```rust\nuse basm::platform::io::{Reader, ReaderTrait, Writer, Print};\nuse core::cmp::max;\npub fn main() {\n    let mut reader: Reader = Default::default();\n    let mut writer: Writer = Default::default();\n    let mut x = [usize::MAX; 100_001]; // x[i] = minimum end-value of \"len \u003e= i\" increasing seq.\n    while !reader.is_eof_skip_whitespace() {\n        let n = reader.usize();\n        let mut ans = 0;\n        x[0] = 0;\n        for i in 0..n {\n            x[i + 1] = usize::MAX;\n            let v = reader.usize();\n            let (mut lo, mut hi) = (0, i);\n            while lo \u003c hi {\n                let mid = (lo + hi + 1) / 2;\n                if x[mid] \u003c v { lo = mid; } else { hi = mid - 1; }\n            }\n            let ans_new = lo + 1;\n            x[ans_new] = v;\n            ans = max(ans, ans_new);\n        }\n        writer.println(ans);\n    }\n}\n```\n\n이후 실행 과정은 위의 \"큰 수 A+B\"와 동일하게 진행하면 됩니다.\n\n## 예제: 정수 N개의 합([BOJ 15596](https://www.acmicpc.net/problem/15596))\n\n이 예제는 basm-rs를 이용해 러스트로 함수 구현 문제를 해결하는 방법을 보여줍니다.\n\n이 프로젝트를 다운로드 또는 클론한 다음, 위의 \"주의사항\"에 나열된 대로 Nightly Rust를 셋업합니다.\n\nbasm/src/solution.rs를 다음과 같이 수정합니다. 이때, main 함수는 모듈이 로드될 때 정확하게 한 번만 실행됩니다. 따라서 필요한 경우 프로그램의 전역 상태를 초기화하는 루틴을 main 함수에 작성해도 됩니다. 만약 main 함수에 작성할 내용이 없더라도 제거하면 컴파일 오류가 발생하므로 빈 함수로 남겨두어야 합니다.\n\n`is_local_env()`는 프로그램이 로컬에서 `cargo run` 등에 의해 실행되고 있으면 true를, 온라인 저지에 제출하기 위해 템플릿에 적재된 경우 false를 반환합니다. 따라서 이를 이용하면 구현한 함수를 콘솔 입출력으로 테스트하고 코드 수정 없이 온라인 저지 제출용으로 빌드할 수 있습니다.\n\n```rust\nuse alloc::vec::Vec;\nuse basm::platform::is_local_env;\nuse basm::platform::io::{Reader, ReaderTrait, Writer, Print};\nuse basm_macro::basm_export;\n\npub fn main() {\n    if is_local_env() {\n        let mut reader: Reader = Default::default();\n        let mut writer: Writer = Default::default();\n        let n = reader.usize();\n        let mut a = Vec::new();\n        for _ in 0..n {\n            a.push(reader.i32());\n        }\n        let ans = sum(\u0026mut a);\n        writer.println(ans);\n    }\n}\n\n#[basm_export]\nfn sum(a: \u0026mut Vec::\u003ci32\u003e) -\u003e i64 {\n    a.iter().map(|\u0026x| x as i64).sum()\n}\n```\n\n함수 구현 문제는 일반 프로그램과는 빌드 방법이 다르며, 출력 형식은 64비트(x86-64) C++ 코드만 지원됩니다.\n\n### Windows\n\n다음 스크립트를 실행하면 64비트 환경(백준 온라인 저지 등)에 제출 가능한 C++ 코드가 출력됩니다.\n\n```\n./release-64bit-windows-fn-impl.cmd \u003e output.cpp\n```\n\n### Linux\n\n다음 스크립트를 실행하면 64비트 환경(백준 온라인 저지 등)에 제출 가능한 C++ 코드가 출력됩니다.\n\n```\n./release-64bit-fn-impl.sh \u003e output.cpp\n```\n\n### 노트\n\n* 함수 구현 문제에서 미리 제공되는 헤더 파일 인클루드(`#include`)를 별도로 추가하지 않아도 채점에 문제가 없도록 내부 코드가 작성되어 있습니다. 만약 오류가 발생하는 경우 이슈를 남겨주세요.\n* 지원되는 자료형은 정수 자료형과 그 포인터, bool 자료형과 그 포인터, Pair, String, Vec입니다. 사용상 문제점 및 추가로 필요하신 기능 등이 있으면 이슈를 남겨주세요.\n\n## 예제: IOI 2016 Aliens([BOJ 20090](https://www.acmicpc.net/problem/20090))\n\n이 예제는 basm-rs의 함수 구현 기능 지원을 이용해 IOI 2016에 출제된 Aliens 문제를 해결하는 예시입니다.\n\n이 프로젝트를 다운로드 또는 클론한 다음, 위의 \"주의사항\"에 나열된 대로 Nightly Rust를 셋업합니다.\n\nbasm/src/solution.rs를 다음과 같이 수정합니다.\n\n```rust\nuse basm::platform::is_local_env;\nuse basm::platform::io::{Reader, ReaderTrait, Writer, Print};\nuse basm_macro::basm_export;\nuse alloc::vec;\nuse alloc::vec::Vec;\n\npub fn main() {\n    if is_local_env() {\n        let mut reader: Reader = Default::default();\n        let mut writer: Writer = Default::default();\n        let n = reader.i32();\n        let m = reader.i32();\n        let k = reader.i32();\n        let (mut r, mut c) = (vec![], vec![]);\n        for _ in 0..n {\n            r.push(reader.i32());\n            c.push(reader.i32());\n        }\n        let ans = take_photos(n, m, k, r, c);\n        writer.println(ans);\n    }\n}\n\nfn deduplicate(n: i32, r: Vec::\u003ci32\u003e, c: Vec::\u003ci32\u003e) -\u003e Vec::\u003c(i32, i32)\u003e {\n    let mut tmp: Vec\u003c(i32, i32)\u003e = (0..n as usize).map(|i| if r[i] \u003c c[i] { (r[i], c[i]) } else { (c[i], r[i]) }).collect();\n    tmp.sort_unstable();\n    let mut out: Vec\u003c(i32, i32)\u003e = vec![];\n    for (rr, cc) in tmp {\n        if !out.is_empty() \u0026\u0026 out[out.len() - 1].0 == rr {\n            out.pop();\n        }\n        if !out.is_empty() \u0026\u0026 out[out.len() - 1].1 \u003e= cc {\n            continue;\n        }\n        out.push((rr, cc));\n    }\n    out\n}\n\n/* minimum hull that expects strictly decreasing slopes */\nstruct ConvexHullTrickLinear {\n    v: Vec::\u003c(i64, i64, usize)\u003e,\n    last_m: i64\n}\n\nimpl ConvexHullTrickLinear {\n    fn new() -\u003e Self {\n        Self { v: vec![], last_m: i64::MAX }\n    }\n    fn push(\u0026mut self, m: i64, b: i64, user_data: usize) {\n        assert!(m \u003c self.last_m);\n        while self.v.len() \u003e= 2 {\n            let (m1, b1, _) = self.v[self.v.len() - 2];\n            let (m2, b2, _) = self.v[self.v.len() - 1];\n            if (b2 - b1) * (m2 - m) \u003c (b - b2) * (m1 - m2) {\n                break;\n            }\n            self.v.pop();\n        }\n        self.v.push((m, b, user_data));\n        self.last_m = m;\n    }\n    fn query(\u0026self, x: i64) -\u003e (i64, usize) {\n        assert!(!self.v.is_empty());\n        let (mut lo, mut hi) = (0, self.v.len() - 1);\n        while lo \u003c hi {\n            let mid = (lo + hi) / 2;\n            let (m1, b1, _) = self.v[mid];\n            let (m2, b2, _) = self.v[mid + 1];\n            if m1 * x + b1 \u003c m2 * x + b2 {\n                hi = mid;\n            } else {\n                lo = mid + 1;\n            }\n        }\n        let (m, b, user_data) = self.v[lo];\n        (m * x + b, user_data)\n    }\n}\n\nfn solve_single(pts: \u0026Vec::\u003c(i32, i32)\u003e, p: i64) -\u003e (i64, usize) {\n    const FACTOR: i64 = 2;\n\n    let l = |i: usize| -\u003e i64 { pts[i - 1].0 as i64 - 1 };\n    let r = |i: usize| -\u003e i64 { pts[i - 1].1 as i64 };\n\n    let n = pts.len();\n    let mut dp = vec![(0, 0)];\n    let mut cht = ConvexHullTrickLinear::new();\n    cht.push(-2 * l(1) * FACTOR, l(1) * l(1) * FACTOR, 0);\n    for i in 1..=n {\n        /* Query CHT */\n        let (val, argmax) = cht.query(r(i));\n        let dp_i = val + r(i) * r(i) * FACTOR;\n        dp.push((dp_i - p, argmax + 1));\n\n        /* Update CHT */\n        if i \u003c n {\n            if l(i+1) \u003c= r(i) {\n                cht.push(-2 * l(i+1) * FACTOR, dp[i].0 - r(i) * r(i) * FACTOR + 2 * l(i+1) * r(i) * FACTOR, dp[i].1);\n            } else {\n                cht.push(-2 * l(i+1) * FACTOR, dp[i].0 + l(i+1) * l(i+1) * FACTOR, dp[i].1);\n            }\n        }\n    }\n    dp[n]\n}\n\n#[basm_export]\nfn take_photos(n: i32, _m: i32, k: i32, r: Vec::\u003ci32\u003e, c: Vec::\u003ci32\u003e) -\u003e i64 {\n    const RANGE: i64 = 1_000_000_000_001;\n\n    let pts = deduplicate(n, r, c);\n    let (mut p_lo, mut p_hi) = (-RANGE, RANGE);\n    while p_lo \u003c p_hi {\n        let p_mid = (p_lo + p_hi + 1 + 2*RANGE) / 2 - RANGE;\n        let p_ans = solve_single(\u0026pts, 2 * p_mid - 1);\n        if p_ans.1 \u003c= k as usize {\n            p_lo = p_mid;\n        } else {\n            p_hi = p_mid - 1;\n        }\n    }\n    let mut p_opt = 2 * p_lo - 1;\n    let ans = solve_single(\u0026pts, p_opt);\n    let mut override_count = false;\n    if p_opt \u003e 0 {\n        p_opt = 0;\n    } else if ans.1 \u003c k as usize {\n        p_opt += 1;\n        override_count = true;\n    }\n    let ans = solve_single(\u0026pts, p_opt);\n    (ans.0 + if override_count { k as i64 } else { ans.1 as i64 } * p_opt) / 2\n}\n```\n\n빌드 및 실행은 이전 함수 구현 예제와 동일합니다. 로컬에서 `cargo run`을 입력하고 아래 테스트 케이스를 입력하면 `25`가 출력되어야 합니다.\n```\n5 7 2\n0 3\n4 4\n4 6\n4 5\n4 6\n```\n\n## 예제: 숫자 야구 F([BOJ 18160](https://www.acmicpc.net/problem/18160))\n\n이 예제는 basm-rs의 함수 구현 기능 지원을 이용해 함수 가져오기(import)를 하는 방법을 보여줍니다.\n\n이 프로젝트를 다운로드 또는 클론한 다음, 위의 \"주의사항\"에 나열된 대로 Nightly Rust를 셋업합니다.\n\nbasm/src/solution.rs를 다음과 같이 수정합니다.\n\n```rust\nuse alloc::{format, string::String, vec::Vec};\nuse basm::serialization::Pair;\nuse basm_macro::{basm_export, basm_import};\npub fn main() {}\n\nbasm_import! {\n    fn guess(b: String) -\u003e Pair::\u003ci32, i32\u003e;\n}\n\nstatic mut ALL: Vec\u003ci32\u003e = Vec::new();\nstatic mut N: i32 = 0;\n\n#[basm_export]\nfn init(_t: i32, n: i32) {\n    unsafe {\n        (*core::ptr::addr_of_mut!(ALL)).clear();\n        N = n;\n        let pow10_n = 10i32.pow(n as u32);\n        'outer: for i in 0..pow10_n {\n            let mut digits = [false; 10];\n            let mut j = i;\n            for _ in 0..n {\n                let d = (j % 10) as usize;\n                if digits[d] {\n                    continue 'outer;\n                }\n                digits[d] = true;\n                j /= 10;\n            }\n            (*core::ptr::addr_of_mut!(ALL)).push(i);\n        }\n    }\n}\n\nfn check(mut x: i32, mut y: i32) -\u003e Pair\u003ci32, i32\u003e {\n    let mut digits_x = [false; 10];\n    let mut digits_y = [false; 10];\n    let mut strikes = 0;\n    let mut balls = 0;\n    unsafe {\n        for _ in 0..N {\n            let d_x = (x % 10) as usize;\n            let d_y = (y % 10) as usize;\n            if d_x == d_y {\n                strikes += 1;\n            }\n            if digits_x[d_y] {\n                balls += 1;\n            }\n            if digits_y[d_x] {\n                balls += 1;\n            }\n            digits_x[d_x] = true;\n            digits_y[d_y] = true;\n            x /= 10;\n            y /= 10;\n        }\n    }\n    Pair::\u003ci32, i32\u003e(strikes, balls)\n}\n\n#[basm_export]\nfn game() {\n    let mut all = unsafe { (*core::ptr::addr_of!(ALL)).clone() };\n    let n = unsafe { N };\n    loop {\n        let query = all[0];\n        let query_str = if n == 3 {\n            format!(\"{:03}\", query)\n        } else {\n            format!(\"{:04}\", query)\n        };\n        let out = guess(query_str);\n        if out == Pair(n, 0) {\n            break;\n        }\n        let mut all_new = Vec::new();\n        for x in all {\n            if check(x, query) == out {\n                all_new.push(x);\n            }\n        }\n        all = all_new;\n    }\n}\n```\n\n빌드 및 실행은 이전 함수 구현 예제와 동일합니다.\n\n## Open Source Attributions\n\n[MINT64 OS](https://github.com/kkamagui/mint64os/blob/master/02.Kernel64/Source/Loader.c)\n```\n/**\n *  file    ApplicationLoader.c\n *  date    2009/12/26\n *  author  kkamagui\n *          Copyright(c)2008 All rights reserved by kkamagui\n *  brief   응용프로그램을 로드하여 실행하는 로더(Loader)에 관련된 함수를 정의한 소스 파일\n */\n(brief in English:\n    source file defining functions for loader that loads and runs applications)\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see \u003chttps://www.gnu.org/licenses/\u003e.\n\n========\n\nThe ELF parsing and relocation routines in basm-rs were adapted\nfrom the following implementation of MINT64OS, licensed under GPLv2+:\n    https://github.com/kkamagui/mint64os/blob/master/02.Kernel64/Source/Loader.c\n\nUnlike all other parts of basm-rs, which are under the MIT license,\nthe files implementing ELF parsing and relocation are exceptionally\nlicensed under GPLv2+ since it is derived from an existing GPLv2+\nimplementation, \"Loader.c\" (see above). Although GPLv2+ mandates\nlicensing the project in its entirety as GPLv2+, the original author\nhas kindly granted us permission to confine the GPLv2+ license to\nthe parts explicitly derived from \"Loader.c\".\n\nThere are currently three files licensed under GPLv2+:\n    scripts/static-pie-elf2bin.py\n    basm-std/src/platform/loader/amd64_elf.rs\n    basm-std/src/platform/loader/i686_elf.rs\n```\n\n[Micro LZMA decoder](https://github.com/ilyakurdyukov/micro-lzmadec)\n```\nCopyright (c) 2022, Ilya Kurdyukov\nAll rights reserved.\n\nMicro LZMA decoder for x86 (static)\nMicro LZMA decoder for x86_64 (static)\n\nThis software is distributed under the terms of the\nCreative Commons Attribution 3.0 License (CC-BY 3.0)\nhttp://creativecommons.org/licenses/by/3.0/\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n```\n\n[dlmalloc-rs](https://github.com/alexcrichton/dlmalloc-rs)\n```\nCopyright (c) 2014 Alex Crichton\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n```\n\n[Go](https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/math/bits/bits.go;l=518)\n```\nCopyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n```\n\n[Rust](https://github.com/rust-lang/rust)\n```\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboj-rs%2Fbasm-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboj-rs%2Fbasm-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboj-rs%2Fbasm-rs/lists"}