├── .github ├── dependabot.yml └── workflows │ ├── ci-version.yml │ └── ci.yml ├── examples ├── tuple_structure.rs ├── fake_struct.rs ├── structure.rs ├── additional_unnamed_fields.rs ├── fake_tuple_struct.rs ├── additional_named_fields.rs ├── enum.rs └── enum_with_name.rs ├── Cargo.toml ├── LICENSE ├── rustfmt.toml ├── .gitignore ├── tests ├── sign.rs ├── tuple_structure.rs ├── structure.rs ├── enum.rs └── enum_with_name.rs ├── README.md └── src └── lib.rs /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" -------------------------------------------------------------------------------- /examples/tuple_structure.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | pub struct A(pub u8, pub i16, pub f64); 4 | 5 | impl Debug for A { 6 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 7 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, (.2, "{:.3}", self.2)); 8 | } 9 | } 10 | 11 | fn main() { 12 | let a = A(1, 2, std::f64::consts::PI); 13 | 14 | println!("{:#?}", a); 15 | 16 | /* 17 | A( 18 | 1, 19 | 3.142, 20 | ) 21 | */ 22 | } 23 | -------------------------------------------------------------------------------- /examples/fake_struct.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | pub struct A(pub u8, pub i16, pub f64); 4 | 5 | impl Debug for A { 6 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 7 | debug_helper::impl_debug_for_struct!(A, f, self, let .f1 = self.0, let .f2 = self.1, let .f3 = self.2); 8 | } 9 | } 10 | 11 | fn main() { 12 | let a = A(1, 2, std::f64::consts::PI); 13 | 14 | println!("{:#?}", a); 15 | 16 | /* 17 | A { 18 | f1: 1, 19 | f2: 2, 20 | f3: 3.141592653589793, 21 | } 22 | */ 23 | } 24 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "debug-helper" 3 | version = "0.3.13" 4 | authors = ["Magic Len "] 5 | edition = "2021" 6 | rust-version = "1.56" 7 | repository = "https://github.com/magiclen/debug-helper" 8 | homepage = "https://magiclen.org/debug-helper" 9 | keywords = ["debug", "macro", "declarative", "format", "trait"] 10 | categories = ["no-std", "development-tools::debugging"] 11 | description= "This crate provides declarative macros to help you implement the `Debug` trait manually." 12 | license = "MIT" 13 | include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE"] 14 | 15 | [dependencies] 16 | -------------------------------------------------------------------------------- /examples/structure.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | pub struct A { 4 | pub f1: u8, 5 | pub f2: i16, 6 | pub f3: f64, 7 | } 8 | 9 | impl Debug for A { 10 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 11 | debug_helper::impl_debug_for_struct!(A, f, self, .f1, (.f3, "{:.3}", self.f3)); 12 | } 13 | } 14 | 15 | fn main() { 16 | let a = A { 17 | f1: 1, f2: 2, f3: std::f64::consts::PI 18 | }; 19 | 20 | println!("{:#?}", a); 21 | 22 | /* 23 | A { 24 | f1: 1, 25 | f3: 3.142, 26 | } 27 | */ 28 | } 29 | -------------------------------------------------------------------------------- /examples/additional_unnamed_fields.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | pub struct A(pub u8, pub i16, pub f64); 4 | 5 | impl Debug for A { 6 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 7 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, (.2, "{:.3}", self.2), (.3, "{:.3}", self.0 as f64 + self.1 as f64 + self.2)); 8 | } 9 | } 10 | 11 | fn main() { 12 | let a = A(1, 2, std::f64::consts::PI); 13 | 14 | println!("{:#?}", a); 15 | 16 | /* 17 | A( 18 | 1, 19 | 3.142, 20 | 6.142, 21 | ) 22 | */ 23 | } 24 | -------------------------------------------------------------------------------- /examples/fake_tuple_struct.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | pub struct A { 4 | pub f1: u8, 5 | pub f2: i16, 6 | pub f3: f64, 7 | } 8 | 9 | impl Debug for A { 10 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 11 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, let .0 = self.f1, let .1 = self.f2, let .2 = self.f3); 12 | } 13 | } 14 | 15 | fn main() { 16 | let a = A { 17 | f1: 1, f2: 2, f3: std::f64::consts::PI 18 | }; 19 | 20 | println!("{:#?}", a); 21 | 22 | /* 23 | A( 24 | 1, 25 | 2, 26 | 3.141592653589793, 27 | ) 28 | */ 29 | } 30 | -------------------------------------------------------------------------------- /examples/additional_named_fields.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | pub struct A { 4 | pub f1: u8, 5 | pub f2: i16, 6 | pub f3: f64, 7 | } 8 | 9 | impl Debug for A { 10 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 11 | debug_helper::impl_debug_for_struct!(A, f, self, .f1, (.f3, "{:.3}", self.f3), (.sum, "{:.3}", self.f1 as f64 + self.f2 as f64 + self.f3)); 12 | } 13 | } 14 | 15 | fn main() { 16 | let a = A { 17 | f1: 1, f2: 2, f3: std::f64::consts::PI 18 | }; 19 | 20 | println!("{:#?}", a); 21 | 22 | /* 23 | A { 24 | f1: 1, 25 | f3: 3.142, 26 | sum: 6.142, 27 | } 28 | */ 29 | } 30 | -------------------------------------------------------------------------------- /examples/enum.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | pub enum A { 4 | V1, 5 | V2(u8, i16, f64), 6 | V3 { f1: u8, f2: i16, f3: f64 }, 7 | } 8 | 9 | impl Debug for A { 10 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 11 | debug_helper::impl_debug_for_enum!(A::{V1, (V2(f1, _, f3): (.f1, (.f3, "{:.3}", f3))), {V3{f1, f2: _, f3}: (.f1, (.f3, "{:.3}", f3))}}, f, self); 12 | } 13 | } 14 | 15 | fn main() { 16 | let a = A::V1; 17 | let b = A::V2(1, 2, std::f64::consts::PI); 18 | let c = A::V3 { 19 | f1: 1, f2: 2, f3: std::f64::consts::PI 20 | }; 21 | 22 | println!("{:#?}", a); 23 | println!("{:#?}", b); 24 | println!("{:#?}", c); 25 | 26 | /* 27 | V1 28 | V2( 29 | 1, 30 | 3.142, 31 | ) 32 | V3 { 33 | f1: 1, 34 | f3: 3.142, 35 | } 36 | */ 37 | } 38 | -------------------------------------------------------------------------------- /examples/enum_with_name.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | pub enum A { 4 | V1, 5 | V2(u8, i16, f64), 6 | V3 { f1: u8, f2: i16, f3: f64 }, 7 | } 8 | 9 | impl Debug for A { 10 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 11 | debug_helper::impl_debug_for_enum!({A::V1, (V2(f1, _, f3): (.f1, (.f3, "{:.3}", f3))), {V3{f1, f2: _, f3}: (.f1, (.f3, "{:.3}", f3))}}, f, self); 12 | } 13 | } 14 | 15 | fn main() { 16 | let a = A::V1; 17 | let b = A::V2(1, 2, std::f64::consts::PI); 18 | let c = A::V3 { 19 | f1: 1, f2: 2, f3: std::f64::consts::PI 20 | }; 21 | 22 | println!("{:#?}", a); 23 | println!("{:#?}", b); 24 | println!("{:#?}", c); 25 | 26 | /* 27 | A::V1 28 | A::V2( 29 | 1, 30 | 3.142, 31 | ) 32 | A::V3 { 33 | f1: 1, 34 | f3: 3.142, 35 | } 36 | */ 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 magiclen.org (Ron Li) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/ci-version.yml: -------------------------------------------------------------------------------- 1 | name: CI-version 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" 7 | 8 | env: 9 | CARGO_TERM_COLOR: always 10 | 11 | jobs: 12 | tests: 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | os: 17 | - ubuntu-latest 18 | - macos-latest 19 | - windows-latest 20 | toolchain: 21 | - stable 22 | - nightly 23 | name: Test ${{ matrix.toolchain }} on ${{ matrix.os }} (${{ matrix.features }}) 24 | runs-on: ${{ matrix.os }} 25 | steps: 26 | - uses: actions/checkout@v5 27 | - uses: actions-rust-lang/setup-rust-toolchain@v1 28 | with: 29 | toolchain: ${{ matrix.toolchain }} 30 | - run: cargo test --release ${{ matrix.features }} 31 | - run: cargo doc --release ${{ matrix.features }} 32 | 33 | MSRV: 34 | strategy: 35 | fail-fast: false 36 | matrix: 37 | os: 38 | - ubuntu-latest 39 | - macos-latest 40 | - windows-latest 41 | toolchain: 42 | - 1.56 43 | name: Test ${{ matrix.toolchain }} on ${{ matrix.os }} (${{ matrix.features }}) 44 | runs-on: ${{ matrix.os }} 45 | steps: 46 | - uses: actions/checkout@v5 47 | - uses: actions-rust-lang/setup-rust-toolchain@v1 48 | with: 49 | toolchain: ${{ matrix.toolchain }} 50 | - run: cargo test --release --lib --bins ${{ matrix.features }} -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | CARGO_TERM_COLOR: always 7 | 8 | jobs: 9 | rustfmt: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v5 13 | - uses: actions-rust-lang/setup-rust-toolchain@v1 14 | with: 15 | toolchain: nightly 16 | components: rustfmt 17 | - uses: actions-rust-lang/rustfmt@v1 18 | 19 | clippy: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v5 23 | - uses: actions-rust-lang/setup-rust-toolchain@v1 24 | with: 25 | components: clippy 26 | - run: cargo clippy --all-targets --all-features -- -D warnings 27 | 28 | tests: 29 | strategy: 30 | fail-fast: false 31 | matrix: 32 | os: 33 | - ubuntu-latest 34 | - macos-latest 35 | - windows-latest 36 | toolchain: 37 | - stable 38 | - nightly 39 | features: 40 | - 41 | name: Test ${{ matrix.toolchain }} on ${{ matrix.os }} (${{ matrix.features }}) 42 | runs-on: ${{ matrix.os }} 43 | steps: 44 | - uses: actions/checkout@v5 45 | - uses: actions-rust-lang/setup-rust-toolchain@v1 46 | with: 47 | toolchain: ${{ matrix.toolchain }} 48 | - run: cargo test ${{ matrix.features }} 49 | - run: cargo doc ${{ matrix.features }} 50 | 51 | MSRV: 52 | strategy: 53 | fail-fast: false 54 | matrix: 55 | os: 56 | - ubuntu-latest 57 | - macos-latest 58 | - windows-latest 59 | toolchain: 60 | - 1.56 61 | features: 62 | - 63 | name: Test ${{ matrix.toolchain }} on ${{ matrix.os }} (${{ matrix.features }}) 64 | runs-on: ${{ matrix.os }} 65 | steps: 66 | - uses: actions/checkout@v5 67 | - uses: actions-rust-lang/setup-rust-toolchain@v1 68 | with: 69 | toolchain: ${{ matrix.toolchain }} 70 | - run: cargo test --lib --bins ${{ matrix.features }} -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # array_width = 60 2 | # attr_fn_like_width = 70 3 | binop_separator = "Front" 4 | blank_lines_lower_bound = 0 5 | blank_lines_upper_bound = 1 6 | brace_style = "PreferSameLine" 7 | # chain_width = 60 8 | color = "Auto" 9 | # comment_width = 100 10 | condense_wildcard_suffixes = true 11 | control_brace_style = "AlwaysSameLine" 12 | empty_item_single_line = true 13 | enum_discrim_align_threshold = 80 14 | error_on_line_overflow = false 15 | error_on_unformatted = false 16 | # fn_call_width = 60 17 | fn_params_layout = "Tall" 18 | fn_single_line = false 19 | force_explicit_abi = true 20 | force_multiline_blocks = false 21 | format_code_in_doc_comments = true 22 | doc_comment_code_block_width = 80 23 | format_generated_files = true 24 | format_macro_matchers = true 25 | format_macro_bodies = true 26 | skip_macro_invocations = [] 27 | format_strings = true 28 | hard_tabs = false 29 | hex_literal_case = "Upper" 30 | imports_indent = "Block" 31 | imports_layout = "Mixed" 32 | indent_style = "Block" 33 | inline_attribute_width = 0 34 | match_arm_blocks = true 35 | match_arm_leading_pipes = "Never" 36 | match_block_trailing_comma = true 37 | max_width = 100 38 | merge_derives = true 39 | imports_granularity = "Crate" 40 | newline_style = "Unix" 41 | normalize_comments = false 42 | normalize_doc_attributes = true 43 | overflow_delimited_expr = true 44 | remove_nested_parens = true 45 | reorder_impl_items = true 46 | reorder_imports = true 47 | group_imports = "StdExternalCrate" 48 | reorder_modules = true 49 | short_array_element_width_threshold = 10 50 | # single_line_if_else_max_width = 50 51 | space_after_colon = true 52 | space_before_colon = false 53 | spaces_around_ranges = false 54 | struct_field_align_threshold = 80 55 | struct_lit_single_line = false 56 | # struct_lit_width = 18 57 | # struct_variant_width = 35 58 | tab_spaces = 4 59 | trailing_comma = "Vertical" 60 | trailing_semicolon = true 61 | type_punctuation_density = "Wide" 62 | use_field_init_shorthand = true 63 | use_small_heuristics = "Max" 64 | use_try_shorthand = true 65 | where_single_line = false 66 | wrap_comments = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/intellij+all 2 | 3 | ### Intellij+all ### 4 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 5 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 6 | 7 | # User-specific stuff 8 | .idea/**/workspace.xml 9 | .idea/**/tasks.xml 10 | .idea/**/usage.statistics.xml 11 | .idea/**/dictionaries 12 | .idea/**/shelf 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | .idea/**/dbnavigator.xml 22 | 23 | # Gradle 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # Gradle and Maven with auto-import 28 | # When using Gradle or Maven with auto-import, you should exclude module files, 29 | # since they will be recreated, and may cause churn. Uncomment if using 30 | # auto-import. 31 | # .idea/modules.xml 32 | # .idea/*.iml 33 | # .idea/modules 34 | 35 | # CMake 36 | cmake-build-*/ 37 | 38 | # Mongo Explorer plugin 39 | .idea/**/mongoSettings.xml 40 | 41 | # File-based project format 42 | *.iws 43 | 44 | # IntelliJ 45 | out/ 46 | 47 | # mpeltonen/sbt-idea plugin 48 | .idea_modules/ 49 | 50 | # JIRA plugin 51 | atlassian-ide-plugin.xml 52 | 53 | # Cursive Clojure plugin 54 | .idea/replstate.xml 55 | 56 | # Crashlytics plugin (for Android Studio and IntelliJ) 57 | com_crashlytics_export_strings.xml 58 | crashlytics.properties 59 | crashlytics-build.properties 60 | fabric.properties 61 | 62 | # Editor-based Rest Client 63 | .idea/httpRequests 64 | 65 | ### Intellij+all Patch ### 66 | # Ignores the whole .idea folder and all .iml files 67 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 68 | 69 | .idea/ 70 | 71 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 72 | 73 | *.iml 74 | modules.xml 75 | .idea/misc.xml 76 | *.ipr 77 | 78 | 79 | # End of https://www.gitignore.io/api/intellij+all 80 | 81 | 82 | ### Rust ### 83 | # Generated by Cargo 84 | # will have compiled files and executables 85 | /target/ 86 | 87 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 88 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 89 | Cargo.lock 90 | 91 | # These are backup files generated by rustfmt 92 | **/*.rs.bk 93 | 94 | 95 | # End of https://www.gitignore.io/api/rust 96 | -------------------------------------------------------------------------------- /tests/sign.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | #[test] 4 | fn signed_values() { 5 | #[allow(dead_code)] 6 | #[derive(Debug)] 7 | struct Inner { 8 | f1: u32, 9 | f2: i64, 10 | } 11 | 12 | struct MyStruct { 13 | f1: u8, 14 | f2: i16, 15 | f3: f64, 16 | f4: Inner, 17 | } 18 | 19 | impl Debug for MyStruct { 20 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 21 | debug_helper::impl_debug_for_struct!(MyStruct, f, self, .f1, .f2, .f3, .f4); 22 | } 23 | } 24 | 25 | let my_struct = MyStruct { 26 | f1: 1, 27 | f2: -2, 28 | f3: 3.0, 29 | f4: Inner { 30 | f1: 4, f2: -5 31 | }, 32 | }; 33 | 34 | assert_eq!( 35 | "MyStruct { f1: +1, f2: -2, f3: +3.0, f4: Inner { f1: +4, f2: -5 } }", 36 | format!("{:+?}", my_struct) 37 | ); 38 | assert_eq!("MyStruct {\n f1: +1,\n f2: -2,\n f3: +3.0,\n f4: Inner {\n f1: +4,\n f2: -5,\n },\n}", format!("{:+#?}", my_struct)); 39 | } 40 | 41 | #[test] 42 | fn zero_values() { 43 | #[allow(dead_code)] 44 | #[derive(Debug)] 45 | struct Inner { 46 | f1: u32, 47 | f2: i64, 48 | } 49 | 50 | struct MyStruct { 51 | f1: u8, 52 | f2: i16, 53 | f3: f64, 54 | f4: Inner, 55 | } 56 | 57 | impl Debug for MyStruct { 58 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 59 | debug_helper::impl_debug_for_struct!(MyStruct, f, self, .f1, .f2, .f3, .f4); 60 | } 61 | } 62 | 63 | let my_struct = MyStruct { 64 | f1: 1, 65 | f2: -2, 66 | f3: 3.0, 67 | f4: Inner { 68 | f1: 4, f2: -5 69 | }, 70 | }; 71 | 72 | assert_eq!( 73 | "MyStruct { f1: 00001, f2: -0002, f3: 003.0, f4: Inner { f1: 00004, f2: -0005 } }", 74 | format!("{:05?}", my_struct) 75 | ); 76 | assert_eq!( 77 | "MyStruct { f1: 00001, f2: 000-2, f3: 003.0, f4: Inner { f1: 00004, f2: 000-5 } }", 78 | format!("{:0>5?}", my_struct) 79 | ); 80 | assert_eq!( 81 | "MyStruct { f1: +0001, f2: -0002, f3: +03.0, f4: Inner { f1: +0004, f2: -0005 } }", 82 | format!("{:+05?}", my_struct) 83 | ); 84 | assert_eq!( 85 | "MyStruct { f1: 000+1, f2: 000-2, f3: 0+3.0, f4: Inner { f1: 000+4, f2: 000-5 } }", 86 | format!("{:0>+5?}", my_struct) 87 | ); 88 | assert_eq!( 89 | "MyStruct {\n f1: 00001,\n f2: -0002,\n f3: 003.0,\n f4: Inner {\n f1: \ 90 | 00004,\n f2: -0005,\n },\n}", 91 | format!("{:#05?}", my_struct) 92 | ); 93 | assert_eq!( 94 | "MyStruct {\n f1: 00001,\n f2: 000-2,\n f3: 003.0,\n f4: Inner {\n f1: \ 95 | 00004,\n f2: 000-5,\n },\n}", 96 | format!("{:0>#5?}", my_struct) 97 | ); 98 | assert_eq!( 99 | "MyStruct {\n f1: +0001,\n f2: -0002,\n f3: +03.0,\n f4: Inner {\n f1: \ 100 | +0004,\n f2: -0005,\n },\n}", 101 | format!("{:+#05?}", my_struct) 102 | ); 103 | assert_eq!( 104 | "MyStruct {\n f1: 000+1,\n f2: 000-2,\n f3: 0+3.0,\n f4: Inner {\n f1: \ 105 | 000+4,\n f2: 000-5,\n },\n}", 106 | format!("{:0>+#5?}", my_struct) 107 | ); 108 | } 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Debug Helper 2 | ==================== 3 | 4 | [![CI](https://github.com/magiclen/debug-helper/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/debug-helper/actions/workflows/ci.yml) 5 | 6 | This crate provides declarative macros to help you implement the `Debug` trait manually. 7 | 8 | Instead of this crate, in most cases, you can use the [`educe`](https://crates.io/crates/educe) crate to implement the `Debug` trait. 9 | 10 | ## Examples 11 | 12 | For structs, 13 | 14 | ```rust 15 | use std::fmt::{self, Formatter, Debug}; 16 | 17 | pub struct A { 18 | pub f1: u8, 19 | pub f2: i16, 20 | pub f3: f64, 21 | } 22 | 23 | impl Debug for A { 24 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 25 | debug_helper::impl_debug_for_struct!(A, f, self, .f1, (.f3, "{:.3}", self.f3)); 26 | } 27 | } 28 | 29 | let a = A { 30 | f1: 1, 31 | f2: 2, 32 | f3: std::f64::consts::PI, 33 | }; 34 | 35 | println!("{:#?}", a); 36 | 37 | /* 38 | A { 39 | f1: 1, 40 | f3: 3.142, 41 | } 42 | */ 43 | ``` 44 | 45 | For tuple structs, 46 | 47 | ```rust 48 | use std::fmt::{self, Formatter, Debug}; 49 | 50 | pub struct A(pub u8, pub i16, pub f64); 51 | 52 | impl Debug for A { 53 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 54 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, (.2, "{:.3}", self.2)); 55 | } 56 | } 57 | 58 | let a = A(1, 2, std::f64::consts::PI); 59 | 60 | println!("{:#?}", a); 61 | 62 | /* 63 | A( 64 | 1, 65 | 3.142, 66 | ) 67 | */ 68 | ``` 69 | 70 | For enums (without the enum name), 71 | 72 | ```rust 73 | use std::fmt::{self, Formatter, Debug}; 74 | 75 | pub enum A { 76 | V1, 77 | V2(u8, i16, f64), 78 | V3 { 79 | f1: u8, 80 | f2: i16, 81 | f3: f64, 82 | }, 83 | } 84 | 85 | impl Debug for A { 86 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 87 | debug_helper::impl_debug_for_enum!(A::{V1, (V2(f1, _, f3): (.f1, (.f3, "{:.3}", f3))), {V3{f1, f2: _, f3}: (.f1, (.f3, "{:.3}", f3))}}, f, self); 88 | } 89 | } 90 | 91 | let a = A::V1; 92 | let b = A::V2(1, 2, std::f64::consts::PI); 93 | let c = A::V3{ 94 | f1: 1, 95 | f2: 2, 96 | f3: std::f64::consts::PI, 97 | }; 98 | 99 | println!("{:#?}", a); 100 | println!("{:#?}", b); 101 | println!("{:#?}", c); 102 | 103 | /* 104 | V1 105 | V2( 106 | 1, 107 | 3.142, 108 | ) 109 | V3 { 110 | f1: 1, 111 | f3: 3.142, 112 | } 113 | */ 114 | ``` 115 | 116 | For enums (with the enum name), 117 | 118 | ```rust 119 | use std::fmt::{self, Formatter, Debug}; 120 | 121 | pub enum A { 122 | V1, 123 | V2(u8, i16, f64), 124 | V3 { 125 | f1: u8, 126 | f2: i16, 127 | f3: f64, 128 | }, 129 | } 130 | 131 | impl Debug for A { 132 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 133 | debug_helper::impl_debug_for_enum!({A::V1, (V2(f1, _, f3): (.f1, (.f3, "{:.3}", f3))), {V3{f1, f2: _, f3}: (.f1, (.f3, "{:.3}", f3))}}, f, self); 134 | } 135 | } 136 | 137 | let a = A::V1; 138 | let b = A::V2(1, 2, std::f64::consts::PI); 139 | let c = A::V3{ 140 | f1: 1, 141 | f2: 2, 142 | f3: std::f64::consts::PI, 143 | }; 144 | 145 | println!("{:#?}", a); 146 | println!("{:#?}", b); 147 | println!("{:#?}", c); 148 | 149 | /* 150 | A::V1 151 | A::V2( 152 | 1, 153 | 3.142, 154 | ) 155 | A::V3 { 156 | f1: 1, 157 | f3: 3.142, 158 | } 159 | */ 160 | ``` 161 | 162 | 163 | 164 | Ghost fields, 165 | 166 | ```rust 167 | use std::fmt::{self, Formatter, Debug}; 168 | 169 | pub struct A { 170 | pub f1: u8, 171 | pub f2: i16, 172 | pub f3: f64, 173 | } 174 | 175 | impl Debug for A { 176 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 177 | debug_helper::impl_debug_for_struct!(A, f, self, .f1, (.f3, "{:.3}", self.f3), (.sum, "{:.3}", self.f1 as f64 + self.f2 as f64 + self.f3)); 178 | } 179 | } 180 | 181 | let a = A { 182 | f1: 1, 183 | f2: 2, 184 | f3: std::f64::consts::PI, 185 | }; 186 | 187 | println!("{:#?}", a); 188 | 189 | /* 190 | A { 191 | f1: 1, 192 | f3: 3.142, 193 | sum: 6.142, 194 | } 195 | */ 196 | ``` 197 | 198 | ```rust 199 | use std::fmt::{self, Formatter, Debug}; 200 | 201 | pub struct A(pub u8, pub i16, pub f64); 202 | 203 | impl Debug for A { 204 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 205 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, (.2, "{:.3}", self.2), (.3, "{:.3}", self.0 as f64 + self.1 as f64 + self.2)); 206 | } 207 | } 208 | 209 | let a = A(1, 2, std::f64::consts::PI); 210 | 211 | println!("{:#?}", a); 212 | 213 | /* 214 | A( 215 | 1, 216 | 3.142, 217 | 6.142, 218 | ) 219 | */ 220 | ``` 221 | 222 | Fake structs, 223 | 224 | ```rust 225 | use std::fmt::{self, Formatter, Debug}; 226 | 227 | pub struct A(pub u8, pub i16, pub f64); 228 | 229 | impl Debug for A { 230 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 231 | debug_helper::impl_debug_for_struct!(A, f, self, let .f1 = self.0, let .f2 = self.1, let .f3 = self.2); 232 | } 233 | } 234 | 235 | let a = A(1, 2, std::f64::consts::PI); 236 | 237 | println!("{:#?}", a); 238 | 239 | /* 240 | A { 241 | f1: 1, 242 | f2: 2, 243 | f3: 3.141592653589793, 244 | } 245 | */ 246 | ``` 247 | 248 | Fake tuple structs, 249 | 250 | ```rust 251 | use std::fmt::{self, Formatter, Debug}; 252 | 253 | pub struct A { 254 | pub f1: u8, 255 | pub f2: i16, 256 | pub f3: f64, 257 | } 258 | 259 | impl Debug for A { 260 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 261 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, let .0 = self.f1, let .1 = self.f2, let .2 = self.f3); 262 | } 263 | } 264 | 265 | let a = A { 266 | f1: 1, 267 | f2: 2, 268 | f3: std::f64::consts::PI, 269 | }; 270 | 271 | println!("{:#?}", a); 272 | 273 | /* 274 | A( 275 | 1, 276 | 2, 277 | 3.141592653589793, 278 | ) 279 | */ 280 | ``` 281 | 282 | ## TODO 283 | 284 | 1. Fake enum struct variants and tuple variants. 285 | 1. Enum variants can be renamed. 286 | 287 | ## Crates.io 288 | 289 | https://crates.io/crates/debug-helper 290 | 291 | ## Documentation 292 | 293 | https://docs.rs/debug-helper 294 | 295 | ## License 296 | 297 | [MIT](LICENSE) -------------------------------------------------------------------------------- /tests/tuple_structure.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | #[test] 4 | #[allow(dead_code)] 5 | fn unit() { 6 | #[derive(Debug)] 7 | struct Inner { 8 | f1: u8, 9 | f2: u8, 10 | } 11 | 12 | struct Outer(f64, Inner); 13 | 14 | impl Debug for Outer { 15 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 16 | debug_helper::impl_debug_for_tuple_struct!(Outer, f, self); 17 | } 18 | } 19 | 20 | let outer = Outer(1.23456789, Inner { 21 | f1: 5, f2: 10 22 | }); 23 | 24 | assert_eq!("Outer", format!("{:?}", outer)); 25 | assert_eq!("Outer", format!("{:#?}", outer)); 26 | assert_eq!("Outer", format!("{:010.2?}", outer)); 27 | assert_eq!("Outer", format!("{:0>10.2?}", outer)); 28 | assert_eq!("Outer", format!("{:?^10.2?}", outer)); 29 | assert_eq!("Outer", format!("{:#<10.2?}", outer)); 30 | assert_eq!("Outer", format!("{:#<#10.2?}", outer)); 31 | } 32 | 33 | #[test] 34 | #[allow(dead_code)] 35 | fn unit_renamed() { 36 | #[derive(Debug)] 37 | struct Inner { 38 | f1: u8, 39 | f2: u8, 40 | } 41 | 42 | struct Outer(f64, Inner); 43 | 44 | impl Debug for Outer { 45 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 46 | debug_helper::impl_debug_for_tuple_struct!(A, f, self); 47 | } 48 | } 49 | 50 | let outer = Outer(1.23456789, Inner { 51 | f1: 5, f2: 10 52 | }); 53 | 54 | assert_eq!("A", format!("{:?}", outer)); 55 | assert_eq!("A", format!("{:#?}", outer)); 56 | assert_eq!("A", format!("{:010.2?}", outer)); 57 | assert_eq!("A", format!("{:0>10.2?}", outer)); 58 | assert_eq!("A", format!("{:?^10.2?}", outer)); 59 | assert_eq!("A", format!("{:#<10.2?}", outer)); 60 | assert_eq!("A", format!("{:#<#10.2?}", outer)); 61 | } 62 | 63 | #[test] 64 | #[allow(dead_code)] 65 | fn one_field_primitive() { 66 | #[derive(Debug)] 67 | struct Inner { 68 | f1: u8, 69 | f2: u8, 70 | } 71 | 72 | struct Outer(f64, Inner); 73 | 74 | impl Debug for Outer { 75 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 76 | debug_helper::impl_debug_for_tuple_struct!(Outer, f, self, .0); 77 | } 78 | } 79 | 80 | let outer = Outer(1.23456789, Inner { 81 | f1: 5, f2: 10 82 | }); 83 | 84 | assert_eq!("Outer(1.23456789)", format!("{:?}", outer)); 85 | assert_eq!("Outer(\n 1.23456789,\n)", format!("{:#?}", outer)); 86 | assert_eq!("Outer(0000001.23)", format!("{:010.2?}", outer)); 87 | assert_eq!("Outer(0000001.23)", format!("{:0>10.2?}", outer)); 88 | assert_eq!("Outer(???1.23???)", format!("{:?^10.2?}", outer)); 89 | assert_eq!("Outer(1.23######)", format!("{:#<10.2?}", outer)); 90 | assert_eq!("Outer(\n 1.23######,\n)", format!("{:#<#10.2?}", outer)); 91 | } 92 | 93 | #[test] 94 | #[allow(dead_code)] 95 | fn one_field_nested() { 96 | #[derive(Debug)] 97 | struct Inner { 98 | f1: u8, 99 | f2: u8, 100 | } 101 | 102 | struct Outer(f64, Inner); 103 | 104 | impl Debug for Outer { 105 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 106 | debug_helper::impl_debug_for_tuple_struct!(Outer, f, self, .1); 107 | } 108 | } 109 | 110 | let outer = Outer(1.23456789, Inner { 111 | f1: 5, f2: 10 112 | }); 113 | 114 | assert_eq!("Outer(Inner { f1: 5, f2: 10 })", format!("{:?}", outer)); 115 | assert_eq!( 116 | "Outer(\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 117 | format!("{:#?}", outer) 118 | ); 119 | assert_eq!("Outer(Inner { f1: 0000000005, f2: 0000000010 })", format!("{:010.2?}", outer)); 120 | assert_eq!("Outer(Inner { f1: 0000000005, f2: 0000000010 })", format!("{:0>10.2?}", outer)); 121 | assert_eq!("Outer(Inner { f1: ????5?????, f2: ????10???? })", format!("{:?^10.2?}", outer)); 122 | assert_eq!("Outer(Inner { f1: 5#########, f2: 10######## })", format!("{:#<10.2?}", outer)); 123 | assert_eq!( 124 | "Outer(\n Inner {\n f1: 5#########,\n f2: 10########,\n },\n)", 125 | format!("{:#<#10.2?}", outer) 126 | ); 127 | } 128 | 129 | #[test] 130 | fn all_renamed() { 131 | #[allow(dead_code)] 132 | #[derive(Debug)] 133 | struct Inner { 134 | f1: u8, 135 | f2: u8, 136 | } 137 | 138 | struct Outer(f64, Inner); 139 | 140 | impl Debug for Outer { 141 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 142 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, .1); 143 | } 144 | } 145 | 146 | let outer = Outer(1.23456789, Inner { 147 | f1: 5, f2: 10 148 | }); 149 | 150 | assert_eq!("A(1.23456789, Inner { f1: 5, f2: 10 })", format!("{:?}", outer)); 151 | assert_eq!( 152 | "A(\n 1.23456789,\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 153 | format!("{:#?}", outer) 154 | ); 155 | assert_eq!( 156 | "A(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 157 | format!("{:010.2?}", outer) 158 | ); 159 | assert_eq!( 160 | "A(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 161 | format!("{:0>10.2?}", outer) 162 | ); 163 | assert_eq!( 164 | "A(???1.23???, Inner { f1: ????5?????, f2: ????10???? })", 165 | format!("{:?^10.2?}", outer) 166 | ); 167 | assert_eq!( 168 | "A(1.23######, Inner { f1: 5#########, f2: 10######## })", 169 | format!("{:#<10.2?}", outer) 170 | ); 171 | assert_eq!( 172 | "A(\n 1.23######,\n Inner {\n f1: 5#########,\n f2: 10########,\n \ 173 | },\n)", 174 | format!("{:#<#10.2?}", outer) 175 | ); 176 | } 177 | 178 | #[test] 179 | #[allow(dead_code)] 180 | fn custom_fmt() { 181 | #[derive(Debug)] 182 | struct Inner { 183 | f1: u8, 184 | f2: u8, 185 | } 186 | 187 | struct Intruder { 188 | s: &'static str, 189 | } 190 | 191 | struct Outer(f64, Inner, Intruder); 192 | 193 | impl Debug for Outer { 194 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 195 | debug_helper::impl_debug_for_tuple_struct!(Outer, f, self, (.0, "number"), .1, (.2, "{}", self.2.s)); 196 | } 197 | } 198 | 199 | let outer = Outer( 200 | 1.23456789, 201 | Inner { 202 | f1: 5, f2: 10 203 | }, 204 | Intruder { 205 | s: "Hi" 206 | }, 207 | ); 208 | 209 | assert_eq!("Outer(number, Inner { f1: 5, f2: 10 }, Hi)", format!("{:?}", outer)); 210 | assert_eq!( 211 | "Outer(\n number,\n Inner {\n f1: 5,\n f2: 10,\n },\n Hi,\n)", 212 | format!("{:#?}", outer) 213 | ); 214 | assert_eq!( 215 | "Outer(number, Inner { f1: 0000000005, f2: 0000000010 }, Hi)", 216 | format!("{:010.2?}", outer) 217 | ); 218 | assert_eq!( 219 | "Outer(number, Inner { f1: 0000000005, f2: 0000000010 }, Hi)", 220 | format!("{:0>10.2?}", outer) 221 | ); 222 | assert_eq!( 223 | "Outer(number, Inner { f1: ????5?????, f2: ????10???? }, Hi)", 224 | format!("{:?^10.2?}", outer) 225 | ); 226 | assert_eq!( 227 | "Outer(number, Inner { f1: 5#########, f2: 10######## }, Hi)", 228 | format!("{:#<10.2?}", outer) 229 | ); 230 | assert_eq!( 231 | "Outer(\n number,\n Inner {\n f1: 5#########,\n f2: 10########,\n \ 232 | },\n Hi,\n)", 233 | format!("{:#<#10.2?}", outer) 234 | ); 235 | } 236 | 237 | #[test] 238 | fn additional_fields() { 239 | #[allow(dead_code)] 240 | #[derive(Debug)] 241 | struct Inner { 242 | f1: u8, 243 | f2: u8, 244 | } 245 | 246 | struct Outer(f64, Inner); 247 | 248 | impl Debug for Outer { 249 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 250 | debug_helper::impl_debug_for_tuple_struct!(Outer, f, self, .0, .1, (.2, "Hi")); 251 | } 252 | } 253 | 254 | let outer = Outer(1.23456789, Inner { 255 | f1: 5, f2: 10 256 | }); 257 | 258 | assert_eq!("Outer(1.23456789, Inner { f1: 5, f2: 10 }, Hi)", format!("{:?}", outer)); 259 | assert_eq!( 260 | "Outer(\n 1.23456789,\n Inner {\n f1: 5,\n f2: 10,\n },\n Hi,\n)", 261 | format!("{:#?}", outer) 262 | ); 263 | assert_eq!( 264 | "Outer(0000001.23, Inner { f1: 0000000005, f2: 0000000010 }, Hi)", 265 | format!("{:010.2?}", outer) 266 | ); 267 | assert_eq!( 268 | "Outer(0000001.23, Inner { f1: 0000000005, f2: 0000000010 }, Hi)", 269 | format!("{:0>10.2?}", outer) 270 | ); 271 | assert_eq!( 272 | "Outer(???1.23???, Inner { f1: ????5?????, f2: ????10???? }, Hi)", 273 | format!("{:?^10.2?}", outer) 274 | ); 275 | assert_eq!( 276 | "Outer(1.23######, Inner { f1: 5#########, f2: 10######## }, Hi)", 277 | format!("{:#<10.2?}", outer) 278 | ); 279 | assert_eq!("Outer(\n 1.23######,\n Inner {\n f1: 5#########,\n f2: 10########,\n },\n Hi,\n)", format!("{:#<#10.2?}", outer)); 280 | } 281 | 282 | #[test] 283 | #[allow(dead_code)] 284 | fn fake_tuple_struct() { 285 | #[derive(Debug)] 286 | struct Inner { 287 | f1: u8, 288 | f2: u8, 289 | } 290 | 291 | struct Outer { 292 | f1: f64, 293 | f2: Inner, 294 | } 295 | 296 | impl Debug for Outer { 297 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 298 | debug_helper::impl_debug_for_tuple_struct!(Outer, f, self, let .0 = self.f1); 299 | } 300 | } 301 | 302 | let outer = Outer { 303 | f1: 1.23456789, 304 | f2: Inner { 305 | f1: 5, f2: 10 306 | }, 307 | }; 308 | 309 | assert_eq!("Outer(1.23456789)", format!("{:?}", outer)); 310 | assert_eq!("Outer(\n 1.23456789,\n)", format!("{:#?}", outer)); 311 | assert_eq!("Outer(0000001.23)", format!("{:010.2?}", outer)); 312 | assert_eq!("Outer(0000001.23)", format!("{:0>10.2?}", outer)); 313 | assert_eq!("Outer(???1.23???)", format!("{:?^10.2?}", outer)); 314 | assert_eq!("Outer(1.23######)", format!("{:#<10.2?}", outer)); 315 | assert_eq!("Outer(\n 1.23######,\n)", format!("{:#<#10.2?}", outer)); 316 | } 317 | -------------------------------------------------------------------------------- /tests/structure.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | #[test] 4 | #[allow(dead_code)] 5 | fn unit() { 6 | #[derive(Debug)] 7 | struct Inner { 8 | f1: u8, 9 | f2: u8, 10 | } 11 | 12 | struct Outer { 13 | f1: f64, 14 | f2: Inner, 15 | } 16 | 17 | impl Debug for Outer { 18 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 19 | debug_helper::impl_debug_for_struct!(Outer, f, self); 20 | } 21 | } 22 | 23 | let outer = Outer { 24 | f1: 1.23456789, 25 | f2: Inner { 26 | f1: 5, f2: 10 27 | }, 28 | }; 29 | 30 | assert_eq!("Outer", format!("{:?}", outer)); 31 | assert_eq!("Outer", format!("{:#?}", outer)); 32 | assert_eq!("Outer", format!("{:0>10.2?}", outer)); 33 | assert_eq!("Outer", format!("{:?^10.2?}", outer)); 34 | assert_eq!("Outer", format!("{:#<10.2?}", outer)); 35 | assert_eq!("Outer", format!("{:#<#10.2?}", outer)); 36 | } 37 | 38 | #[test] 39 | #[allow(dead_code)] 40 | fn unit_renamed() { 41 | #[derive(Debug)] 42 | struct Inner { 43 | f1: u8, 44 | f2: u8, 45 | } 46 | 47 | struct Outer { 48 | f1: f64, 49 | f2: Inner, 50 | } 51 | 52 | impl Debug for Outer { 53 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 54 | debug_helper::impl_debug_for_struct!(A, f, self); 55 | } 56 | } 57 | 58 | let outer = Outer { 59 | f1: 1.23456789, 60 | f2: Inner { 61 | f1: 5, f2: 10 62 | }, 63 | }; 64 | 65 | assert_eq!("A", format!("{:?}", outer)); 66 | assert_eq!("A", format!("{:#?}", outer)); 67 | assert_eq!("A", format!("{:010.2?}", outer)); 68 | assert_eq!("A", format!("{:0>10.2?}", outer)); 69 | assert_eq!("A", format!("{:?^10.2?}", outer)); 70 | assert_eq!("A", format!("{:#<10.2?}", outer)); 71 | assert_eq!("A", format!("{:#<#10.2?}", outer)); 72 | } 73 | 74 | #[test] 75 | #[allow(dead_code)] 76 | fn one_field_primitive() { 77 | #[derive(Debug)] 78 | struct Inner { 79 | f1: u8, 80 | f2: u8, 81 | } 82 | 83 | struct Outer { 84 | f1: f64, 85 | f2: Inner, 86 | } 87 | 88 | impl Debug for Outer { 89 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 90 | debug_helper::impl_debug_for_struct!(Outer, f, self, .f1); 91 | } 92 | } 93 | 94 | let outer = Outer { 95 | f1: 1.23456789, 96 | f2: Inner { 97 | f1: 5, f2: 10 98 | }, 99 | }; 100 | 101 | assert_eq!("Outer { f1: 1.23456789 }", format!("{:?}", outer)); 102 | assert_eq!("Outer {\n f1: 1.23456789,\n}", format!("{:#?}", outer)); 103 | assert_eq!("Outer { f1: 0000001.23 }", format!("{:010.2?}", outer)); 104 | assert_eq!("Outer { f1: 0000001.23 }", format!("{:0>10.2?}", outer)); 105 | assert_eq!("Outer { f1: ???1.23??? }", format!("{:?^10.2?}", outer)); 106 | assert_eq!("Outer { f1: 1.23###### }", format!("{:#<10.2?}", outer)); 107 | assert_eq!("Outer {\n f1: 1.23######,\n}", format!("{:#<#10.2?}", outer)); 108 | } 109 | 110 | #[test] 111 | #[allow(dead_code)] 112 | fn one_field_nested() { 113 | #[derive(Debug)] 114 | struct Inner { 115 | f1: u8, 116 | f2: u8, 117 | } 118 | 119 | struct Outer { 120 | f1: f64, 121 | f2: Inner, 122 | } 123 | 124 | impl Debug for Outer { 125 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 126 | debug_helper::impl_debug_for_struct!(Outer, f, self, .f2); 127 | } 128 | } 129 | 130 | let outer = Outer { 131 | f1: 1.23456789, 132 | f2: Inner { 133 | f1: 5, f2: 10 134 | }, 135 | }; 136 | 137 | assert_eq!("Outer { f2: Inner { f1: 5, f2: 10 } }", format!("{:?}", outer)); 138 | assert_eq!( 139 | "Outer {\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n}", 140 | format!("{:#?}", outer) 141 | ); 142 | assert_eq!( 143 | "Outer { f2: Inner { f1: 0000000005, f2: 0000000010 } }", 144 | format!("{:010.2?}", outer) 145 | ); 146 | assert_eq!( 147 | "Outer { f2: Inner { f1: 0000000005, f2: 0000000010 } }", 148 | format!("{:0>10.2?}", outer) 149 | ); 150 | assert_eq!( 151 | "Outer { f2: Inner { f1: ????5?????, f2: ????10???? } }", 152 | format!("{:?^10.2?}", outer) 153 | ); 154 | assert_eq!( 155 | "Outer { f2: Inner { f1: 5#########, f2: 10######## } }", 156 | format!("{:#<10.2?}", outer) 157 | ); 158 | assert_eq!( 159 | "Outer {\n f2: Inner {\n f1: 5#########,\n f2: 10########,\n },\n}", 160 | format!("{:#<#10.2?}", outer) 161 | ); 162 | } 163 | 164 | #[test] 165 | fn all_renamed() { 166 | #[allow(dead_code)] 167 | #[derive(Debug)] 168 | struct Inner { 169 | f1: u8, 170 | f2: u8, 171 | } 172 | 173 | struct Outer { 174 | f1: f64, 175 | f2: Inner, 176 | } 177 | 178 | impl Debug for Outer { 179 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 180 | debug_helper::impl_debug_for_struct!(A, f, self, .f1, .f2); 181 | } 182 | } 183 | 184 | let outer = Outer { 185 | f1: 1.23456789, 186 | f2: Inner { 187 | f1: 5, f2: 10 188 | }, 189 | }; 190 | 191 | assert_eq!("A { f1: 1.23456789, f2: Inner { f1: 5, f2: 10 } }", format!("{:?}", outer)); 192 | assert_eq!( 193 | "A {\n f1: 1.23456789,\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n}", 194 | format!("{:#?}", outer) 195 | ); 196 | assert_eq!( 197 | "A { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 198 | format!("{:010.2?}", outer) 199 | ); 200 | assert_eq!( 201 | "A { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 202 | format!("{:0>10.2?}", outer) 203 | ); 204 | assert_eq!( 205 | "A { f1: ???1.23???, f2: Inner { f1: ????5?????, f2: ????10???? } }", 206 | format!("{:?^10.2?}", outer) 207 | ); 208 | assert_eq!( 209 | "A { f1: 1.23######, f2: Inner { f1: 5#########, f2: 10######## } }", 210 | format!("{:#<10.2?}", outer) 211 | ); 212 | assert_eq!( 213 | "A {\n f1: 1.23######,\n f2: Inner {\n f1: 5#########,\n f2: \ 214 | 10########,\n },\n}", 215 | format!("{:#<#10.2?}", outer) 216 | ); 217 | } 218 | 219 | #[test] 220 | #[allow(dead_code)] 221 | fn custom_fmt() { 222 | #[derive(Debug)] 223 | struct Inner { 224 | f1: u8, 225 | f2: u8, 226 | } 227 | 228 | struct Intruder { 229 | s: &'static str, 230 | } 231 | 232 | struct Outer { 233 | f1: f64, 234 | f2: Inner, 235 | f3: Intruder, 236 | } 237 | 238 | impl Debug for Outer { 239 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 240 | debug_helper::impl_debug_for_struct!(Outer, f, self, (.f1, "number"), .f2, (.f3, "{}", self.f3.s)); 241 | } 242 | } 243 | 244 | let outer = Outer { 245 | f1: 1.23456789, 246 | f2: Inner { 247 | f1: 5, f2: 10 248 | }, 249 | f3: Intruder { 250 | s: "Hi" 251 | }, 252 | }; 253 | 254 | assert_eq!("Outer { f1: number, f2: Inner { f1: 5, f2: 10 }, f3: Hi }", format!("{:?}", outer)); 255 | assert_eq!( 256 | "Outer {\n f1: number,\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n \ 257 | f3: Hi,\n}", 258 | format!("{:#?}", outer) 259 | ); 260 | assert_eq!( 261 | "Outer { f1: number, f2: Inner { f1: 0000000005, f2: 0000000010 }, f3: Hi }", 262 | format!("{:010.2?}", outer) 263 | ); 264 | assert_eq!( 265 | "Outer { f1: number, f2: Inner { f1: 0000000005, f2: 0000000010 }, f3: Hi }", 266 | format!("{:0>10.2?}", outer) 267 | ); 268 | assert_eq!( 269 | "Outer { f1: number, f2: Inner { f1: ????5?????, f2: ????10???? }, f3: Hi }", 270 | format!("{:?^10.2?}", outer) 271 | ); 272 | assert_eq!( 273 | "Outer { f1: number, f2: Inner { f1: 5#########, f2: 10######## }, f3: Hi }", 274 | format!("{:#<10.2?}", outer) 275 | ); 276 | assert_eq!( 277 | "Outer {\n f1: number,\n f2: Inner {\n f1: 5#########,\n f2: \ 278 | 10########,\n },\n f3: Hi,\n}", 279 | format!("{:#<#10.2?}", outer) 280 | ); 281 | } 282 | 283 | #[test] 284 | fn additional_fields() { 285 | #[allow(dead_code)] 286 | #[derive(Debug)] 287 | struct Inner { 288 | f1: u8, 289 | f2: u8, 290 | } 291 | 292 | struct Outer { 293 | f1: f64, 294 | f2: Inner, 295 | } 296 | 297 | impl Debug for Outer { 298 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 299 | debug_helper::impl_debug_for_struct!(Outer, f, self, .f1, .f2, (.f3, "Hi")); 300 | } 301 | } 302 | 303 | let outer = Outer { 304 | f1: 1.23456789, 305 | f2: Inner { 306 | f1: 5, f2: 10 307 | }, 308 | }; 309 | 310 | assert_eq!( 311 | "Outer { f1: 1.23456789, f2: Inner { f1: 5, f2: 10 }, f3: Hi }", 312 | format!("{:?}", outer) 313 | ); 314 | assert_eq!("Outer {\n f1: 1.23456789,\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n f3: Hi,\n}", format!("{:#?}", outer)); 315 | assert_eq!( 316 | "Outer { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 }, f3: Hi }", 317 | format!("{:010.2?}", outer) 318 | ); 319 | assert_eq!( 320 | "Outer { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 }, f3: Hi }", 321 | format!("{:0>10.2?}", outer) 322 | ); 323 | assert_eq!( 324 | "Outer { f1: ???1.23???, f2: Inner { f1: ????5?????, f2: ????10???? }, f3: Hi }", 325 | format!("{:?^10.2?}", outer) 326 | ); 327 | assert_eq!( 328 | "Outer { f1: 1.23######, f2: Inner { f1: 5#########, f2: 10######## }, f3: Hi }", 329 | format!("{:#<10.2?}", outer) 330 | ); 331 | assert_eq!( 332 | "Outer {\n f1: 1.23######,\n f2: Inner {\n f1: 5#########,\n f2: \ 333 | 10########,\n },\n f3: Hi,\n}", 334 | format!("{:#<#10.2?}", outer) 335 | ); 336 | } 337 | 338 | #[test] 339 | fn fake_struct() { 340 | #[allow(dead_code)] 341 | #[derive(Debug)] 342 | struct Inner { 343 | f1: u8, 344 | f2: u8, 345 | } 346 | 347 | #[allow(dead_code)] 348 | struct Outer(f64, Inner); 349 | 350 | impl Debug for Outer { 351 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 352 | debug_helper::impl_debug_for_struct!(Outer, f, self, let .f1 = self.0); 353 | } 354 | } 355 | 356 | let outer = Outer(1.23456789, Inner { 357 | f1: 5, f2: 10 358 | }); 359 | 360 | assert_eq!("Outer { f1: 1.23456789 }", format!("{:?}", outer)); 361 | assert_eq!("Outer {\n f1: 1.23456789,\n}", format!("{:#?}", outer)); 362 | assert_eq!("Outer { f1: 0000001.23 }", format!("{:010.2?}", outer)); 363 | assert_eq!("Outer { f1: 0000001.23 }", format!("{:0>10.2?}", outer)); 364 | assert_eq!("Outer { f1: ???1.23??? }", format!("{:?^10.2?}", outer)); 365 | assert_eq!("Outer { f1: 1.23###### }", format!("{:#<10.2?}", outer)); 366 | assert_eq!("Outer {\n f1: 1.23######,\n}", format!("{:#<#10.2?}", outer)); 367 | } 368 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | # Debug Helper 3 | 4 | This crate provides declarative macros to help you implement the `Debug` trait manually. 5 | 6 | Instead of this crate, in most cases, you can use the [`educe`](https://crates.io/crates/educe) crate to implement the `Debug` trait. 7 | 8 | ## Examples 9 | 10 | For structs, 11 | 12 | ```rust 13 | use std::fmt::{self, Formatter, Debug}; 14 | 15 | pub struct A { 16 | pub f1: u8, 17 | pub f2: i16, 18 | pub f3: f64, 19 | } 20 | 21 | impl Debug for A { 22 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 23 | debug_helper::impl_debug_for_struct!(A, f, self, .f1, (.f3, "{:.3}", self.f3)); 24 | } 25 | } 26 | 27 | let a = A { 28 | f1: 1, 29 | f2: 2, 30 | f3: std::f64::consts::PI, 31 | }; 32 | 33 | println!("{:#?}", a); 34 | 35 | /* 36 | A { 37 | f1: 1, 38 | f3: 3.142, 39 | } 40 | */ 41 | ``` 42 | 43 | For tuple structs, 44 | 45 | ```rust 46 | use std::fmt::{self, Formatter, Debug}; 47 | 48 | pub struct A(pub u8, pub i16, pub f64); 49 | 50 | impl Debug for A { 51 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 52 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, (.2, "{:.3}", self.2)); 53 | } 54 | } 55 | 56 | let a = A(1, 2, std::f64::consts::PI); 57 | 58 | println!("{:#?}", a); 59 | 60 | /* 61 | A( 62 | 1, 63 | 3.142, 64 | ) 65 | */ 66 | ``` 67 | 68 | For enums (without the enum name), 69 | 70 | ```rust 71 | use std::fmt::{self, Formatter, Debug}; 72 | 73 | pub enum A { 74 | V1, 75 | V2(u8, i16, f64), 76 | V3 { 77 | f1: u8, 78 | f2: i16, 79 | f3: f64, 80 | }, 81 | } 82 | 83 | impl Debug for A { 84 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 85 | debug_helper::impl_debug_for_enum!(A::{V1, (V2(f1, _, f3): (.f1, (.f3, "{:.3}", f3))), {V3{f1, f2: _, f3}: (.f1, (.f3, "{:.3}", f3))}}, f, self); 86 | } 87 | } 88 | 89 | let a = A::V1; 90 | let b = A::V2(1, 2, std::f64::consts::PI); 91 | let c = A::V3{ 92 | f1: 1, 93 | f2: 2, 94 | f3: std::f64::consts::PI, 95 | }; 96 | 97 | println!("{:#?}", a); 98 | println!("{:#?}", b); 99 | println!("{:#?}", c); 100 | 101 | /* 102 | V1 103 | V2( 104 | 1, 105 | 3.142, 106 | ) 107 | V3 { 108 | f1: 1, 109 | f3: 3.142, 110 | } 111 | */ 112 | ``` 113 | 114 | For enums (with the enum name), 115 | 116 | ```rust 117 | use std::fmt::{self, Formatter, Debug}; 118 | 119 | pub enum A { 120 | V1, 121 | V2(u8, i16, f64), 122 | V3 { 123 | f1: u8, 124 | f2: i16, 125 | f3: f64, 126 | }, 127 | } 128 | 129 | impl Debug for A { 130 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 131 | debug_helper::impl_debug_for_enum!({A::V1, (V2(f1, _, f3): (.f1, (.f3, "{:.3}", f3))), {V3{f1, f2: _, f3}: (.f1, (.f3, "{:.3}", f3))}}, f, self); 132 | } 133 | } 134 | 135 | let a = A::V1; 136 | let b = A::V2(1, 2, std::f64::consts::PI); 137 | let c = A::V3{ 138 | f1: 1, 139 | f2: 2, 140 | f3: std::f64::consts::PI, 141 | }; 142 | 143 | println!("{:#?}", a); 144 | println!("{:#?}", b); 145 | println!("{:#?}", c); 146 | 147 | /* 148 | A::V1 149 | A::V2( 150 | 1, 151 | 3.142, 152 | ) 153 | A::V3 { 154 | f1: 1, 155 | f3: 3.142, 156 | } 157 | */ 158 | ``` 159 | 160 | 161 | 162 | Ghost fields, 163 | 164 | ```rust 165 | use std::fmt::{self, Formatter, Debug}; 166 | 167 | pub struct A { 168 | pub f1: u8, 169 | pub f2: i16, 170 | pub f3: f64, 171 | } 172 | 173 | impl Debug for A { 174 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 175 | debug_helper::impl_debug_for_struct!(A, f, self, .f1, (.f3, "{:.3}", self.f3), (.sum, "{:.3}", self.f1 as f64 + self.f2 as f64 + self.f3)); 176 | } 177 | } 178 | 179 | let a = A { 180 | f1: 1, 181 | f2: 2, 182 | f3: std::f64::consts::PI, 183 | }; 184 | 185 | println!("{:#?}", a); 186 | 187 | /* 188 | A { 189 | f1: 1, 190 | f3: 3.142, 191 | sum: 6.142, 192 | } 193 | */ 194 | ``` 195 | 196 | ```rust 197 | use std::fmt::{self, Formatter, Debug}; 198 | 199 | pub struct A(pub u8, pub i16, pub f64); 200 | 201 | impl Debug for A { 202 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 203 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, .0, (.2, "{:.3}", self.2), (.3, "{:.3}", self.0 as f64 + self.1 as f64 + self.2)); 204 | } 205 | } 206 | 207 | let a = A(1, 2, std::f64::consts::PI); 208 | 209 | println!("{:#?}", a); 210 | 211 | /* 212 | A( 213 | 1, 214 | 3.142, 215 | 6.142, 216 | ) 217 | */ 218 | ``` 219 | 220 | Fake structs, 221 | 222 | ```rust 223 | use std::fmt::{self, Formatter, Debug}; 224 | 225 | pub struct A(pub u8, pub i16, pub f64); 226 | 227 | impl Debug for A { 228 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 229 | debug_helper::impl_debug_for_struct!(A, f, self, let .f1 = self.0, let .f2 = self.1, let .f3 = self.2); 230 | } 231 | } 232 | 233 | let a = A(1, 2, std::f64::consts::PI); 234 | 235 | println!("{:#?}", a); 236 | 237 | /* 238 | A { 239 | f1: 1, 240 | f2: 2, 241 | f3: 3.141592653589793, 242 | } 243 | */ 244 | ``` 245 | 246 | Fake tuple structs, 247 | 248 | ```rust 249 | use std::fmt::{self, Formatter, Debug}; 250 | 251 | pub struct A { 252 | pub f1: u8, 253 | pub f2: i16, 254 | pub f3: f64, 255 | } 256 | 257 | impl Debug for A { 258 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 259 | debug_helper::impl_debug_for_tuple_struct!(A, f, self, let .0 = self.f1, let .1 = self.f2, let .2 = self.f3); 260 | } 261 | } 262 | 263 | let a = A { 264 | f1: 1, 265 | f2: 2, 266 | f3: std::f64::consts::PI, 267 | }; 268 | 269 | println!("{:#?}", a); 270 | 271 | /* 272 | A( 273 | 1, 274 | 2, 275 | 3.141592653589793, 276 | ) 277 | */ 278 | ``` 279 | 280 | ## TODO 281 | 282 | 1. Fake enum struct variants and tuple variants. 283 | 1. Enum variants can be renamed. 284 | 285 | */ 286 | 287 | #![no_std] 288 | 289 | extern crate alloc; 290 | 291 | use alloc::{ 292 | fmt::{Debug, Formatter, Result as FormatResult}, 293 | string::String, 294 | }; 295 | 296 | #[doc(hidden)] 297 | pub struct RawString(pub String); 298 | 299 | impl Debug for RawString { 300 | fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult { 301 | if f.alternate() { 302 | f.write_str(self.0.replace('\n', "\n ").as_str()) 303 | } else { 304 | f.write_str(self.0.as_str()) 305 | } 306 | } 307 | } 308 | 309 | #[macro_export] 310 | macro_rules! impl_debug_for_struct { 311 | // TODO unit struct 312 | ($struct_name:ident, $formatter:expr $(, $self:expr)? $(,)*) => { 313 | return $formatter.write_str(stringify!($struct_name)); 314 | }; 315 | // TODO struct 316 | ($struct_name:ident, $formatter:expr, $self:expr, $( $(.$field:ident)? $((.$field_2:ident, $($field_2_fmt:tt)+))? $(let .$field_3:ident = $field_3_value:expr)? ),* $(,)*) => { 317 | { 318 | let mut builder = $formatter.debug_struct(stringify!($struct_name)); 319 | 320 | $( 321 | $( 322 | builder.field(stringify!($field), &$self.$field); 323 | )? 324 | 325 | $( 326 | builder.field(stringify!($field_2), &$crate::RawString(format!($($field_2_fmt)*))); 327 | )? 328 | 329 | $( 330 | builder.field(stringify!($field_3), &$field_3_value); 331 | )? 332 | )* 333 | 334 | return builder.finish(); 335 | } 336 | }; 337 | } 338 | 339 | #[macro_export] 340 | macro_rules! impl_debug_for_tuple_struct { 341 | // TODO unit tuple struct 342 | ($struct_name:ident, $formatter:expr $(, $self:expr)? $(,)*) => { 343 | return $formatter.write_str(stringify!($struct_name)); 344 | }; 345 | // TODO tuple struct 346 | ($struct_name:ident, $formatter:expr, $self:expr, $( $(.$field:tt)? $((.$field_2:tt, $($field_2_fmt:tt)+))? $(let .$field_3:tt = $field_3_value:expr)? ),* $(,)*) => { 347 | { 348 | let mut builder = $formatter.debug_tuple(stringify!($struct_name)); 349 | 350 | $( 351 | $( 352 | builder.field(&$self.$field); 353 | )? 354 | 355 | $( 356 | builder.field(&$crate::RawString(format!($($field_2_fmt)*))); 357 | )? 358 | 359 | $( 360 | builder.field(&$field_3_value); 361 | )? 362 | )* 363 | 364 | return builder.finish(); 365 | } 366 | } 367 | } 368 | 369 | #[macro_export] 370 | macro_rules! impl_debug_for_enum { 371 | // TODO enum 372 | ($enum_name:ident::{$( $($variant_unit:ident)? $(($variant_tuple:ident ($($tuple:tt)*) $(:($( $(.$t_field:tt)? $((.$t_field_2:tt, $($t_field_2_fmt:tt)+))? $(let .$t_field_3:tt = $t_field_3_value:expr)? ),* $(,)*))? ) )? $({$variant_struct:ident {$($struct:tt)*} $(:($( $(.$s_field:tt)? $((.$s_field_2:tt, $($s_field_2_fmt:tt)+))? $(let .$s_field_3:ident = $s_field_3_value:expr)? ),* $(,)*))? })? ),+ $(,)*}, $formatter:expr, $self:expr $(,)*) => { 373 | { 374 | match $self { 375 | $( 376 | $( 377 | Self::$variant_unit => { 378 | return $formatter.write_str(stringify!($variant_unit)); 379 | } 380 | )? 381 | $( 382 | Self::$variant_tuple ($($tuple)*)=> { 383 | let mut builder = $formatter.debug_tuple(stringify!($variant_tuple)); 384 | 385 | $( 386 | $( 387 | $( 388 | builder.field(&$t_field); 389 | )? 390 | 391 | $( 392 | builder.field(&$crate::RawString(format!($($t_field_2_fmt)*))); 393 | )? 394 | 395 | $( 396 | builder.field(&$t_field_3_value); 397 | )? 398 | )* 399 | )? 400 | 401 | return builder.finish(); 402 | } 403 | )? 404 | $( 405 | Self::$variant_struct {$($struct)*}=> { 406 | let mut builder = $formatter.debug_struct(stringify!($variant_struct)); 407 | 408 | $( 409 | $( 410 | $( 411 | builder.field(stringify!($s_field), &$s_field); 412 | )? 413 | 414 | $( 415 | builder.field(stringify!($s_field_2), &$crate::RawString(format!($($s_field_2_fmt)*))); 416 | )? 417 | 418 | $( 419 | builder.field(stringify!($s_field_3), &$s_field_3_value); 420 | )? 421 | )* 422 | )? 423 | 424 | return builder.finish(); 425 | } 426 | )? 427 | )+ 428 | } 429 | } 430 | }; 431 | // TODO enum full path 432 | ({$enum_name:ident::$( $($variant_unit:ident)? $(($variant_tuple:ident ($($tuple:tt)*) $(:($( $(.$t_field:tt)? $((.$t_field_2:tt, $($t_field_2_fmt:tt)+))? $(let .$t_field_3:tt = $t_field_3_value:expr)? ),* $(,)*))? ) )? $({$variant_struct:ident {$($struct:tt)*} $(:($( $(.$s_field:tt)? $((.$s_field_2:tt, $($s_field_2_fmt:tt)+))? $(let .$s_field_3:ident = $s_field_3_value:expr)? ),* $(,)*))? })? ),+ $(,)*}, $formatter:expr, $self:expr $(,)*) => { 433 | { 434 | match $self { 435 | $( 436 | $( 437 | Self::$variant_unit => { 438 | $formatter.write_str(stringify!($enum_name))?; 439 | $formatter.write_str("::")?; 440 | return $formatter.write_str(stringify!($variant_unit)); 441 | } 442 | )? 443 | $( 444 | Self::$variant_tuple ($($tuple)*)=> { 445 | let mut builder = $formatter.debug_tuple(&format!("{}::{}", stringify!($enum_name), stringify!($variant_tuple))); 446 | 447 | $( 448 | $( 449 | $( 450 | builder.field(&$t_field); 451 | )? 452 | 453 | $( 454 | builder.field(&$crate::RawString(format!($($t_field_2_fmt)*))); 455 | )? 456 | 457 | $( 458 | builder.field(&$t_field_3_value); 459 | )? 460 | )* 461 | )? 462 | 463 | return builder.finish(); 464 | } 465 | )? 466 | $( 467 | Self::$variant_struct {$($struct)*}=> { 468 | let mut builder = $formatter.debug_struct(&format!("{}::{}", stringify!($enum_name), stringify!($variant_struct))); 469 | 470 | $( 471 | $( 472 | $( 473 | builder.field(stringify!($s_field), &$s_field); 474 | )? 475 | 476 | $( 477 | builder.field(stringify!($s_field_2), &$crate::RawString(format!($($s_field_2_fmt)*))); 478 | )? 479 | 480 | $( 481 | builder.field(stringify!($s_field_3), &$s_field_3_value); 482 | )? 483 | )* 484 | )? 485 | 486 | return builder.finish(); 487 | } 488 | )? 489 | )+ 490 | } 491 | } 492 | }; 493 | } 494 | -------------------------------------------------------------------------------- /tests/enum.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | #[test] 4 | #[allow(dead_code)] 5 | fn unit() { 6 | #[derive(Debug)] 7 | struct Inner { 8 | f1: u8, 9 | f2: u8, 10 | } 11 | 12 | enum Outer { 13 | F0, 14 | F1(f64, Inner), 15 | F2 { f1: f64, f2: Inner }, 16 | } 17 | 18 | impl Debug for Outer { 19 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 20 | debug_helper::impl_debug_for_enum!(Outer::{F0, (F1(..)), {F2{..}}}, f, self); 21 | } 22 | } 23 | 24 | let outer_1 = Outer::F0; 25 | let outer_2 = Outer::F1(1.23456789, Inner { 26 | f1: 5, f2: 10 27 | }); 28 | let outer_3 = Outer::F2 { 29 | f1: 1.23456789, 30 | f2: Inner { 31 | f1: 5, f2: 10 32 | }, 33 | }; 34 | 35 | assert_eq!("F0", format!("{:?}", outer_1)); 36 | assert_eq!("F0", format!("{:#?}", outer_1)); 37 | assert_eq!("F0", format!("{:010.2?}", outer_1)); 38 | assert_eq!("F0", format!("{:0>10.2?}", outer_1)); 39 | assert_eq!("F0", format!("{:?^10.2?}", outer_1)); 40 | assert_eq!("F0", format!("{:#<10.2?}", outer_1)); 41 | assert_eq!("F0", format!("{:#<#10.2?}", outer_1)); 42 | 43 | assert_eq!("F1", format!("{:?}", outer_2)); 44 | assert_eq!("F1", format!("{:#?}", outer_2)); 45 | assert_eq!("F1", format!("{:010.2?}", outer_2)); 46 | assert_eq!("F1", format!("{:0>10.2?}", outer_2)); 47 | assert_eq!("F1", format!("{:?^10.2?}", outer_2)); 48 | assert_eq!("F1", format!("{:#<10.2?}", outer_2)); 49 | assert_eq!("F1", format!("{:#<#10.2?}", outer_2)); 50 | 51 | assert_eq!("F2", format!("{:?}", outer_3)); 52 | assert_eq!("F2", format!("{:#?}", outer_3)); 53 | assert_eq!("F2", format!("{:010.2?}", outer_3)); 54 | assert_eq!("F2", format!("{:0>10.2?}", outer_3)); 55 | assert_eq!("F2", format!("{:?^10.2?}", outer_3)); 56 | assert_eq!("F2", format!("{:#<10.2?}", outer_3)); 57 | assert_eq!("F2", format!("{:#<#10.2?}", outer_3)); 58 | } 59 | 60 | #[test] 61 | #[allow(dead_code)] 62 | fn one_field_primitive() { 63 | #[derive(Debug)] 64 | struct Inner { 65 | f1: u8, 66 | f2: u8, 67 | } 68 | 69 | enum Outer { 70 | F0, 71 | F1(f64, Inner), 72 | F2 { f1: f64, f2: Inner }, 73 | } 74 | 75 | impl Debug for Outer { 76 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 77 | debug_helper::impl_debug_for_enum!(Outer::{F0, (F1(f1, ..): (.f1)), {F2{f1, ..}: (.f1)}}, f, self); 78 | } 79 | } 80 | 81 | let outer_1 = Outer::F0; 82 | let outer_2 = Outer::F1(1.23456789, Inner { 83 | f1: 5, f2: 10 84 | }); 85 | let outer_3 = Outer::F2 { 86 | f1: 1.23456789, 87 | f2: Inner { 88 | f1: 5, f2: 10 89 | }, 90 | }; 91 | 92 | assert_eq!("F0", format!("{:?}", outer_1)); 93 | assert_eq!("F0", format!("{:#?}", outer_1)); 94 | assert_eq!("F0", format!("{:010.2?}", outer_1)); 95 | assert_eq!("F0", format!("{:0>10.2?}", outer_1)); 96 | assert_eq!("F0", format!("{:?^10.2?}", outer_1)); 97 | assert_eq!("F0", format!("{:#<10.2?}", outer_1)); 98 | assert_eq!("F0", format!("{:#<#10.2?}", outer_1)); 99 | 100 | assert_eq!("F1(1.23456789)", format!("{:?}", outer_2)); 101 | assert_eq!("F1(\n 1.23456789,\n)", format!("{:#?}", outer_2)); 102 | assert_eq!("F1(0000001.23)", format!("{:010.2?}", outer_2)); 103 | assert_eq!("F1(0000001.23)", format!("{:0>10.2?}", outer_2)); 104 | assert_eq!("F1(???1.23???)", format!("{:?^10.2?}", outer_2)); 105 | assert_eq!("F1(1.23######)", format!("{:#<10.2?}", outer_2)); 106 | assert_eq!("F1(\n 1.23######,\n)", format!("{:#<#10.2?}", outer_2)); 107 | 108 | assert_eq!("F2 { f1: 1.23456789 }", format!("{:?}", outer_3)); 109 | assert_eq!("F2 {\n f1: 1.23456789,\n}", format!("{:#?}", outer_3)); 110 | assert_eq!("F2 { f1: 0000001.23 }", format!("{:010.2?}", outer_3)); 111 | assert_eq!("F2 { f1: 0000001.23 }", format!("{:0>10.2?}", outer_3)); 112 | assert_eq!("F2 { f1: ???1.23??? }", format!("{:?^10.2?}", outer_3)); 113 | assert_eq!("F2 { f1: 1.23###### }", format!("{:#<10.2?}", outer_3)); 114 | assert_eq!("F2 {\n f1: 1.23######,\n}", format!("{:#<#10.2?}", outer_3)); 115 | } 116 | 117 | #[test] 118 | #[allow(dead_code)] 119 | fn one_field_nested() { 120 | #[derive(Debug)] 121 | struct Inner { 122 | f1: u8, 123 | f2: u8, 124 | } 125 | 126 | enum Outer { 127 | F0, 128 | F1(f64, Inner), 129 | F2 { f1: f64, f2: Inner }, 130 | } 131 | 132 | impl Debug for Outer { 133 | #[allow(clippy::unneeded_field_pattern)] 134 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 135 | debug_helper::impl_debug_for_enum!(Outer::{F0, (F1(_, f2): (.f2)), {F2{f1: _, f2}: (.f2)}}, f, self); 136 | } 137 | } 138 | 139 | let outer_1 = Outer::F0; 140 | let outer_2 = Outer::F1(1.23456789, Inner { 141 | f1: 5, f2: 10 142 | }); 143 | let outer_3 = Outer::F2 { 144 | f1: 1.23456789, 145 | f2: Inner { 146 | f1: 5, f2: 10 147 | }, 148 | }; 149 | 150 | assert_eq!("F0", format!("{:?}", outer_1)); 151 | assert_eq!("F0", format!("{:#?}", outer_1)); 152 | assert_eq!("F0", format!("{:010.2?}", outer_1)); 153 | assert_eq!("F0", format!("{:0>10.2?}", outer_1)); 154 | assert_eq!("F0", format!("{:?^10.2?}", outer_1)); 155 | assert_eq!("F0", format!("{:#<10.2?}", outer_1)); 156 | assert_eq!("F0", format!("{:#<#10.2?}", outer_1)); 157 | 158 | assert_eq!("F1(Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 159 | assert_eq!( 160 | "F1(\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 161 | format!("{:#?}", outer_2) 162 | ); 163 | assert_eq!("F1(Inner { f1: 0000000005, f2: 0000000010 })", format!("{:010.2?}", outer_2)); 164 | assert_eq!("F1(Inner { f1: 0000000005, f2: 0000000010 })", format!("{:0>10.2?}", outer_2)); 165 | assert_eq!("F1(Inner { f1: ????5?????, f2: ????10???? })", format!("{:?^10.2?}", outer_2)); 166 | assert_eq!("F1(Inner { f1: 5#########, f2: 10######## })", format!("{:#<10.2?}", outer_2)); 167 | assert_eq!( 168 | "F1(\n Inner {\n f1: 5#########,\n f2: 10########,\n },\n)", 169 | format!("{:#<#10.2?}", outer_2) 170 | ); 171 | 172 | assert_eq!("F2 { f2: Inner { f1: 5, f2: 10 } }", format!("{:?}", outer_3)); 173 | assert_eq!( 174 | "F2 {\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n}", 175 | format!("{:#?}", outer_3) 176 | ); 177 | assert_eq!( 178 | "F2 { f2: Inner { f1: 0000000005, f2: 0000000010 } }", 179 | format!("{:010.2?}", outer_3) 180 | ); 181 | assert_eq!( 182 | "F2 { f2: Inner { f1: 0000000005, f2: 0000000010 } }", 183 | format!("{:0>10.2?}", outer_3) 184 | ); 185 | assert_eq!( 186 | "F2 { f2: Inner { f1: ????5?????, f2: ????10???? } }", 187 | format!("{:?^10.2?}", outer_3) 188 | ); 189 | assert_eq!( 190 | "F2 { f2: Inner { f1: 5#########, f2: 10######## } }", 191 | format!("{:#<10.2?}", outer_3) 192 | ); 193 | assert_eq!( 194 | "F2 {\n f2: Inner {\n f1: 5#########,\n f2: 10########,\n },\n}", 195 | format!("{:#<#10.2?}", outer_3) 196 | ); 197 | } 198 | 199 | #[test] 200 | #[allow(dead_code)] 201 | fn all() { 202 | #[derive(Debug)] 203 | struct Inner { 204 | f1: u8, 205 | f2: u8, 206 | } 207 | 208 | enum Outer { 209 | F0, 210 | F1(f64, Inner), 211 | F2 { f1: f64, f2: Inner }, 212 | } 213 | 214 | impl Debug for Outer { 215 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 216 | debug_helper::impl_debug_for_enum!(Outer::{F0, (F1(f1, f2): (.f1, .f2)), {F2{f1, f2}: (.f1, .f2)}}, f, self); 217 | } 218 | } 219 | 220 | let outer_1 = Outer::F0; 221 | let outer_2 = Outer::F1(1.23456789, Inner { 222 | f1: 5, f2: 10 223 | }); 224 | let outer_3 = Outer::F2 { 225 | f1: 1.23456789, 226 | f2: Inner { 227 | f1: 5, f2: 10 228 | }, 229 | }; 230 | 231 | assert_eq!("F0", format!("{:?}", outer_1)); 232 | assert_eq!("F0", format!("{:#?}", outer_1)); 233 | assert_eq!("F0", format!("{:010.2?}", outer_1)); 234 | assert_eq!("F0", format!("{:0>10.2?}", outer_1)); 235 | assert_eq!("F0", format!("{:?^10.2?}", outer_1)); 236 | assert_eq!("F0", format!("{:#<10.2?}", outer_1)); 237 | assert_eq!("F0", format!("{:#<#10.2?}", outer_1)); 238 | 239 | assert_eq!("F1(1.23456789, Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 240 | assert_eq!( 241 | "F1(\n 1.23456789,\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 242 | format!("{:#?}", outer_2) 243 | ); 244 | assert_eq!( 245 | "F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 246 | format!("{:010.2?}", outer_2) 247 | ); 248 | assert_eq!( 249 | "F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 250 | format!("{:0>10.2?}", outer_2) 251 | ); 252 | assert_eq!( 253 | "F1(???1.23???, Inner { f1: ????5?????, f2: ????10???? })", 254 | format!("{:?^10.2?}", outer_2) 255 | ); 256 | assert_eq!( 257 | "F1(1.23######, Inner { f1: 5#########, f2: 10######## })", 258 | format!("{:#<10.2?}", outer_2) 259 | ); 260 | assert_eq!( 261 | "F1(\n 1.23######,\n Inner {\n f1: 5#########,\n f2: 10########,\n \ 262 | },\n)", 263 | format!("{:#<#10.2?}", outer_2) 264 | ); 265 | 266 | assert_eq!("F2 { f1: 1.23456789, f2: Inner { f1: 5, f2: 10 } }", format!("{:?}", outer_3)); 267 | assert_eq!( 268 | "F2 {\n f1: 1.23456789,\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n}", 269 | format!("{:#?}", outer_3) 270 | ); 271 | assert_eq!( 272 | "F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 273 | format!("{:010.2?}", outer_3) 274 | ); 275 | assert_eq!( 276 | "F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 277 | format!("{:0>10.2?}", outer_3) 278 | ); 279 | assert_eq!( 280 | "F2 { f1: ???1.23???, f2: Inner { f1: ????5?????, f2: ????10???? } }", 281 | format!("{:?^10.2?}", outer_3) 282 | ); 283 | assert_eq!( 284 | "F2 { f1: 1.23######, f2: Inner { f1: 5#########, f2: 10######## } }", 285 | format!("{:#<10.2?}", outer_3) 286 | ); 287 | assert_eq!( 288 | "F2 {\n f1: 1.23######,\n f2: Inner {\n f1: 5#########,\n f2: \ 289 | 10########,\n },\n}", 290 | format!("{:#<#10.2?}", outer_3) 291 | ); 292 | } 293 | 294 | #[test] 295 | fn custom_fmt() { 296 | #[allow(dead_code)] 297 | #[derive(Debug)] 298 | struct Inner { 299 | f1: u8, 300 | f2: u8, 301 | } 302 | 303 | struct Intruder { 304 | s: &'static str, 305 | } 306 | 307 | #[allow(dead_code)] 308 | enum Outer { 309 | F0, 310 | F1(f64, Inner), 311 | F2 { f1: f64, f2: Inner }, 312 | F3(Intruder), 313 | } 314 | 315 | impl Debug for Outer { 316 | #[allow(clippy::unneeded_field_pattern)] 317 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 318 | debug_helper::impl_debug_for_enum!(Outer::{F0, (F1(_f1, f2): ((._f1, "number"), .f2)), {F2{f1: _, f2}: ((.f1, "number"), .f2)}, (F3(f3): ((.f3, "{}", f3.s)))}, f, self); 319 | } 320 | } 321 | 322 | let outer_1 = Outer::F0; 323 | let outer_2 = Outer::F1(1.23456789, Inner { 324 | f1: 5, f2: 10 325 | }); 326 | let outer_3 = Outer::F2 { 327 | f1: 1.23456789, 328 | f2: Inner { 329 | f1: 5, f2: 10 330 | }, 331 | }; 332 | let outer_4 = Outer::F3(Intruder { 333 | s: "Hi" 334 | }); 335 | 336 | assert_eq!("F0", format!("{:?}", outer_1)); 337 | assert_eq!("F0", format!("{:#?}", outer_1)); 338 | assert_eq!("F0", format!("{:010.2?}", outer_1)); 339 | assert_eq!("F0", format!("{:0>10.2?}", outer_1)); 340 | assert_eq!("F0", format!("{:?^10.2?}", outer_1)); 341 | assert_eq!("F0", format!("{:#<10.2?}", outer_1)); 342 | assert_eq!("F0", format!("{:#<#10.2?}", outer_1)); 343 | 344 | assert_eq!("F1(number, Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 345 | assert_eq!( 346 | "F1(\n number,\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 347 | format!("{:#?}", outer_2) 348 | ); 349 | assert_eq!( 350 | "F1(number, Inner { f1: 0000000005, f2: 0000000010 })", 351 | format!("{:010.2?}", outer_2) 352 | ); 353 | assert_eq!( 354 | "F1(number, Inner { f1: 0000000005, f2: 0000000010 })", 355 | format!("{:0>10.2?}", outer_2) 356 | ); 357 | assert_eq!( 358 | "F1(number, Inner { f1: ????5?????, f2: ????10???? })", 359 | format!("{:?^10.2?}", outer_2) 360 | ); 361 | assert_eq!( 362 | "F1(number, Inner { f1: 5#########, f2: 10######## })", 363 | format!("{:#<10.2?}", outer_2) 364 | ); 365 | assert_eq!( 366 | "F1(\n number,\n Inner {\n f1: 5#########,\n f2: 10########,\n \ 367 | },\n)", 368 | format!("{:#<#10.2?}", outer_2) 369 | ); 370 | 371 | assert_eq!("F2 { f1: number, f2: Inner { f1: 5, f2: 10 } }", format!("{:?}", outer_3)); 372 | assert_eq!( 373 | "F2 {\n f1: number,\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n}", 374 | format!("{:#?}", outer_3) 375 | ); 376 | assert_eq!( 377 | "F2 { f1: number, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 378 | format!("{:010.2?}", outer_3) 379 | ); 380 | assert_eq!( 381 | "F2 { f1: number, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 382 | format!("{:0>10.2?}", outer_3) 383 | ); 384 | assert_eq!( 385 | "F2 { f1: number, f2: Inner { f1: ????5?????, f2: ????10???? } }", 386 | format!("{:?^10.2?}", outer_3) 387 | ); 388 | assert_eq!( 389 | "F2 { f1: number, f2: Inner { f1: 5#########, f2: 10######## } }", 390 | format!("{:#<10.2?}", outer_3) 391 | ); 392 | assert_eq!( 393 | "F2 {\n f1: number,\n f2: Inner {\n f1: 5#########,\n f2: \ 394 | 10########,\n },\n}", 395 | format!("{:#<#10.2?}", outer_3) 396 | ); 397 | 398 | assert_eq!("F3(Hi)", format!("{:?}", outer_4)); 399 | assert_eq!("F3(\n Hi,\n)", format!("{:#?}", outer_4)); 400 | assert_eq!("F3(Hi)", format!("{:010.2?}", outer_4)); 401 | assert_eq!("F3(Hi)", format!("{:0>10.2?}", outer_4)); 402 | assert_eq!("F3(Hi)", format!("{:?^10.2?}", outer_4)); 403 | assert_eq!("F3(Hi)", format!("{:#<10.2?}", outer_4)); 404 | assert_eq!("F3(\n Hi,\n)", format!("{:#<#10.2?}", outer_4)); 405 | } 406 | 407 | #[test] 408 | #[allow(dead_code)] 409 | fn additional_fields() { 410 | #[derive(Debug)] 411 | struct Inner { 412 | f1: u8, 413 | f2: u8, 414 | } 415 | 416 | enum Outer { 417 | F0, 418 | F1(f64, Inner), 419 | F2 { f1: f64, f2: Inner }, 420 | } 421 | 422 | impl Debug for Outer { 423 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 424 | debug_helper::impl_debug_for_enum!(Outer::{F0, (F1(f1, f2): (.f1, .f2)), {F2{f1, f2}: (.f1, .f2, (.f3, "Hi"))}}, f, self); 425 | } 426 | } 427 | 428 | let outer_1 = Outer::F0; 429 | let outer_2 = Outer::F1(1.23456789, Inner { 430 | f1: 5, f2: 10 431 | }); 432 | let outer_3 = Outer::F2 { 433 | f1: 1.23456789, 434 | f2: Inner { 435 | f1: 5, f2: 10 436 | }, 437 | }; 438 | 439 | assert_eq!("F0", format!("{:?}", outer_1)); 440 | assert_eq!("F0", format!("{:#?}", outer_1)); 441 | assert_eq!("F0", format!("{:010.2?}", outer_1)); 442 | assert_eq!("F0", format!("{:0>10.2?}", outer_1)); 443 | assert_eq!("F0", format!("{:?^10.2?}", outer_1)); 444 | assert_eq!("F0", format!("{:#<10.2?}", outer_1)); 445 | assert_eq!("F0", format!("{:#<#10.2?}", outer_1)); 446 | 447 | assert_eq!("F1(1.23456789, Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 448 | assert_eq!( 449 | "F1(\n 1.23456789,\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 450 | format!("{:#?}", outer_2) 451 | ); 452 | assert_eq!( 453 | "F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 454 | format!("{:010.2?}", outer_2) 455 | ); 456 | assert_eq!( 457 | "F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 458 | format!("{:0>10.2?}", outer_2) 459 | ); 460 | assert_eq!( 461 | "F1(???1.23???, Inner { f1: ????5?????, f2: ????10???? })", 462 | format!("{:?^10.2?}", outer_2) 463 | ); 464 | assert_eq!( 465 | "F1(1.23######, Inner { f1: 5#########, f2: 10######## })", 466 | format!("{:#<10.2?}", outer_2) 467 | ); 468 | assert_eq!( 469 | "F1(\n 1.23######,\n Inner {\n f1: 5#########,\n f2: 10########,\n \ 470 | },\n)", 471 | format!("{:#<#10.2?}", outer_2) 472 | ); 473 | 474 | assert_eq!( 475 | "F2 { f1: 1.23456789, f2: Inner { f1: 5, f2: 10 }, f3: Hi }", 476 | format!("{:?}", outer_3) 477 | ); 478 | assert_eq!( 479 | "F2 {\n f1: 1.23456789,\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n \ 480 | f3: Hi,\n}", 481 | format!("{:#?}", outer_3) 482 | ); 483 | assert_eq!( 484 | "F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 }, f3: Hi }", 485 | format!("{:010.2?}", outer_3) 486 | ); 487 | assert_eq!( 488 | "F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 }, f3: Hi }", 489 | format!("{:0>10.2?}", outer_3) 490 | ); 491 | assert_eq!( 492 | "F2 { f1: ???1.23???, f2: Inner { f1: ????5?????, f2: ????10???? }, f3: Hi }", 493 | format!("{:?^10.2?}", outer_3) 494 | ); 495 | assert_eq!( 496 | "F2 { f1: 1.23######, f2: Inner { f1: 5#########, f2: 10######## }, f3: Hi }", 497 | format!("{:#<10.2?}", outer_3) 498 | ); 499 | assert_eq!( 500 | "F2 {\n f1: 1.23######,\n f2: Inner {\n f1: 5#########,\n f2: \ 501 | 10########,\n },\n f3: Hi,\n}", 502 | format!("{:#<#10.2?}", outer_3) 503 | ); 504 | } 505 | 506 | #[test] 507 | #[allow(dead_code)] 508 | fn reset() { 509 | #[derive(Debug)] 510 | struct Inner { 511 | f1: u8, 512 | f2: u8, 513 | } 514 | 515 | enum Outer { 516 | F0, 517 | F1(f64, Inner), 518 | F2 { f1: f64, f2: Inner }, 519 | } 520 | 521 | impl Debug for Outer { 522 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 523 | debug_helper::impl_debug_for_enum!(Outer::{F0, (F1(f1, f2): (let .f1 = f2, let .f2 = f1)), {F2{f1, f2}: (let .f1 = f2, let .f2 = f1)}}, f, self); 524 | } 525 | } 526 | 527 | let outer_1 = Outer::F0; 528 | let outer_2 = Outer::F1(1.23456789, Inner { 529 | f1: 5, f2: 10 530 | }); 531 | let outer_3 = Outer::F2 { 532 | f1: 1.23456789, 533 | f2: Inner { 534 | f1: 5, f2: 10 535 | }, 536 | }; 537 | 538 | assert_eq!("F0", format!("{:?}", outer_1)); 539 | assert_eq!("F0", format!("{:#?}", outer_1)); 540 | assert_eq!("F0", format!("{:010.2?}", outer_1)); 541 | assert_eq!("F0", format!("{:0>10.2?}", outer_1)); 542 | assert_eq!("F0", format!("{:?^10.2?}", outer_1)); 543 | assert_eq!("F0", format!("{:#<10.2?}", outer_1)); 544 | assert_eq!("F0", format!("{:#<#10.2?}", outer_1)); 545 | 546 | assert_eq!("F1(Inner { f1: 5, f2: 10 }, 1.23456789)", format!("{:?}", outer_2)); 547 | assert_eq!( 548 | "F1(\n Inner {\n f1: 5,\n f2: 10,\n },\n 1.23456789,\n)", 549 | format!("{:#?}", outer_2) 550 | ); 551 | assert_eq!( 552 | "F1(Inner { f1: 0000000005, f2: 0000000010 }, 0000001.23)", 553 | format!("{:010.2?}", outer_2) 554 | ); 555 | assert_eq!( 556 | "F1(Inner { f1: 0000000005, f2: 0000000010 }, 0000001.23)", 557 | format!("{:0>10.2?}", outer_2) 558 | ); 559 | assert_eq!( 560 | "F1(Inner { f1: ????5?????, f2: ????10???? }, ???1.23???)", 561 | format!("{:?^10.2?}", outer_2) 562 | ); 563 | assert_eq!( 564 | "F1(Inner { f1: 5#########, f2: 10######## }, 1.23######)", 565 | format!("{:#<10.2?}", outer_2) 566 | ); 567 | assert_eq!( 568 | "F1(\n Inner {\n f1: 5#########,\n f2: 10########,\n },\n \ 569 | 1.23######,\n)", 570 | format!("{:#<#10.2?}", outer_2) 571 | ); 572 | 573 | assert_eq!("F2 { f1: Inner { f1: 5, f2: 10 }, f2: 1.23456789 }", format!("{:?}", outer_3)); 574 | assert_eq!( 575 | "F2 {\n f1: Inner {\n f1: 5,\n f2: 10,\n },\n f2: 1.23456789,\n}", 576 | format!("{:#?}", outer_3) 577 | ); 578 | assert_eq!( 579 | "F2 { f1: Inner { f1: 0000000005, f2: 0000000010 }, f2: 0000001.23 }", 580 | format!("{:010.2?}", outer_3) 581 | ); 582 | assert_eq!( 583 | "F2 { f1: Inner { f1: 0000000005, f2: 0000000010 }, f2: 0000001.23 }", 584 | format!("{:0>10.2?}", outer_3) 585 | ); 586 | assert_eq!( 587 | "F2 { f1: Inner { f1: ????5?????, f2: ????10???? }, f2: ???1.23??? }", 588 | format!("{:?^10.2?}", outer_3) 589 | ); 590 | assert_eq!( 591 | "F2 { f1: Inner { f1: 5#########, f2: 10######## }, f2: 1.23###### }", 592 | format!("{:#<10.2?}", outer_3) 593 | ); 594 | assert_eq!( 595 | "F2 {\n f1: Inner {\n f1: 5#########,\n f2: 10########,\n },\n f2: \ 596 | 1.23######,\n}", 597 | format!("{:#<#10.2?}", outer_3) 598 | ); 599 | } 600 | -------------------------------------------------------------------------------- /tests/enum_with_name.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Debug, Formatter}; 2 | 3 | #[test] 4 | #[allow(dead_code)] 5 | fn unit() { 6 | #[derive(Debug)] 7 | struct Inner { 8 | f1: u8, 9 | f2: u8, 10 | } 11 | 12 | enum Outer { 13 | F0, 14 | F1(f64, Inner), 15 | F2 { f1: f64, f2: Inner }, 16 | } 17 | 18 | impl Debug for Outer { 19 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 20 | debug_helper::impl_debug_for_enum!({Outer::F0, (F1(..)), {F2{..}}}, f, self); 21 | } 22 | } 23 | 24 | let outer_1 = Outer::F0; 25 | let outer_2 = Outer::F1(1.23456789, Inner { 26 | f1: 5, f2: 10 27 | }); 28 | let outer_3 = Outer::F2 { 29 | f1: 1.23456789, 30 | f2: Inner { 31 | f1: 5, f2: 10 32 | }, 33 | }; 34 | 35 | assert_eq!("Outer::F0", format!("{:?}", outer_1)); 36 | assert_eq!("Outer::F0", format!("{:#?}", outer_1)); 37 | assert_eq!("Outer::F0", format!("{:010.2?}", outer_1)); 38 | assert_eq!("Outer::F0", format!("{:0>10.2?}", outer_1)); 39 | assert_eq!("Outer::F0", format!("{:?^10.2?}", outer_1)); 40 | assert_eq!("Outer::F0", format!("{:#<10.2?}", outer_1)); 41 | assert_eq!("Outer::F0", format!("{:#<#10.2?}", outer_1)); 42 | 43 | assert_eq!("Outer::F1", format!("{:?}", outer_2)); 44 | assert_eq!("Outer::F1", format!("{:#?}", outer_2)); 45 | assert_eq!("Outer::F1", format!("{:010.2?}", outer_2)); 46 | assert_eq!("Outer::F1", format!("{:0>10.2?}", outer_2)); 47 | assert_eq!("Outer::F1", format!("{:?^10.2?}", outer_2)); 48 | assert_eq!("Outer::F1", format!("{:#<10.2?}", outer_2)); 49 | assert_eq!("Outer::F1", format!("{:#<#10.2?}", outer_2)); 50 | 51 | assert_eq!("Outer::F2", format!("{:?}", outer_3)); 52 | assert_eq!("Outer::F2", format!("{:#?}", outer_3)); 53 | assert_eq!("Outer::F2", format!("{:010.2?}", outer_3)); 54 | assert_eq!("Outer::F2", format!("{:0>10.2?}", outer_3)); 55 | assert_eq!("Outer::F2", format!("{:?^10.2?}", outer_3)); 56 | assert_eq!("Outer::F2", format!("{:#<10.2?}", outer_3)); 57 | assert_eq!("Outer::F2", format!("{:#<#10.2?}", outer_3)); 58 | } 59 | 60 | #[test] 61 | #[allow(dead_code)] 62 | fn unit_renamed() { 63 | #[derive(Debug)] 64 | struct Inner { 65 | f1: u8, 66 | f2: u8, 67 | } 68 | 69 | enum Outer { 70 | F0, 71 | F1(f64, Inner), 72 | F2 { f1: f64, f2: Inner }, 73 | } 74 | 75 | impl Debug for Outer { 76 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 77 | debug_helper::impl_debug_for_enum!({A::F0, (F1(..)), {F2{..}}}, f, self); 78 | } 79 | } 80 | 81 | let outer_1 = Outer::F0; 82 | let outer_2 = Outer::F1(1.23456789, Inner { 83 | f1: 5, f2: 10 84 | }); 85 | let outer_3 = Outer::F2 { 86 | f1: 1.23456789, 87 | f2: Inner { 88 | f1: 5, f2: 10 89 | }, 90 | }; 91 | 92 | assert_eq!("A::F0", format!("{:?}", outer_1)); 93 | assert_eq!("A::F0", format!("{:#?}", outer_1)); 94 | assert_eq!("A::F0", format!("{:010.2?}", outer_1)); 95 | assert_eq!("A::F0", format!("{:0>10.2?}", outer_1)); 96 | assert_eq!("A::F0", format!("{:?^10.2?}", outer_1)); 97 | assert_eq!("A::F0", format!("{:#<10.2?}", outer_1)); 98 | assert_eq!("A::F0", format!("{:#<#10.2?}", outer_1)); 99 | 100 | assert_eq!("A::F1", format!("{:?}", outer_2)); 101 | assert_eq!("A::F1", format!("{:#?}", outer_2)); 102 | assert_eq!("A::F1", format!("{:010.2?}", outer_2)); 103 | assert_eq!("A::F1", format!("{:0>10.2?}", outer_2)); 104 | assert_eq!("A::F1", format!("{:?^10.2?}", outer_2)); 105 | assert_eq!("A::F1", format!("{:#<10.2?}", outer_2)); 106 | assert_eq!("A::F1", format!("{:#<#10.2?}", outer_2)); 107 | 108 | assert_eq!("A::F2", format!("{:?}", outer_3)); 109 | assert_eq!("A::F2", format!("{:#?}", outer_3)); 110 | assert_eq!("A::F2", format!("{:010.2?}", outer_3)); 111 | assert_eq!("A::F2", format!("{:0>10.2?}", outer_3)); 112 | assert_eq!("A::F2", format!("{:?^10.2?}", outer_3)); 113 | assert_eq!("A::F2", format!("{:#<10.2?}", outer_3)); 114 | assert_eq!("A::F2", format!("{:#<#10.2?}", outer_3)); 115 | } 116 | 117 | #[test] 118 | #[allow(dead_code)] 119 | fn one_field_primitive() { 120 | #[derive(Debug)] 121 | struct Inner { 122 | f1: u8, 123 | f2: u8, 124 | } 125 | 126 | enum Outer { 127 | F0, 128 | F1(f64, Inner), 129 | F2 { f1: f64, f2: Inner }, 130 | } 131 | 132 | impl Debug for Outer { 133 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 134 | debug_helper::impl_debug_for_enum!({Outer::F0, (F1(f1, ..): (.f1)), {F2{f1, ..}: (.f1)}}, f, self); 135 | } 136 | } 137 | 138 | let outer_1 = Outer::F0; 139 | let outer_2 = Outer::F1(1.23456789, Inner { 140 | f1: 5, f2: 10 141 | }); 142 | let outer_3 = Outer::F2 { 143 | f1: 1.23456789, 144 | f2: Inner { 145 | f1: 5, f2: 10 146 | }, 147 | }; 148 | 149 | assert_eq!("Outer::F0", format!("{:?}", outer_1)); 150 | assert_eq!("Outer::F0", format!("{:#?}", outer_1)); 151 | assert_eq!("Outer::F0", format!("{:010.2?}", outer_1)); 152 | assert_eq!("Outer::F0", format!("{:0>10.2?}", outer_1)); 153 | assert_eq!("Outer::F0", format!("{:?^10.2?}", outer_1)); 154 | assert_eq!("Outer::F0", format!("{:#<10.2?}", outer_1)); 155 | assert_eq!("Outer::F0", format!("{:#<#10.2?}", outer_1)); 156 | 157 | assert_eq!("Outer::F1(1.23456789)", format!("{:?}", outer_2)); 158 | assert_eq!("Outer::F1(\n 1.23456789,\n)", format!("{:#?}", outer_2)); 159 | assert_eq!("Outer::F1(0000001.23)", format!("{:010.2?}", outer_2)); 160 | assert_eq!("Outer::F1(0000001.23)", format!("{:0>10.2?}", outer_2)); 161 | assert_eq!("Outer::F1(???1.23???)", format!("{:?^10.2?}", outer_2)); 162 | assert_eq!("Outer::F1(1.23######)", format!("{:#<10.2?}", outer_2)); 163 | assert_eq!("Outer::F1(\n 1.23######,\n)", format!("{:#<#10.2?}", outer_2)); 164 | 165 | assert_eq!("Outer::F2 { f1: 1.23456789 }", format!("{:?}", outer_3)); 166 | assert_eq!("Outer::F2 {\n f1: 1.23456789,\n}", format!("{:#?}", outer_3)); 167 | assert_eq!("Outer::F2 { f1: 0000001.23 }", format!("{:010.2?}", outer_3)); 168 | assert_eq!("Outer::F2 { f1: 0000001.23 }", format!("{:0>10.2?}", outer_3)); 169 | assert_eq!("Outer::F2 { f1: ???1.23??? }", format!("{:?^10.2?}", outer_3)); 170 | assert_eq!("Outer::F2 { f1: 1.23###### }", format!("{:#<10.2?}", outer_3)); 171 | assert_eq!("Outer::F2 {\n f1: 1.23######,\n}", format!("{:#<#10.2?}", outer_3)); 172 | } 173 | 174 | #[test] 175 | #[allow(dead_code)] 176 | fn one_field_nested() { 177 | #[derive(Debug)] 178 | struct Inner { 179 | f1: u8, 180 | f2: u8, 181 | } 182 | 183 | enum Outer { 184 | F0, 185 | F1(f64, Inner), 186 | F2 { f1: f64, f2: Inner }, 187 | } 188 | 189 | impl Debug for Outer { 190 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 191 | debug_helper::impl_debug_for_enum!({Outer::F0, (F1(_, f2): (.f2)), {F2{f1: _, f2}: (.f2)}}, f, self); 192 | } 193 | } 194 | 195 | let outer_1 = Outer::F0; 196 | let outer_2 = Outer::F1(1.23456789, Inner { 197 | f1: 5, f2: 10 198 | }); 199 | let outer_3 = Outer::F2 { 200 | f1: 1.23456789, 201 | f2: Inner { 202 | f1: 5, f2: 10 203 | }, 204 | }; 205 | 206 | assert_eq!("Outer::F0", format!("{:?}", outer_1)); 207 | assert_eq!("Outer::F0", format!("{:#?}", outer_1)); 208 | assert_eq!("Outer::F0", format!("{:010.2?}", outer_1)); 209 | assert_eq!("Outer::F0", format!("{:0>10.2?}", outer_1)); 210 | assert_eq!("Outer::F0", format!("{:?^10.2?}", outer_1)); 211 | assert_eq!("Outer::F0", format!("{:#<10.2?}", outer_1)); 212 | assert_eq!("Outer::F0", format!("{:#<#10.2?}", outer_1)); 213 | 214 | assert_eq!("Outer::F1(Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 215 | assert_eq!( 216 | "Outer::F1(\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 217 | format!("{:#?}", outer_2) 218 | ); 219 | assert_eq!( 220 | "Outer::F1(Inner { f1: 0000000005, f2: 0000000010 })", 221 | format!("{:010.2?}", outer_2) 222 | ); 223 | assert_eq!( 224 | "Outer::F1(Inner { f1: 0000000005, f2: 0000000010 })", 225 | format!("{:0>10.2?}", outer_2) 226 | ); 227 | assert_eq!( 228 | "Outer::F1(Inner { f1: ????5?????, f2: ????10???? })", 229 | format!("{:?^10.2?}", outer_2) 230 | ); 231 | assert_eq!( 232 | "Outer::F1(Inner { f1: 5#########, f2: 10######## })", 233 | format!("{:#<10.2?}", outer_2) 234 | ); 235 | assert_eq!( 236 | "Outer::F1(\n Inner {\n f1: 5#########,\n f2: 10########,\n },\n)", 237 | format!("{:#<#10.2?}", outer_2) 238 | ); 239 | 240 | assert_eq!("Outer::F2 { f2: Inner { f1: 5, f2: 10 } }", format!("{:?}", outer_3)); 241 | assert_eq!( 242 | "Outer::F2 {\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n}", 243 | format!("{:#?}", outer_3) 244 | ); 245 | assert_eq!( 246 | "Outer::F2 { f2: Inner { f1: 0000000005, f2: 0000000010 } }", 247 | format!("{:010.2?}", outer_3) 248 | ); 249 | assert_eq!( 250 | "Outer::F2 { f2: Inner { f1: 0000000005, f2: 0000000010 } }", 251 | format!("{:0>10.2?}", outer_3) 252 | ); 253 | assert_eq!( 254 | "Outer::F2 { f2: Inner { f1: ????5?????, f2: ????10???? } }", 255 | format!("{:?^10.2?}", outer_3) 256 | ); 257 | assert_eq!( 258 | "Outer::F2 { f2: Inner { f1: 5#########, f2: 10######## } }", 259 | format!("{:#<10.2?}", outer_3) 260 | ); 261 | assert_eq!( 262 | "Outer::F2 {\n f2: Inner {\n f1: 5#########,\n f2: 10########,\n },\n}", 263 | format!("{:#<#10.2?}", outer_3) 264 | ); 265 | } 266 | 267 | #[test] 268 | #[allow(dead_code)] 269 | fn all() { 270 | #[derive(Debug)] 271 | struct Inner { 272 | f1: u8, 273 | f2: u8, 274 | } 275 | 276 | enum Outer { 277 | F0, 278 | F1(f64, Inner), 279 | F2 { f1: f64, f2: Inner }, 280 | } 281 | 282 | impl Debug for Outer { 283 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 284 | debug_helper::impl_debug_for_enum!({Outer::F0, (F1(f1, f2): (.f1, .f2)), {F2{f1, f2}: (.f1, .f2)}}, f, self); 285 | } 286 | } 287 | 288 | let outer_1 = Outer::F0; 289 | let outer_2 = Outer::F1(1.23456789, Inner { 290 | f1: 5, f2: 10 291 | }); 292 | let outer_3 = Outer::F2 { 293 | f1: 1.23456789, 294 | f2: Inner { 295 | f1: 5, f2: 10 296 | }, 297 | }; 298 | 299 | assert_eq!("Outer::F0", format!("{:?}", outer_1)); 300 | assert_eq!("Outer::F0", format!("{:#?}", outer_1)); 301 | assert_eq!("Outer::F0", format!("{:010.2?}", outer_1)); 302 | assert_eq!("Outer::F0", format!("{:0>10.2?}", outer_1)); 303 | assert_eq!("Outer::F0", format!("{:?^10.2?}", outer_1)); 304 | assert_eq!("Outer::F0", format!("{:#<10.2?}", outer_1)); 305 | assert_eq!("Outer::F0", format!("{:#<#10.2?}", outer_1)); 306 | 307 | assert_eq!("Outer::F1(1.23456789, Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 308 | assert_eq!( 309 | "Outer::F1(\n 1.23456789,\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 310 | format!("{:#?}", outer_2) 311 | ); 312 | assert_eq!( 313 | "Outer::F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 314 | format!("{:010.2?}", outer_2) 315 | ); 316 | assert_eq!( 317 | "Outer::F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 318 | format!("{:0>10.2?}", outer_2) 319 | ); 320 | assert_eq!( 321 | "Outer::F1(???1.23???, Inner { f1: ????5?????, f2: ????10???? })", 322 | format!("{:?^10.2?}", outer_2) 323 | ); 324 | assert_eq!( 325 | "Outer::F1(1.23######, Inner { f1: 5#########, f2: 10######## })", 326 | format!("{:#<10.2?}", outer_2) 327 | ); 328 | assert_eq!( 329 | "Outer::F1(\n 1.23######,\n Inner {\n f1: 5#########,\n f2: \ 330 | 10########,\n },\n)", 331 | format!("{:#<#10.2?}", outer_2) 332 | ); 333 | 334 | assert_eq!( 335 | "Outer::F2 { f1: 1.23456789, f2: Inner { f1: 5, f2: 10 } }", 336 | format!("{:?}", outer_3) 337 | ); 338 | assert_eq!( 339 | "Outer::F2 {\n f1: 1.23456789,\n f2: Inner {\n f1: 5,\n f2: 10,\n \ 340 | },\n}", 341 | format!("{:#?}", outer_3) 342 | ); 343 | assert_eq!( 344 | "Outer::F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 345 | format!("{:010.2?}", outer_3) 346 | ); 347 | assert_eq!( 348 | "Outer::F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 349 | format!("{:0>10.2?}", outer_3) 350 | ); 351 | assert_eq!( 352 | "Outer::F2 { f1: ???1.23???, f2: Inner { f1: ????5?????, f2: ????10???? } }", 353 | format!("{:?^10.2?}", outer_3) 354 | ); 355 | assert_eq!( 356 | "Outer::F2 { f1: 1.23######, f2: Inner { f1: 5#########, f2: 10######## } }", 357 | format!("{:#<10.2?}", outer_3) 358 | ); 359 | assert_eq!( 360 | "Outer::F2 {\n f1: 1.23######,\n f2: Inner {\n f1: 5#########,\n f2: \ 361 | 10########,\n },\n}", 362 | format!("{:#<#10.2?}", outer_3) 363 | ); 364 | } 365 | 366 | #[test] 367 | #[allow(dead_code)] 368 | fn all_renamed() { 369 | #[derive(Debug)] 370 | struct Inner { 371 | f1: u8, 372 | f2: u8, 373 | } 374 | 375 | enum Outer { 376 | F0, 377 | F1(f64, Inner), 378 | F2 { f1: f64, f2: Inner }, 379 | } 380 | 381 | impl Debug for Outer { 382 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 383 | debug_helper::impl_debug_for_enum!({A::F0, (F1(f1, f2): (.f1, .f2)), {F2{f1, f2}: (.f1, .f2)}}, f, self); 384 | } 385 | } 386 | 387 | let outer_1 = Outer::F0; 388 | let outer_2 = Outer::F1(1.23456789, Inner { 389 | f1: 5, f2: 10 390 | }); 391 | let outer_3 = Outer::F2 { 392 | f1: 1.23456789, 393 | f2: Inner { 394 | f1: 5, f2: 10 395 | }, 396 | }; 397 | 398 | assert_eq!("A::F0", format!("{:?}", outer_1)); 399 | assert_eq!("A::F0", format!("{:#?}", outer_1)); 400 | assert_eq!("A::F0", format!("{:010.2?}", outer_1)); 401 | assert_eq!("A::F0", format!("{:0>10.2?}", outer_1)); 402 | assert_eq!("A::F0", format!("{:?^10.2?}", outer_1)); 403 | assert_eq!("A::F0", format!("{:#<10.2?}", outer_1)); 404 | assert_eq!("A::F0", format!("{:#<#10.2?}", outer_1)); 405 | 406 | assert_eq!("A::F1(1.23456789, Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 407 | assert_eq!( 408 | "A::F1(\n 1.23456789,\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 409 | format!("{:#?}", outer_2) 410 | ); 411 | assert_eq!( 412 | "A::F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 413 | format!("{:010.2?}", outer_2) 414 | ); 415 | assert_eq!( 416 | "A::F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 417 | format!("{:0>10.2?}", outer_2) 418 | ); 419 | assert_eq!( 420 | "A::F1(???1.23???, Inner { f1: ????5?????, f2: ????10???? })", 421 | format!("{:?^10.2?}", outer_2) 422 | ); 423 | assert_eq!( 424 | "A::F1(1.23######, Inner { f1: 5#########, f2: 10######## })", 425 | format!("{:#<10.2?}", outer_2) 426 | ); 427 | assert_eq!("A::F1(\n 1.23######,\n Inner {\n f1: 5#########,\n f2: 10########,\n },\n)", format!("{:#<#10.2?}", outer_2)); 428 | 429 | assert_eq!("A::F2 { f1: 1.23456789, f2: Inner { f1: 5, f2: 10 } }", format!("{:?}", outer_3)); 430 | assert_eq!( 431 | "A::F2 {\n f1: 1.23456789,\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n}", 432 | format!("{:#?}", outer_3) 433 | ); 434 | assert_eq!( 435 | "A::F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 436 | format!("{:010.2?}", outer_3) 437 | ); 438 | assert_eq!( 439 | "A::F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 440 | format!("{:0>10.2?}", outer_3) 441 | ); 442 | assert_eq!( 443 | "A::F2 { f1: ???1.23???, f2: Inner { f1: ????5?????, f2: ????10???? } }", 444 | format!("{:?^10.2?}", outer_3) 445 | ); 446 | assert_eq!( 447 | "A::F2 { f1: 1.23######, f2: Inner { f1: 5#########, f2: 10######## } }", 448 | format!("{:#<10.2?}", outer_3) 449 | ); 450 | assert_eq!( 451 | "A::F2 {\n f1: 1.23######,\n f2: Inner {\n f1: 5#########,\n f2: \ 452 | 10########,\n },\n}", 453 | format!("{:#<#10.2?}", outer_3) 454 | ); 455 | } 456 | 457 | #[test] 458 | #[allow(dead_code)] 459 | fn custom_fmt() { 460 | #[derive(Debug)] 461 | struct Inner { 462 | f1: u8, 463 | f2: u8, 464 | } 465 | 466 | struct Intruder { 467 | s: &'static str, 468 | } 469 | 470 | enum Outer { 471 | F0, 472 | F1(f64, Inner), 473 | F2 { f1: f64, f2: Inner }, 474 | F3(Intruder), 475 | } 476 | 477 | impl Debug for Outer { 478 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 479 | debug_helper::impl_debug_for_enum!({Outer::F0, (F1(_f1, f2): ((._f1, "number"), .f2)), {F2{f1: _, f2}: ((.f1, "number"), .f2)}, (F3(f3): ((.f3, "{}", f3.s)))}, f, self); 480 | } 481 | } 482 | 483 | let outer_1 = Outer::F0; 484 | let outer_2 = Outer::F1(1.23456789, Inner { 485 | f1: 5, f2: 10 486 | }); 487 | let outer_3 = Outer::F2 { 488 | f1: 1.23456789, 489 | f2: Inner { 490 | f1: 5, f2: 10 491 | }, 492 | }; 493 | let outer_4 = Outer::F3(Intruder { 494 | s: "Hi" 495 | }); 496 | 497 | assert_eq!("Outer::F0", format!("{:?}", outer_1)); 498 | assert_eq!("Outer::F0", format!("{:#?}", outer_1)); 499 | assert_eq!("Outer::F0", format!("{:010.2?}", outer_1)); 500 | assert_eq!("Outer::F0", format!("{:0>10.2?}", outer_1)); 501 | assert_eq!("Outer::F0", format!("{:?^10.2?}", outer_1)); 502 | assert_eq!("Outer::F0", format!("{:#<10.2?}", outer_1)); 503 | assert_eq!("Outer::F0", format!("{:#<#10.2?}", outer_1)); 504 | 505 | assert_eq!("Outer::F1(number, Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 506 | assert_eq!( 507 | "Outer::F1(\n number,\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 508 | format!("{:#?}", outer_2) 509 | ); 510 | assert_eq!( 511 | "Outer::F1(number, Inner { f1: 0000000005, f2: 0000000010 })", 512 | format!("{:010.2?}", outer_2) 513 | ); 514 | assert_eq!( 515 | "Outer::F1(number, Inner { f1: 0000000005, f2: 0000000010 })", 516 | format!("{:0>10.2?}", outer_2) 517 | ); 518 | assert_eq!( 519 | "Outer::F1(number, Inner { f1: ????5?????, f2: ????10???? })", 520 | format!("{:?^10.2?}", outer_2) 521 | ); 522 | assert_eq!( 523 | "Outer::F1(number, Inner { f1: 5#########, f2: 10######## })", 524 | format!("{:#<10.2?}", outer_2) 525 | ); 526 | assert_eq!("Outer::F1(\n number,\n Inner {\n f1: 5#########,\n f2: 10########,\n },\n)", format!("{:#<#10.2?}", outer_2)); 527 | 528 | assert_eq!("Outer::F2 { f1: number, f2: Inner { f1: 5, f2: 10 } }", format!("{:?}", outer_3)); 529 | assert_eq!( 530 | "Outer::F2 {\n f1: number,\n f2: Inner {\n f1: 5,\n f2: 10,\n },\n}", 531 | format!("{:#?}", outer_3) 532 | ); 533 | assert_eq!( 534 | "Outer::F2 { f1: number, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 535 | format!("{:010.2?}", outer_3) 536 | ); 537 | assert_eq!( 538 | "Outer::F2 { f1: number, f2: Inner { f1: 0000000005, f2: 0000000010 } }", 539 | format!("{:0>10.2?}", outer_3) 540 | ); 541 | assert_eq!( 542 | "Outer::F2 { f1: number, f2: Inner { f1: ????5?????, f2: ????10???? } }", 543 | format!("{:?^10.2?}", outer_3) 544 | ); 545 | assert_eq!( 546 | "Outer::F2 { f1: number, f2: Inner { f1: 5#########, f2: 10######## } }", 547 | format!("{:#<10.2?}", outer_3) 548 | ); 549 | assert_eq!( 550 | "Outer::F2 {\n f1: number,\n f2: Inner {\n f1: 5#########,\n f2: \ 551 | 10########,\n },\n}", 552 | format!("{:#<#10.2?}", outer_3) 553 | ); 554 | 555 | assert_eq!("Outer::F3(Hi)", format!("{:?}", outer_4)); 556 | assert_eq!("Outer::F3(\n Hi,\n)", format!("{:#?}", outer_4)); 557 | assert_eq!("Outer::F3(Hi)", format!("{:010.2?}", outer_4)); 558 | assert_eq!("Outer::F3(Hi)", format!("{:0>10.2?}", outer_4)); 559 | assert_eq!("Outer::F3(Hi)", format!("{:?^10.2?}", outer_4)); 560 | assert_eq!("Outer::F3(Hi)", format!("{:#<10.2?}", outer_4)); 561 | assert_eq!("Outer::F3(\n Hi,\n)", format!("{:#<#10.2?}", outer_4)); 562 | } 563 | 564 | #[test] 565 | #[allow(dead_code)] 566 | fn additional_fields() { 567 | #[derive(Debug)] 568 | struct Inner { 569 | f1: u8, 570 | f2: u8, 571 | } 572 | 573 | enum Outer { 574 | F0, 575 | F1(f64, Inner), 576 | F2 { f1: f64, f2: Inner }, 577 | } 578 | 579 | impl Debug for Outer { 580 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 581 | debug_helper::impl_debug_for_enum!({Outer::F0, (F1(f1, f2): (.f1, .f2)), {F2{f1, f2}: (.f1, .f2, (.f3, "Hi"))}}, f, self); 582 | } 583 | } 584 | 585 | let outer_1 = Outer::F0; 586 | let outer_2 = Outer::F1(1.23456789, Inner { 587 | f1: 5, f2: 10 588 | }); 589 | let outer_3 = Outer::F2 { 590 | f1: 1.23456789, 591 | f2: Inner { 592 | f1: 5, f2: 10 593 | }, 594 | }; 595 | 596 | assert_eq!("Outer::F0", format!("{:?}", outer_1)); 597 | assert_eq!("Outer::F0", format!("{:#?}", outer_1)); 598 | assert_eq!("Outer::F0", format!("{:010.2?}", outer_1)); 599 | assert_eq!("Outer::F0", format!("{:0>10.2?}", outer_1)); 600 | assert_eq!("Outer::F0", format!("{:?^10.2?}", outer_1)); 601 | assert_eq!("Outer::F0", format!("{:#<10.2?}", outer_1)); 602 | assert_eq!("Outer::F0", format!("{:#<#10.2?}", outer_1)); 603 | 604 | assert_eq!("Outer::F1(1.23456789, Inner { f1: 5, f2: 10 })", format!("{:?}", outer_2)); 605 | assert_eq!( 606 | "Outer::F1(\n 1.23456789,\n Inner {\n f1: 5,\n f2: 10,\n },\n)", 607 | format!("{:#?}", outer_2) 608 | ); 609 | assert_eq!( 610 | "Outer::F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 611 | format!("{:010.2?}", outer_2) 612 | ); 613 | assert_eq!( 614 | "Outer::F1(0000001.23, Inner { f1: 0000000005, f2: 0000000010 })", 615 | format!("{:0>10.2?}", outer_2) 616 | ); 617 | assert_eq!( 618 | "Outer::F1(???1.23???, Inner { f1: ????5?????, f2: ????10???? })", 619 | format!("{:?^10.2?}", outer_2) 620 | ); 621 | assert_eq!( 622 | "Outer::F1(1.23######, Inner { f1: 5#########, f2: 10######## })", 623 | format!("{:#<10.2?}", outer_2) 624 | ); 625 | assert_eq!( 626 | "Outer::F1(\n 1.23######,\n Inner {\n f1: 5#########,\n f2: \ 627 | 10########,\n },\n)", 628 | format!("{:#<#10.2?}", outer_2) 629 | ); 630 | 631 | assert_eq!( 632 | "Outer::F2 { f1: 1.23456789, f2: Inner { f1: 5, f2: 10 }, f3: Hi }", 633 | format!("{:?}", outer_3) 634 | ); 635 | assert_eq!( 636 | "Outer::F2 {\n f1: 1.23456789,\n f2: Inner {\n f1: 5,\n f2: 10,\n \ 637 | },\n f3: Hi,\n}", 638 | format!("{:#?}", outer_3) 639 | ); 640 | assert_eq!( 641 | "Outer::F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 }, f3: Hi }", 642 | format!("{:010.2?}", outer_3) 643 | ); 644 | assert_eq!( 645 | "Outer::F2 { f1: 0000001.23, f2: Inner { f1: 0000000005, f2: 0000000010 }, f3: Hi }", 646 | format!("{:0>10.2?}", outer_3) 647 | ); 648 | assert_eq!( 649 | "Outer::F2 { f1: ???1.23???, f2: Inner { f1: ????5?????, f2: ????10???? }, f3: Hi }", 650 | format!("{:?^10.2?}", outer_3) 651 | ); 652 | assert_eq!( 653 | "Outer::F2 { f1: 1.23######, f2: Inner { f1: 5#########, f2: 10######## }, f3: Hi }", 654 | format!("{:#<10.2?}", outer_3) 655 | ); 656 | assert_eq!( 657 | "Outer::F2 {\n f1: 1.23######,\n f2: Inner {\n f1: 5#########,\n f2: \ 658 | 10########,\n },\n f3: Hi,\n}", 659 | format!("{:#<#10.2?}", outer_3) 660 | ); 661 | } 662 | 663 | #[test] 664 | #[allow(dead_code)] 665 | fn reset() { 666 | #[derive(Debug)] 667 | struct Inner { 668 | f1: u8, 669 | f2: u8, 670 | } 671 | 672 | enum Outer { 673 | F0, 674 | F1(f64, Inner), 675 | F2 { f1: f64, f2: Inner }, 676 | } 677 | 678 | impl Debug for Outer { 679 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 680 | debug_helper::impl_debug_for_enum!({Outer::F0, (F1(f1, f2): (let .f1 = f2, let .f2 = f1)), {F2{f1, f2}: (let .f1 = f2, let .f2 = f1)}}, f, self); 681 | } 682 | } 683 | 684 | let outer_1 = Outer::F0; 685 | let outer_2 = Outer::F1(1.23456789, Inner { 686 | f1: 5, f2: 10 687 | }); 688 | let outer_3 = Outer::F2 { 689 | f1: 1.23456789, 690 | f2: Inner { 691 | f1: 5, f2: 10 692 | }, 693 | }; 694 | 695 | assert_eq!("Outer::F0", format!("{:?}", outer_1)); 696 | assert_eq!("Outer::F0", format!("{:#?}", outer_1)); 697 | assert_eq!("Outer::F0", format!("{:010.2?}", outer_1)); 698 | assert_eq!("Outer::F0", format!("{:0>10.2?}", outer_1)); 699 | assert_eq!("Outer::F0", format!("{:?^10.2?}", outer_1)); 700 | assert_eq!("Outer::F0", format!("{:#<10.2?}", outer_1)); 701 | assert_eq!("Outer::F0", format!("{:#<#10.2?}", outer_1)); 702 | 703 | assert_eq!("Outer::F1(Inner { f1: 5, f2: 10 }, 1.23456789)", format!("{:?}", outer_2)); 704 | assert_eq!( 705 | "Outer::F1(\n Inner {\n f1: 5,\n f2: 10,\n },\n 1.23456789,\n)", 706 | format!("{:#?}", outer_2) 707 | ); 708 | assert_eq!( 709 | "Outer::F1(Inner { f1: 0000000005, f2: 0000000010 }, 0000001.23)", 710 | format!("{:010.2?}", outer_2) 711 | ); 712 | assert_eq!( 713 | "Outer::F1(Inner { f1: 0000000005, f2: 0000000010 }, 0000001.23)", 714 | format!("{:0>10.2?}", outer_2) 715 | ); 716 | assert_eq!( 717 | "Outer::F1(Inner { f1: ????5?????, f2: ????10???? }, ???1.23???)", 718 | format!("{:?^10.2?}", outer_2) 719 | ); 720 | assert_eq!( 721 | "Outer::F1(Inner { f1: 5#########, f2: 10######## }, 1.23######)", 722 | format!("{:#<10.2?}", outer_2) 723 | ); 724 | assert_eq!( 725 | "Outer::F1(\n Inner {\n f1: 5#########,\n f2: 10########,\n },\n \ 726 | 1.23######,\n)", 727 | format!("{:#<#10.2?}", outer_2) 728 | ); 729 | 730 | assert_eq!( 731 | "Outer::F2 { f1: Inner { f1: 5, f2: 10 }, f2: 1.23456789 }", 732 | format!("{:?}", outer_3) 733 | ); 734 | assert_eq!( 735 | "Outer::F2 {\n f1: Inner {\n f1: 5,\n f2: 10,\n },\n f2: \ 736 | 1.23456789,\n}", 737 | format!("{:#?}", outer_3) 738 | ); 739 | assert_eq!( 740 | "Outer::F2 { f1: Inner { f1: 0000000005, f2: 0000000010 }, f2: 0000001.23 }", 741 | format!("{:010.2?}", outer_3) 742 | ); 743 | assert_eq!( 744 | "Outer::F2 { f1: Inner { f1: 0000000005, f2: 0000000010 }, f2: 0000001.23 }", 745 | format!("{:0>10.2?}", outer_3) 746 | ); 747 | assert_eq!( 748 | "Outer::F2 { f1: Inner { f1: ????5?????, f2: ????10???? }, f2: ???1.23??? }", 749 | format!("{:?^10.2?}", outer_3) 750 | ); 751 | assert_eq!( 752 | "Outer::F2 { f1: Inner { f1: 5#########, f2: 10######## }, f2: 1.23###### }", 753 | format!("{:#<10.2?}", outer_3) 754 | ); 755 | assert_eq!("Outer::F2 {\n f1: Inner {\n f1: 5#########,\n f2: 10########,\n },\n f2: 1.23######,\n}", format!("{:#<#10.2?}", outer_3)); 756 | } 757 | --------------------------------------------------------------------------------